diff --git a/.gitignore b/.gitignore
index 0048d5f58..1741710c6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -59,6 +59,9 @@ blsbench.*
runbench
runtest
+runtest.log
+runtest.trs
+test-suite.log
**/.DS_Store
diff --git a/CMakeLists.txt b/CMakeLists.txt
index df0abe13f..20b6d87fe 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,8 +8,8 @@ ENDIF()
project(BLS)
-set(BUILD_BLS_TESTS 1 CACHE INTEGER "")
-set(BUILD_BLS_BENCHMARKS 1 CACHE INTEGER "")
+set(BUILD_BLS_TESTS "1" CACHE STRING "")
+set(BUILD_BLS_BENCHMARKS "1" CACHE STRING "")
message(STATUS "Build tests: ${BUILD_BLS_TESTS}")
message(STATUS "Build benchmarks: ${BUILD_BLS_BENCHMARKS}")
@@ -41,9 +41,9 @@ if(EMSCRIPTEN)
# emscripten needs arch set to be none since it can't compile assembly
set(ARCH "" CACHE STRING "")
# emscripten is a 32 bit compiler
- set(WSIZE 32 CACHE INTEGER "")
+ set(WSIZE "32" CACHE STRING "Relic - Processor word size")
else()
- set(WSIZE 64 CACHE INTEGER "")
+ set(WSIZE "64" CACHE STRING "Relic - Processor word size")
endif()
set(TIMER "CYCLE" CACHE STRING "")
@@ -54,7 +54,7 @@ set(SHLIB "OFF" CACHE STRING "")
set(MULTI "PTHREAD" CACHE STRING "")
set(DOCUM "off" CACHE STRING "")
-set(FP_PRIME 381 CACHE INTEGER "")
+set(FP_PRIME "381" CACHE STRING "Relic - Prime modulus size")
IF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(SEED "UDEV" CACHE STRING "")
@@ -68,16 +68,16 @@ ELSE()
ENDIF()
set(STBIN "OFF" CACHE STRING "")
-set(FP_METHD "INTEG;INTEG;INTEG;MONTY;LOWER;SLIDE" CACHE STRING "")
+set(FP_METHD "INTEG;INTEG;INTEG;MONTY;LOWER;LOWER;SLIDE" CACHE STRING "")
set(CFLAGS "-O3 -funroll-loops -fomit-frame-pointer" CACHE STRING "")
set(FP_PMERS "off" CACHE STRING "")
set(FPX_METHD "INTEG;INTEG;LAZYR" CACHE STRING "")
set(EP_PLAIN "off" CACHE STRING "")
set(EP_SUPER "off" CACHE STRING "")
# Disable relic tests and benchmarks
-set(TESTS 0 CACHE INTEGER "")
-set(BENCH 0 CACHE INTEGER "")
-set(QUIET 1 CACHE INTEGER "")
+set(TESTS "0" CACHE STRING "Relic - Number of times each test is ran")
+set(BENCH "0" CACHE STRING "Relic - Number of times each benchmark is ran")
+set(QUIET "on" CACHE STRING "Relic - Build with printing disabled")
set(PP_EXT "LAZYR" CACHE STRING "")
set(PP_METHD "LAZYR;OATEP" CACHE STRING "")
diff --git a/Makefile.am b/Makefile.am
index f43e6527f..2f4f2045d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,6 +1,7 @@
ACLOCAL_AMFLAGS = -I build-aux/m4
AM_CPPFLAGS = $(SODIUM_CPPFLAGS) $(SODIUM_CFLAGS)
+AM_CXXFLAGS = $(WARN_CXXFLAGS) $(NOWARN_CXXFLAGS)
AM_LDFLAGS = $(PTHREAD_CFLAGS) $(LIBTOOL_LDFLAGS)
LIBRELIC = librelic.la
@@ -92,7 +93,8 @@ FP_SRCS = \
contrib/relic/src/fp/relic_fp_shift.c \
contrib/relic/src/fp/relic_fp_sqr.c \
contrib/relic/src/fp/relic_fp_srt.c \
- contrib/relic/src/fp/relic_fp_util.c
+ contrib/relic/src/fp/relic_fp_util.c \
+ contrib/relic/src/fp/relic_fp_smb.c
FPX_SRCS = \
contrib/relic/src/fpx/relic_fp2_mul.c \
@@ -176,7 +178,20 @@ EPX_SRCS = \
contrib/relic/src/epx/relic_ep2_neg.c \
contrib/relic/src/epx/relic_ep2_norm.c \
contrib/relic/src/epx/relic_ep2_pck.c \
- contrib/relic/src/epx/relic_ep2_util.c
+ contrib/relic/src/epx/relic_ep2_util.c \
+ contrib/relic/src/epx/relic_ep4_add.c \
+ contrib/relic/src/epx/relic_ep4_cmp.c \
+ contrib/relic/src/epx/relic_ep4_curve.c \
+ contrib/relic/src/epx/relic_ep4_dbl.c \
+ contrib/relic/src/epx/relic_ep4_frb.c \
+ contrib/relic/src/epx/relic_ep4_map.c \
+ contrib/relic/src/epx/relic_ep4_mul.c \
+ contrib/relic/src/epx/relic_ep4_mul_cof.c \
+ contrib/relic/src/epx/relic_ep4_mul_fix.c \
+ contrib/relic/src/epx/relic_ep4_mul_sim.c \
+ contrib/relic/src/epx/relic_ep4_neg.c \
+ contrib/relic/src/epx/relic_ep4_norm.c \
+ contrib/relic/src/epx/relic_ep4_util.c
EB_SRCS = \
contrib/relic/src/eb/relic_eb_add.c \
@@ -232,7 +247,11 @@ PP_SRCS = \
contrib/relic/src/pp/relic_pp_map_k12.c \
contrib/relic/src/pp/relic_pp_map_k48.c \
contrib/relic/src/pp/relic_pp_map_k54.c \
- contrib/relic/src/pp/relic_pp_norm.c
+ contrib/relic/src/pp/relic_pp_norm.c \
+ contrib/relic/src/pp/relic_pp_add_k24.c \
+ contrib/relic/src/pp/relic_pp_dbl_k24.c \
+ contrib/relic/src/pp/relic_pp_exp_k24.c \
+ contrib/relic/src/pp/relic_pp_map_k24.c
PC_SRCS = \
contrib/relic/src/pc/relic_pc_core.c \
@@ -290,6 +309,7 @@ RELIC_SRCS += contrib/relic/src/low/gmp/relic_fp_mul_low.c
RELIC_SRCS += contrib/relic/src/low/gmp/relic_fp_rdc_low.c
RELIC_SRCS += contrib/relic/src/low/gmp/relic_fp_shift_low.c
RELIC_SRCS += contrib/relic/src/low/gmp/relic_fp_sqr_low.c
+RELIC_SRCS += contrib/relic/src/low/easy/relic_fp_smb_low.c
endif
if WITH_FPX
@@ -368,6 +388,13 @@ RELIC_SRCS += contrib/relic/src/cp/relic_cp_bbs.c
RELIC_SRCS += contrib/relic/src/cp/relic_cp_zss.c
RELIC_SRCS += contrib/relic/src/cp/relic_cp_cmlhs.c
RELIC_SRCS += contrib/relic/src/cp/relic_cp_mklhs.c
+RELIC_SRCS += contrib/relic/src/cp/relic_cp_ers.c
+RELIC_SRCS += contrib/relic/src/cp/relic_cp_etrs.c
+RELIC_SRCS += contrib/relic/src/cp/relic_cp_lapsi.c
+RELIC_SRCS += contrib/relic/src/cp/relic_cp_pcdel.c
+RELIC_SRCS += contrib/relic/src/cp/relic_cp_pok.c
+RELIC_SRCS += contrib/relic/src/cp/relic_cp_smlers.c
+RELIC_SRCS += contrib/relic/src/cp/relic_cp_sok.c
endif
if WITH_BC
diff --git a/configure.ac b/configure.ac
index a8ac63456..fa6b2aab7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -52,19 +52,19 @@ AX_CXX_COMPILE_STDCXX([14], [noext], [mandatory], [nodefault])
dnl Libtool init checks.
LT_INIT([pic-only])
-AC_PATH_TOOL(AR, ar)
-AC_PATH_TOOL(RANLIB, ranlib)
-AC_PATH_TOOL(STRIP, strip)
+AC_PATH_TOOL([AR], [ar])
+AC_PATH_TOOL([RANLIB], [ranlib])
+AC_PATH_TOOL([STRIP], [strip])
AM_PROG_AS
AC_ARG_ENABLE(tests,
- AS_HELP_STRING([--disable-tests],[do not compile tests (default is to compile)]),
+ AS_HELP_STRING([--disable-tests], [do not compile tests (default is to compile)]),
[use_tests=$enableval],
[use_tests=yes])
AC_ARG_ENABLE(bench,
- AS_HELP_STRING([--disable-bench],[do not compile benchmarks (default is to compile)]),
+ AS_HELP_STRING([--disable-bench], [do not compile benchmarks (default is to compile)]),
[use_bench=$enableval],
[use_bench=yes])
@@ -172,7 +172,7 @@ case $host in
AC_DEFINE([FP_QNRES], [], [Use -1 as quadratic non-residue.])
AC_DEFINE([OPSYS], [MACOSX], [Detected operation system.])
if test x$cross_compiling != xyes; then
- AC_PATH_PROG([BREW],brew,)
+ AC_PATH_PROG([BREW], [brew], [])
if test x$BREW != x; then
dnl These Homebrew packages may be keg-only, meaning that they won't be found
dnl in expected paths because they may conflict with system files. Ask
@@ -239,11 +239,11 @@ case $host in
esac
if test x$use_pkgconfig = xyes; then
- m4_ifndef([PKG_PROG_PKG_CONFIG], [AC_MSG_ERROR(PKG_PROG_PKG_CONFIG macro not found. Please install pkg-config and re-run autogen.sh.)])
+ m4_ifndef([PKG_PROG_PKG_CONFIG], [AC_MSG_ERROR([PKG_PROG_PKG_CONFIG macro not found. Please install pkg-config and re-run autogen.sh.])])
m4_ifdef([PKG_PROG_PKG_CONFIG], [
PKG_PROG_PKG_CONFIG
if test x"$PKG_CONFIG" = "x"; then
- AC_MSG_ERROR(pkg-config not found.)
+ AC_MSG_ERROR([pkg-config not found.])
fi
])
fi
@@ -266,139 +266,154 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])],
CFLAGS="$saved_CFLAGS"
])
+if test "x$CXXFLAGS_overridden" = "xno"; then
+ AC_LANG_PUSH([C++])
+ AX_CHECK_COMPILE_FLAG([-Wall], [WARN_CXXFLAGS="$WARN_CXXFLAGS -Wall"], [], [])
+ AX_CHECK_COMPILE_FLAG([-Wextra], [WARN_CXXFLAGS="$WARN_CXXFLAGS -Wextra"], [], [])
+ AX_CHECK_COMPILE_FLAG([-Wcast-align], [WARN_CXXFLAGS="$WARN_CXXFLAGS -Wcast-align"], [], [])
+ AX_CHECK_COMPILE_FLAG([-Wredundant-decls], [WARN_CXXFLAGS="$WARN_CXXFLAGS -Wredundant-decls"], [], [])
+ AX_CHECK_COMPILE_FLAG([-Wformat -Wformat-security], [WARN_CXXFLAGS="$WARN_CXXFLAGS -Wformat -Wformat-security"], [], [])
+ AX_CHECK_COMPILE_FLAG([-Wthread-safety-analysis], [WARN_CXXFLAGS="$WARN_CXXFLAGS -Wthread-safety-analysis"], [], [])
+ AX_CHECK_COMPILE_FLAG([-Wrange-loop-analysis], [WARN_CXXFLAGS="$WARN_CXXFLAGS -Wrange-loop-analysis"], [], [])
+
+ AX_CHECK_COMPILE_FLAG([-Wunused-parameter], [NOWARN_CXXFLAGS="$NOWARN_CXXFLAGS -Wno-unused-parameter"], [], [])
+ AX_CHECK_COMPILE_FLAG([-Wvla], [NOWARN_CXXFLAGS="$NOWARN_CXXFLAGS -Wno-vla"], [], [])
+ AC_LANG_POP([C++])
+fi
+
AC_LANG_PUSH([C])
-AX_CHECK_COMPILE_FLAG([-Wall],[WARN_CFLAGS="$WARN_CFLAGS -Wall"],,)
-AX_CHECK_COMPILE_FLAG([-Wextra],[WARN_CFLAGS="$WARN_CFLAGS -Wextra"],,)
-AX_CHECK_COMPILE_FLAG([-Wcast-align],[WARN_CFLAGS="$WARN_CFLAGS -Wcast-align"],,)
-AX_CHECK_COMPILE_FLAG([-Wunused-parameter],[NOWARN_CFLAGS="$NOWARN_CFLAGS -Wno-unused-parameter"],,)
-AX_CHECK_COMPILE_FLAG([-Wshadow],[NOWARN_CFLAGS="$NOWARN_CFLAGS -Wno-shadow"],,)
-AX_CHECK_COMPILE_FLAG([-Wsign-compare],[NOWARN_CFLAGS="$NOWARN_CFLAGS -Wno-sign-compare"],,)
-AX_CHECK_COMPILE_FLAG([-Wstrict-prototypes],[NOWARN_CFLAGS="$NOWARN_CFLAGS -Wno-strict-prototypes"],,)
-AX_CHECK_COMPILE_FLAG([-Wunused-function],[NOWARN_CFLAGS="$NOWARN_CFLAGS -Wno-unused-function"],,)
-AX_CHECK_COMPILE_FLAG([-Wlong-long],[NOWARN_CFLAGS="$NOWARN_CFLAGS -Wno-long-long"],,)
+AX_CHECK_COMPILE_FLAG([-Wall], [WARN_CFLAGS="$WARN_CFLAGS -Wall"], [], [])
+AX_CHECK_COMPILE_FLAG([-Wextra], [WARN_CFLAGS="$WARN_CFLAGS -Wextra"], [], [])
+AX_CHECK_COMPILE_FLAG([-Wcast-align], [WARN_CFLAGS="$WARN_CFLAGS -Wcast-align"], [], [])
+AX_CHECK_COMPILE_FLAG([-Wunused-parameter], [NOWARN_CFLAGS="$NOWARN_CFLAGS -Wno-unused-parameter"], [], [])
+AX_CHECK_COMPILE_FLAG([-Wshadow], [NOWARN_CFLAGS="$NOWARN_CFLAGS -Wno-shadow"], [], [])
+AX_CHECK_COMPILE_FLAG([-Wsign-compare], [NOWARN_CFLAGS="$NOWARN_CFLAGS -Wno-sign-compare"], [], [])
+AX_CHECK_COMPILE_FLAG([-Wstrict-prototypes], [NOWARN_CFLAGS="$NOWARN_CFLAGS -Wno-strict-prototypes"], [], [])
+AX_CHECK_COMPILE_FLAG([-Wunused-function], [NOWARN_CFLAGS="$NOWARN_CFLAGS -Wno-unused-function"], [], [])
+AX_CHECK_COMPILE_FLAG([-Wlong-long], [NOWARN_CFLAGS="$NOWARN_CFLAGS -Wno-long-long"], [], [])
AC_LANG_POP([C])
dnl set default settings for relic
-AC_DEFINE([ALIGN], [1], [Byte boundary to align digit vectors.])
-
-AC_DEFINE(WITH_BN,, Build multiple precision integer module.)
-AC_DEFINE(WITH_DV,, Temporary double-precision digit vectors.)
-AC_DEFINE(WITH_FP,, Build prime field module.)
-AC_DEFINE(WITH_FPX,, Build prime field extension module.)
-AC_DEFINE(WITH_FB,, Build binary field module.)
-AC_DEFINE(WITH_FBX,, Build binary field extension module.)
-AC_DEFINE(WITH_EP,, Build prime elliptic curve module.)
-AC_DEFINE(WITH_EPX,, Build prime field extension elliptic curve module.)
-AC_DEFINE(WITH_EB,, Build binary elliptic curve module.)
-AC_DEFINE(WITH_ED,, Build elliptic Edwards curve module.)
-AC_DEFINE(WITH_EC,, Build elliptic curve cryptography module.)
-AC_DEFINE(WITH_PP,, Build pairings over prime curves module.)
-AC_DEFINE(WITH_PC,, Build pairing-based cryptography module.)
-AC_DEFINE(WITH_BC,, Build block ciphers.)
-AC_DEFINE(WITH_MD,, Build hash functions.)
-AC_DEFINE(WITH_CP,, Build cryptographic protocols.)
-AC_DEFINE(WITH_MPC,, Build Multi-party computation primitives.)
-
-AC_DEFINE(BN_PRECI, 1024, Required precision in bits.)
-AC_DEFINE(BN_KARAT, 0, Number of Karatsuba steps.)
-AC_DEFINE(BN_MAGNI, [DOUBLE], Effective size of a multiple precision integer.)
-
-AC_DEFINE(BN_METHD, "COMBA;COMBA;MONTY;SLIDE;BASIC;BASIC", Multiple precision arithmetic method.)
-AC_DEFINE(BN_MUL, COMBA, Chosen multiple precision multiplication method.)
-AC_DEFINE(BN_SQR, COMBA, Chosen multiple precision multiplication method.)
-AC_DEFINE(BN_MOD, MONTY, Chosen multiple precision modular reduction method.)
-AC_DEFINE(BN_MXP, SLIDE, Chosen multiple precision modular exponentiation method.)
-AC_DEFINE(BN_GCD, BASIC, Chosen multiple precision greatest common divisor method.)
-AC_DEFINE(BN_GEN, BASIC, Chosen prime generation algorithm.)
-
-AC_DEFINE(FP_PRIME, 381, Prime field size in bits.)
-AC_DEFINE(FP_METHD, "INTEG;INTEG;INTEG;MONTY;LOWER;SLIDE", Prime field arithmetic method.)
-AC_DEFINE(FP_KARAT, 0, Number of Karatsuba steps.)
-AC_DEFINE(FP_WIDTH, 4, Width of window processing for exponentiation methods.)
-AC_DEFINE(FP_ADD, INTEG, Chosen prime field multiplication method.)
-AC_DEFINE(FP_MUL, INTEG, Chosen prime field multiplication method.)
-AC_DEFINE(FP_SQR, INTEG, Chosen prime field multiplication method.)
-AC_DEFINE(FP_RDC, MONTY, Chosen prime field reduction method.)
-AC_DEFINE(FP_INV, LOWER, Chosen prime field inversion method.)
-AC_DEFINE(FP_EXP, SLIDE, Chosen multiple precision modular exponentiation method.)
-
-AC_DEFINE(FPX_METHD, "INTEG;INTEG;LAZYR", Prime extension field arithmetic method.)
-AC_DEFINE(FPX_QDR, INTEG, Chosen extension field arithmetic method.)
-AC_DEFINE(FPX_CBC, INTEG, Chosen extension field arithmetic method.)
-AC_DEFINE(FPX_RDC, LAZYR, Chosen extension field arithmetic method.)
-
-AC_DEFINE(FB_METHD, "LODAH;QUICK;QUICK;QUICK;QUICK;QUICK;EXGCD;SLIDE;QUICK", Binary field arithmetic method)
-AC_DEFINE(FB_POLYN, 283, Irreducible polynomial size in bits.)
-AC_DEFINE(FB_KARAT, 0, Number of Karatsuba levels.)
-AC_DEFINE(FB_TRINO,, Prefer trinomials over pentanomials.)
-AC_DEFINE(FB_PRECO,, Precompute multiplication table for sqrt(z).)
-AC_DEFINE(FB_WIDTH, 4, Width of window processing for exponentiation methods.)
-AC_DEFINE(FB_MUL, LODAH, Chosen binary field multiplication method.)
-AC_DEFINE(FB_SQR, QUICK, Chosen binary field squaring method.)
-AC_DEFINE(FB_RDC, QUICK, Chosen binary field modular reduction method.)
-AC_DEFINE(FB_SRT, QUICK, Chosen binary field modular reduction method.)
-AC_DEFINE(FB_TRC, QUICK, Chosen trace computation method.)
-AC_DEFINE(FB_SLV, QUICK, Chosen method to solve a quadratic equation.)
-AC_DEFINE(FB_INV, EXGCD, Chosen binary field inversion method.)
-AC_DEFINE(FB_EXP, SLIDE, Chosen multiple precision modular exponentiation method.)
-AC_DEFINE(FB_ITR, QUICK, Chosen method to solve a quadratic equation.)
-
-AC_DEFINE(EP_METHD, "PROJC;LWNAF;COMBS;INTER", Prime elliptic curve arithmetic method.)
-AC_DEFINE(EP_ENDOM,, Support for prime curves with efficient endormorphisms.)
-AC_DEFINE(EP_MIXED,, Use mixed coordinates.)
-AC_DEFINE(EP_PRECO,, Build precomputation table for generator.)
-AC_DEFINE(EP_CTMAP,, Enable isogeny map for SSWU map-to-curve.)
-AC_DEFINE(EP_DEPTH, 4, Width of precomputation table for fixed point methods.)
-AC_DEFINE(EP_WIDTH, 4, Width of window processing for unknown point methods.)
-AC_DEFINE(EP_ADD, PROJC, Chosen prime elliptic curve coordinate method.)
-AC_DEFINE(EP_MUL, LWNAF, Chosen prime elliptic curve point multiplication method.)
-AC_DEFINE(EP_FIX, COMBS, Chosen prime elliptic curve point multiplication method.)
-AC_DEFINE(EP_SIM, INTER, Chosen prime elliptic curve simulteanous point multiplication method.)
-
-AC_DEFINE(EB_METHD, "PROJC;LWNAF;COMBS;INTER", Binary elliptic curve arithmetic method.)
-AC_DEFINE(EB_PLAIN,, Support for ordinary curves without endormorphisms.)
-AC_DEFINE(EB_KBLTZ,, Support for Koblitz anomalous binary curves.)
-AC_DEFINE(EB_MIXED,, Use mixed coordinates.)
-AC_DEFINE(EB_PRECO,, Build precomputation table for generator.)
-AC_DEFINE(EB_DEPTH, 4, Width of precomputation table for fixed point methods.)
-AC_DEFINE(EB_WIDTH, 4, Width of window processing for unknown point methods.)
-AC_DEFINE(EB_ADD, PROJC, Chosen binary elliptic curve coordinate method.)
-AC_DEFINE(EB_MUL, LWNAF, Chosen binary elliptic curve point multiplication method.)
-AC_DEFINE(EB_FIX, COMBS, Chosen binary elliptic curve point multiplication method.)
-AC_DEFINE(EB_SIM, INTER, Chosen binary elliptic curve simulteanous point multiplication method.)
-
-AC_DEFINE(ED_METHD, "PROJC;LWNAF;COMBS;INTER", Edwards elliptic curve arithmetic method.)
-AC_DEFINE(ED_PRECO,, Build precomputation table for generator.)
-AC_DEFINE(ED_DEPTH, 4, Width of precomputation table for fixed point methods.)
-AC_DEFINE(ED_WIDTH, 4, Width of window processing for unknown point methods.)
-AC_DEFINE(ED_ADD, PROJC, Chosen binary elliptic curve coordinate method.)
-AC_DEFINE(ED_MUL, LWNAF, Chosen prime elliptic twisted Edwards curve point multiplication method.)
-AC_DEFINE(ED_FIX, COMBS, Chosen prime elliptic twisted Edwards curve point multiplication method.)
-AC_DEFINE(ED_SIM, INTER, Chosen prime elliptic curve simulteanous point multiplication method.)
-
-AC_DEFINE(EC_METHD, "PRIME", Chosen elliptic curve cryptography method.)
-AC_DEFINE(EC_CUR, PRIME, Chosen elliptic curve type.)
-
-AC_DEFINE(PP_METHD, "LAZYR;OATEP", Bilinear pairing method.)
-AC_DEFINE(PP_EXT, LAZYR, Chosen extension field arithmetic method.)
-AC_DEFINE(PP_MAP, OATEP, Chosen pairing method over prime elliptic curves.)
-
-AC_DEFINE(MD_METHD, "SH256", Choice of hash function.)
-AC_DEFINE(MD_MAP, SH256, Chosen hash function.)
-
-AC_DEFINE(CP_CRT,, Support for faster CRT-based exponentiation in factoring-based cryptosystems.)
-AC_DEFINE(CP_RSAPD, PKCS2, Chosen RSA padding method.)
-
-AC_DEFINE(ALLOC, AUTO, Chosen memory allocation policy.)
-AC_DEFINE(RAND, HASHD, Chosen random generator.)
-AC_DEFINE(MULTI, PTHREAD, Chosen multithreading API.)
-AC_DEFINE(TIMER, CYCLE, Chosen timer.)
-
-
-AC_CHECK_HEADER(gmp.h,[AC_CHECK_LIB(gmp, __gmpz_init,[has_gmp=yes; LIBS="$LIBS -lgmp";])], AC_MSG_ERROR(gmp headers missing),)
+AC_DEFINE([ALIGN], [1], [Byte boundary to align digit vectors.])
+AC_DEFINE([WITH_BN], [], [Build multiple precision integer module.])
+AC_DEFINE([WITH_DV], [], [Temporary double-precision digit vectors.])
+AC_DEFINE([WITH_FP], [], [Build prime field module.])
+AC_DEFINE([WITH_FPX], [], [Build prime field extension module.])
+AC_DEFINE([WITH_FB], [], [Build binary field module.])
+AC_DEFINE([WITH_FBX], [], [Build binary field extension module.])
+AC_DEFINE([WITH_EP], [], [Build prime elliptic curve module.])
+AC_DEFINE([WITH_EPX], [], [Build prime field extension elliptic curve module.])
+AC_DEFINE([WITH_EB], [], [Build binary elliptic curve module.])
+AC_DEFINE([WITH_ED], [], [Build elliptic Edwards curve module.])
+AC_DEFINE([WITH_EC], [], [Build elliptic curve cryptography module.])
+AC_DEFINE([WITH_PP], [], [Build pairings over prime curves module.])
+AC_DEFINE([WITH_PC], [], [Build pairing-based cryptography module.])
+AC_DEFINE([WITH_BC], [], [Build block ciphers.])
+AC_DEFINE([WITH_MD], [], [Build hash functions.])
+AC_DEFINE([WITH_CP], [], [Build cryptographic protocols.])
+AC_DEFINE([WITH_MPC], [], [Build Multi-party computation primitives.])
+
+AC_DEFINE([BN_PRECI], [1024], [Required precision in bits.])
+AC_DEFINE([BN_KARAT], [0], [Number of Karatsuba steps.])
+AC_DEFINE([BN_MAGNI], [DOUBLE], [Effective size of a multiple precision integer.])
+
+AC_DEFINE([BN_METHD], ["COMBA;COMBA;MONTY;SLIDE;BASIC;BASIC"], [Multiple precision arithmetic method.])
+AC_DEFINE([BN_MUL], [COMBA], [Chosen multiple precision multiplication method.])
+AC_DEFINE([BN_SQR], [COMBA], [Chosen multiple precision multiplication method.])
+AC_DEFINE([BN_MOD], [MONTY], [Chosen multiple precision modular reduction method.])
+AC_DEFINE([BN_MXP], [SLIDE], [Chosen multiple precision modular exponentiation method.])
+AC_DEFINE([BN_GCD], [BASIC], [Chosen multiple precision greatest common divisor method.])
+AC_DEFINE([BN_GEN], [BASIC], [Chosen prime generation algorithm.])
+
+AC_DEFINE([FP_METHD], ["INTEG;INTEG;INTEG;MONTY;LOWER;LOWER;SLIDE"], [Prime field arithmetic method.])
+AC_DEFINE([FP_PRIME], [381], [Prime field size in bits.])
+AC_DEFINE([FP_KARAT], [0], [Number of Karatsuba steps.])
+AC_DEFINE([FP_WIDTH], [4], [Width of window processing for exponentiation methods.])
+AC_DEFINE([FP_ADD], [INTEG], [Chosen prime field multiplication method.])
+AC_DEFINE([FP_MUL], [INTEG], [Chosen prime field multiplication method.])
+AC_DEFINE([FP_SQR], [INTEG], [Chosen prime field multiplication method.])
+AC_DEFINE([FP_RDC], [MONTY], [Chosen prime field reduction method.])
+AC_DEFINE([FP_INV], [LOWER], [Chosen prime field inversion method.])
+AC_DEFINE([FP_SMB], [LOWER], [Chosen prime field Legendre symbol method.])
+AC_DEFINE([FP_EXP], [SLIDE], [Chosen multiple precision modular exponentiation method.])
+
+AC_DEFINE([FPX_METHD], ["INTEG;INTEG;LAZYR"], [Prime extension field arithmetic method.])
+AC_DEFINE([FPX_QDR], [INTEG], [Chosen extension field arithmetic method.])
+AC_DEFINE([FPX_CBC], [INTEG], [Chosen extension field arithmetic method.])
+AC_DEFINE([FPX_RDC], [LAZYR], [Chosen extension field arithmetic method.])
+
+AC_DEFINE([FB_METHD], ["LODAH;QUICK;QUICK;QUICK;QUICK;QUICK;EXGCD;SLIDE;QUICK"], [Binary field arithmetic method.])
+AC_DEFINE([FB_POLYN], [283], [Irreducible polynomial size in bits.])
+AC_DEFINE([FB_KARAT], [0], [Number of Karatsuba levels.])
+AC_DEFINE([FB_TRINO], [], [Prefer trinomials over pentanomials.])
+AC_DEFINE([FB_PRECO], [], [Precompute multiplication table for sqrt(z).])
+AC_DEFINE([FB_WIDTH], [4], [Width of window processing for exponentiation methods.])
+AC_DEFINE([FB_MUL], [LODAH], [Chosen binary field multiplication method.])
+AC_DEFINE([FB_SQR], [QUICK], [Chosen binary field squaring method.])
+AC_DEFINE([FB_RDC], [QUICK], [Chosen binary field modular reduction method.])
+AC_DEFINE([FB_SRT], [QUICK], [Chosen binary field modular reduction method.])
+AC_DEFINE([FB_TRC], [QUICK], [Chosen trace computation method.])
+AC_DEFINE([FB_SLV], [QUICK], [Chosen method to solve a quadratic equation.])
+AC_DEFINE([FB_INV], [EXGCD], [Chosen binary field inversion method.])
+AC_DEFINE([FB_EXP], [SLIDE], [Chosen multiple precision modular exponentiation method.])
+AC_DEFINE([FB_ITR], [QUICK], [Chosen method to solve a quadratic equation.])
+
+AC_DEFINE([EP_METHD], ["PROJC;LWNAF;COMBS;INTER"], [Prime elliptic curve arithmetic method.])
+AC_DEFINE([EP_ENDOM], [], [Support for prime curves with efficient endormorphisms.])
+AC_DEFINE([EP_MIXED], [], [Use mixed coordinates.])
+AC_DEFINE([EP_PRECO], [], [Build precomputation table for generator.])
+AC_DEFINE([EP_CTMAP], [], [Enable isogeny map for SSWU map-to-curve.])
+AC_DEFINE([EP_DEPTH], [4], [Width of precomputation table for fixed point methods.])
+AC_DEFINE([EP_WIDTH], [4], [Width of window processing for unknown point methods.])
+AC_DEFINE([EP_ADD], [PROJC], [Chosen prime elliptic curve coordinate method.])
+AC_DEFINE([EP_MUL], [LWNAF], [Chosen prime elliptic curve point multiplication method.])
+AC_DEFINE([EP_FIX], [COMBS], [Chosen prime elliptic curve point multiplication method.])
+AC_DEFINE([EP_SIM], [INTER], [Chosen prime elliptic curve simulteanous point multiplication method.])
+
+AC_DEFINE([EB_METHD], ["PROJC;LWNAF;COMBS;INTER"], [Binary elliptic curve arithmetic method.])
+AC_DEFINE([EB_PLAIN], [], [Support for ordinary curves without endormorphisms.])
+AC_DEFINE([EB_KBLTZ], [], [Support for Koblitz anomalous binary curves.])
+AC_DEFINE([EB_MIXED], [], [Use mixed coordinates.])
+AC_DEFINE([EB_PRECO], [], [Build precomputation table for generator.])
+AC_DEFINE([EB_DEPTH], [4], [Width of precomputation table for fixed point methods.])
+AC_DEFINE([EB_WIDTH], [4], [Width of window processing for unknown point methods.])
+AC_DEFINE([EB_ADD], [PROJC], [Chosen binary elliptic curve coordinate method.])
+AC_DEFINE([EB_MUL], [LWNAF], [Chosen binary elliptic curve point multiplication method.])
+AC_DEFINE([EB_FIX], [COMBS], [Chosen binary elliptic curve point multiplication method.])
+AC_DEFINE([EB_SIM], [INTER], [Chosen binary elliptic curve simulteanous point multiplication method.])
+
+AC_DEFINE([ED_METHD], ["PROJC;LWNAF;COMBS;INTER"], [Edwards elliptic curve arithmetic method.])
+AC_DEFINE([ED_PRECO], [], [Build precomputation table for generator.])
+AC_DEFINE([ED_DEPTH], [4], [Width of precomputation table for fixed point methods.])
+AC_DEFINE([ED_WIDTH], [4], [Width of window processing for unknown point methods.])
+AC_DEFINE([ED_ADD], [PROJC], [Chosen binary elliptic curve coordinate method.])
+AC_DEFINE([ED_MUL], [LWNAF], [Chosen prime elliptic twisted Edwards curve point multiplication method.])
+AC_DEFINE([ED_FIX], [COMBS], [Chosen prime elliptic twisted Edwards curve point multiplication method.])
+AC_DEFINE([ED_SIM], [INTER], [Chosen prime elliptic curve simulteanous point multiplication method.])
+
+AC_DEFINE([EC_METHD], ["PRIME"], [Chosen elliptic curve cryptography method.])
+AC_DEFINE([EC_CUR], [PRIME], [Chosen elliptic curve type.])
+
+AC_DEFINE([PP_METHD], ["LAZYR;OATEP"], [Bilinear pairing method.])
+AC_DEFINE([PP_EXT], [LAZYR], [Chosen extension field arithmetic method.])
+AC_DEFINE([PP_MAP], [OATEP], [Chosen pairing method over prime elliptic curves.])
+
+AC_DEFINE([MD_METHD], ["SH256"], [Choice of hash function.])
+AC_DEFINE([MD_MAP], [SH256], [Chosen hash function.])
+
+AC_DEFINE([CP_CRT], [], [Support for faster CRT-based exponentiation in factoring-based cryptosystems.])
+AC_DEFINE([CP_RSAPD], [PKCS2], [Chosen RSA padding method.])
+
+AC_DEFINE([ALLOC], [AUTO], [Chosen memory allocation policy.])
+AC_DEFINE([RAND], [HASHD], [Chosen random generator.])
+AC_DEFINE([MULTI], [PTHREAD], [Chosen multithreading API.])
+AC_DEFINE([TIMER], [CYCLE], [Chosen timer.])
+
+
+AC_CHECK_HEADER([gmp.h], [AC_CHECK_LIB([gmp], [__gmpz_init], [has_gmp=yes; LIBS="$LIBS -lgmp";])], [AC_MSG_ERROR([gmp headers missing])],[])
if test x$has_gmp = xyes; then
- AC_DEFINE(ARITH, GMP, Arithmetic backend.)
+ AC_DEFINE([ARITH], [GMP], [Arithmetic backend.])
fi
if test x$use_pkgconfig = xyes; then
@@ -406,18 +421,18 @@ if test x$use_pkgconfig = xyes; then
m4_ifdef(
[PKG_CHECK_MODULES],
[
- PKG_CHECK_MODULES([SODIUM], [libsodium],, [AC_MSG_ERROR(libsodium not found.)])
+ PKG_CHECK_MODULES([SODIUM], [libsodium], [], [AC_MSG_ERROR(libsodium not found.)])
]
)
else
- AC_CHECK_HEADER([sodium/core.h],, AC_MSG_ERROR(libsodium headers missing),)
- AC_CHECK_LIB([sodium],[main],SODIUM_LIBS=-lsodium, AC_MSG_ERROR(libsodium missing))
+ AC_CHECK_HEADER([sodium/core.h], [], [AC_MSG_ERROR([libsodium headers missing])], [])
+ AC_CHECK_LIB([sodium], [main], [SODIUM_LIBS=-lsodium], [AC_MSG_ERROR([libsodium missing])])
fi
dnl Check for pthread compile/link requirements
AX_PTHREAD
-AC_SEARCH_LIBS([clock_gettime],[rt])
+AC_SEARCH_LIBS([clock_gettime], [rt])
AC_MSG_CHECKING([whether to build runtest])
if test x$use_tests = xyes; then
@@ -437,23 +452,23 @@ else
BUILD_BENCH=""
fi
-AM_CONDITIONAL(WITH_BN, test 1 -eq 1)
-AM_CONDITIONAL(WITH_FP, test 1 -eq 1)
-AM_CONDITIONAL(WITH_FPX, test 1 -eq 1)
-AM_CONDITIONAL(WITH_FB, test 1 -eq 1)
-AM_CONDITIONAL(WITH_EP, test 1 -eq 1)
-AM_CONDITIONAL(WITH_EPX, test 1 -eq 1)
-AM_CONDITIONAL(WITH_EB, test 1 -eq 1)
-AM_CONDITIONAL(WITH_ED, test 1 -eq 1)
-AM_CONDITIONAL(WITH_EC, test 1 -eq 1)
-AM_CONDITIONAL(WITH_PP, test 1 -eq 1)
-AM_CONDITIONAL(WITH_PC, test 1 -eq 1)
-AM_CONDITIONAL(WITH_BC, test 1 -eq 1)
-AM_CONDITIONAL(WITH_MD, test 1 -eq 1)
-AM_CONDITIONAL(WITH_CP, test 1 -eq 1)
-AM_CONDITIONAL(WITH_MPC, test 1 -eq 1)
-AM_CONDITIONAL(WITH_DV, test 1 -eq 1)
-AM_CONDITIONAL(WITH_FBX, test 1 -eq 1)
+AM_CONDITIONAL([WITH_BN], [test 1 -eq 1])
+AM_CONDITIONAL([WITH_FP], [test 1 -eq 1])
+AM_CONDITIONAL([WITH_FPX], [test 1 -eq 1])
+AM_CONDITIONAL([WITH_FB], [test 1 -eq 1])
+AM_CONDITIONAL([WITH_EP], [test 1 -eq 1])
+AM_CONDITIONAL([WITH_EPX], [test 1 -eq 1])
+AM_CONDITIONAL([WITH_EB], [test 1 -eq 1])
+AM_CONDITIONAL([WITH_ED], [test 1 -eq 1])
+AM_CONDITIONAL([WITH_EC], [test 1 -eq 1])
+AM_CONDITIONAL([WITH_PP], [test 1 -eq 1])
+AM_CONDITIONAL([WITH_PC], [test 1 -eq 1])
+AM_CONDITIONAL([WITH_BC], [test 1 -eq 1])
+AM_CONDITIONAL([WITH_MD], [test 1 -eq 1])
+AM_CONDITIONAL([WITH_CP], [test 1 -eq 1])
+AM_CONDITIONAL([WITH_MPC], [test 1 -eq 1])
+AM_CONDITIONAL([WITH_DV], [test 1 -eq 1])
+AM_CONDITIONAL([WITH_FBX], [test 1 -eq 1])
AM_CONDITIONAL([USE_TESTS], [test x$BUILD_TEST = xyes])
AM_CONDITIONAL([USE_BENCH], [test x$BUILD_BENCH = xyes])
AC_SUBST(CPU_ARCH)
@@ -463,6 +478,8 @@ AC_SUBST(SODIUM_LIBS)
AC_SUBST(RELIC_CPPFLAGS)
AC_SUBST(WARN_CFLAGS)
AC_SUBST(NOWARN_CFLAGS)
+AC_SUBST(WARN_CXXFLAGS)
+AC_SUBST(NOWARN_CXXFLAGS)
AC_SUBST(LIBTOOL_APP_LDFLAGS)
diff --git a/contrib/relic/.editorconfig b/contrib/relic/.editorconfig
new file mode 100644
index 000000000..bdc049fe5
--- /dev/null
+++ b/contrib/relic/.editorconfig
@@ -0,0 +1,7 @@
+# top-most EditorConfig file
+root = true
+
+# 4 space indentation
+[*.{cmake,c,h}]
+indent_style = tab
+indent_size = 4
diff --git a/contrib/relic/.github/workflows/16bit.yml b/contrib/relic/.github/workflows/16bit.yml
new file mode 100644
index 000000000..8633cd322
--- /dev/null
+++ b/contrib/relic/.github/workflows/16bit.yml
@@ -0,0 +1,48 @@
+name: Basic configuration (16 bits)
+
+on:
+ push:
+ branches:
+ - '**' # all branches
+ pull_request:
+ branches:
+ - '**' # all branches
+
+jobs:
+ build:
+ name: ${{ matrix.config.name }}
+ runs-on: ${{ matrix.config.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ config:
+ - {
+ name: "Ubuntu Latest - GCC",
+ artifact: "linux-gcc.tar.xz",
+ os: ubuntu-latest,
+ cc: "gcc",
+ }
+ - {
+ name: "Ubuntu Latest - Clang",
+ artifact: "linux-clang.tar.xz",
+ os: ubuntu-latest,
+ cc: "clang",
+ }
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Run CMake (standard)
+ if: ${{ !(runner.os == 'Windows') }}
+ shell: bash
+ run: |
+ mkdir build
+ cd build
+ cmake -DCMAKE_C_COMPILER=${{ matrix.config.cc }} -DWSIZE=16 -DSEED= -DBENCH=0 -DTESTS=10 ..
+
+ - name: CMake Build
+ run: cmake --build build
+
+ - name: CMake Test
+ run: |
+ cd build
+ ctest --verbose .
diff --git a/contrib/relic/.github/workflows/32bit.yml b/contrib/relic/.github/workflows/32bit.yml
new file mode 100644
index 000000000..bb225ab80
--- /dev/null
+++ b/contrib/relic/.github/workflows/32bit.yml
@@ -0,0 +1,97 @@
+name: Basic configuration (32 bits)
+
+on:
+ push:
+ branches:
+ - '**' # all branches
+ pull_request:
+ branches:
+ - '**' # all branches
+
+jobs:
+ build:
+ name: ${{ matrix.config.name }}
+ runs-on: ${{ matrix.config.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ config:
+ - {
+ name: "Windows Latest - MSVC",
+ artifact: "windows-msvc.tar.xz",
+ os: windows-latest,
+ cc: "cl",
+ }
+ - {
+ name: "Windows Latest - MinGW",
+ artifact: "windows-mingw.tar.xz",
+ os: windows-latest,
+ cc: "gcc"
+ }
+ - {
+ name: "Ubuntu Latest - GCC",
+ artifact: "linux-gcc.tar.xz",
+ os: ubuntu-latest,
+ cc: "gcc",
+ }
+ - {
+ name: "Ubuntu Latest - Clang",
+ artifact: "linux-clang.tar.xz",
+ os: ubuntu-latest,
+ cc: "clang",
+ }
+ - {
+ name: "MacOS Latest",
+ os: macos-latest,
+ cc: "clang",
+ }
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Set Windows enviroment
+ if: ${{ (runner.os == 'Windows') && (matrix.config.cc == 'cl') }}
+ uses: ilammy/msvc-dev-cmd@v1
+
+ - name: Set MinGW enviroment
+ if: ${{ (runner.os == 'Windows') && (matrix.config.cc == 'gcc') }}
+ uses: msys2/setup-msys2@v2
+ with:
+ msystem: MINGW64
+ install: >-
+ git
+ base-devel
+ gcc
+ cmake
+ update: true
+
+ - name: Run CMake (Win)
+ if: ${{ (runner.os == 'Windows') && (matrix.config.cc == 'cl') }}
+ shell: bash
+ run: |
+ mkdir build
+ cd build
+ cmake -DWSIZE=32 -DSEED= -DBENCH=0 -G "NMake Makefiles" ..
+
+ - name: Run CMake (MingW)
+ if: ${{ (runner.os == 'Windows') && (matrix.config.cc == 'gcc') }}
+ shell: bash
+ run: |
+ mkdir build
+ cd build
+ cmake -DWSIZE=32 -DSEED= -DBENCH=0 -G "MinGW Makefiles" ..
+
+ - name: Run CMake (standard)
+ if: ${{ !(runner.os == 'Windows') }}
+ shell: bash
+ run: |
+ mkdir build
+ cd build
+ cmake -DCMAKE_C_COMPILER=${{ matrix.config.cc }} -DWSIZE=32 -DSEED= -DBENCH=0 ..
+
+ - name: CMake Build
+ run: cmake --build build
+
+ - name: CMake Test
+ run: |
+ cd build
+ ctest --verbose .
diff --git a/contrib/relic/.github/workflows/8bit.yml b/contrib/relic/.github/workflows/8bit.yml
new file mode 100644
index 000000000..0765607ec
--- /dev/null
+++ b/contrib/relic/.github/workflows/8bit.yml
@@ -0,0 +1,48 @@
+name: Basic configuration (8 bits)
+
+on:
+ push:
+ branches:
+ - '**' # all branches
+ pull_request:
+ branches:
+ - '**' # all branches
+
+jobs:
+ build:
+ name: ${{ matrix.config.name }}
+ runs-on: ${{ matrix.config.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ config:
+ - {
+ name: "Ubuntu Latest - GCC",
+ artifact: "linux-gcc.tar.xz",
+ os: ubuntu-latest,
+ cc: "gcc",
+ }
+ - {
+ name: "Ubuntu Latest - Clang",
+ artifact: "linux-clang.tar.xz",
+ os: ubuntu-latest,
+ cc: "clang",
+ }
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Run CMake (standard)
+ if: ${{ !(runner.os == 'Windows') }}
+ shell: bash
+ run: |
+ mkdir build
+ cd build
+ cmake -DCMAKE_C_COMPILER=${{ matrix.config.cc }} -DWSIZE=8 -DSEED= -DBENCH=0 -DTESTS=10 ..
+
+ - name: CMake Build
+ run: cmake --build build
+
+ - name: CMake Test
+ run: |
+ cd build
+ ctest --verbose .
diff --git a/contrib/relic/.github/workflows/bls12-381.yml b/contrib/relic/.github/workflows/bls12-381.yml
new file mode 100644
index 000000000..e99f190ac
--- /dev/null
+++ b/contrib/relic/.github/workflows/bls12-381.yml
@@ -0,0 +1,86 @@
+name: BLS12-381 configuration (ASM)
+
+on:
+ push:
+ branches:
+ - '**' # all branches
+ pull_request:
+ branches:
+ - '**' # all branches
+
+jobs:
+ build:
+ name: ${{ matrix.config.name }}
+ runs-on: ${{ matrix.config.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ config:
+ #- {
+ #name: "Windows Latest - MinGW",
+ #artifact: "windows-mingw.tar.xz",
+ #os: windows-latest,
+ #cc: "gcc"
+ #}
+ - {
+ name: "Ubuntu Latest - GCC",
+ artifact: "linux-gcc.tar.xz",
+ os: ubuntu-latest,
+ cc: "gcc",
+ }
+ - {
+ name: "Ubuntu Latest - Clang",
+ artifact: "linux-clang.tar.xz",
+ os: ubuntu-latest,
+ cc: "clang",
+ }
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Install Linux Dependencies
+ if: runner.os == 'Linux'
+ run: sudo apt install libgmp-dev
+
+ - name: Install MacOS Dependencies
+ if: runner.os == 'MacOS'
+ run: brew install gmp
+
+ - name: Set MinGW enviroment
+ if: ${{ (runner.os == 'Windows') && (matrix.config.cc == 'gcc') }}
+ uses: msys2/setup-msys2@v2
+ with:
+ msystem: MINGW64
+ install: >-
+ git
+ base-devel
+ gcc
+ cmake
+ gmp
+ update: true
+
+ - name: Run CMake (MingW)
+ if: ${{ (runner.os == 'Windows') && (matrix.config.cc == 'gcc') }}
+ shell: bash
+ run: |
+ mkdir build
+ cd build
+ cmake -G "MinGW Makefiles" ..
+ cmake -DSEED= -DBENCH=0 -DSTBIN=off -DRAND=HASHD ..
+ ../preset/x64-pbc-bls12-381.sh ..
+
+ - name: Run CMake (standard)
+ if: ${{ !(runner.os == 'Windows') }}
+ shell: bash
+ run: |
+ mkdir build
+ cd build
+ cmake -DCMAKE_C_COMPILER=${{ matrix.config.cc }} -DSEED= -DBENCH=0 ..
+ ../preset/x64-pbc-bls12-381.sh ..
+
+ - name: CMake Build
+ run: cmake --build build
+
+ - name: CMake Test
+ run: |
+ cd build
+ ctest --verbose .
diff --git a/contrib/relic/.github/workflows/push.yml b/contrib/relic/.github/workflows/easy.yml
similarity index 93%
rename from contrib/relic/.github/workflows/push.yml
rename to contrib/relic/.github/workflows/easy.yml
index 0977f5646..761f07f33 100644
--- a/contrib/relic/.github/workflows/push.yml
+++ b/contrib/relic/.github/workflows/easy.yml
@@ -1,6 +1,12 @@
-name: Continuous Integration
+name: Basic configuration
-on: [push, pull_request]
+on:
+ push:
+ branches:
+ - '**' # all branches
+ pull_request:
+ branches:
+ - '**' # all branches
jobs:
build:
@@ -42,10 +48,6 @@ jobs:
steps:
- uses: actions/checkout@v2
- - name: Install Linux Dependencies
- if: runner.os == 'Linux'
- run: sudo apt install libgmp-dev
-
- name: Set Windows enviroment
if: ${{ (runner.os == 'Windows') && (matrix.config.cc == 'cl') }}
uses: ilammy/msvc-dev-cmd@v1
diff --git a/contrib/relic/.github/workflows/gmp-sec.yml b/contrib/relic/.github/workflows/gmp-sec.yml
new file mode 100644
index 000000000..2cd342099
--- /dev/null
+++ b/contrib/relic/.github/workflows/gmp-sec.yml
@@ -0,0 +1,88 @@
+name: Faster configuration (constant-time GMP)
+
+on:
+ push:
+ branches:
+ - '**' # all branches
+ pull_request:
+ branches:
+ - '**' # all branches
+
+jobs:
+ build:
+ name: ${{ matrix.config.name }}
+ runs-on: ${{ matrix.config.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ config:
+ - {
+ name: "Windows Latest - MinGW",
+ artifact: "windows-mingw.tar.xz",
+ os: windows-latest,
+ cc: "gcc"
+ }
+ - {
+ name: "Ubuntu Latest - GCC",
+ artifact: "linux-gcc.tar.xz",
+ os: ubuntu-latest,
+ cc: "gcc",
+ }
+ - {
+ name: "Ubuntu Latest - Clang",
+ artifact: "linux-clang.tar.xz",
+ os: ubuntu-latest,
+ cc: "clang",
+ }
+ - {
+ name: "MacOS Latest",
+ os: macos-latest,
+ cc: "clang",
+ }
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Install Linux Dependencies
+ if: runner.os == 'Linux'
+ run: sudo apt install libgmp-dev
+
+ - name: Install MacOS Dependencies
+ if: runner.os == 'MacOS'
+ run: brew install gmp
+
+ - name: Set MinGW enviroment
+ if: ${{ (runner.os == 'Windows') && (matrix.config.cc == 'gcc') }}
+ uses: msys2/setup-msys2@v2
+ with:
+ msystem: MINGW64
+ install: >-
+ git
+ base-devel
+ gcc
+ cmake
+ gmp
+ update: true
+
+ - name: Run CMake (MingW)
+ if: ${{ (runner.os == 'Windows') && (matrix.config.cc == 'gcc') }}
+ shell: bash
+ run: |
+ mkdir build
+ cd build
+ cmake -DSEED= -DBENCH=0 -DARITH=gmp-sec -G "MinGW Makefiles" ..
+
+ - name: Run CMake (standard)
+ if: ${{ !(runner.os == 'Windows') }}
+ shell: bash
+ run: |
+ mkdir build
+ cd build
+ cmake -DCMAKE_C_COMPILER=${{ matrix.config.cc }} -DSEED= -DBENCH=0 -DARITH=gmp-sec ..
+
+ - name: CMake Build
+ run: cmake --build build
+
+ - name: CMake Test
+ run: |
+ cd build
+ ctest --verbose .
diff --git a/contrib/relic/.github/workflows/gmp.yml b/contrib/relic/.github/workflows/gmp.yml
new file mode 100644
index 000000000..618e05da3
--- /dev/null
+++ b/contrib/relic/.github/workflows/gmp.yml
@@ -0,0 +1,88 @@
+name: Faster configuration (GMP)
+
+on:
+ push:
+ branches:
+ - '**' # all branches
+ pull_request:
+ branches:
+ - '**' # all branches
+
+jobs:
+ build:
+ name: ${{ matrix.config.name }}
+ runs-on: ${{ matrix.config.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ config:
+ - {
+ name: "Windows Latest - MinGW",
+ artifact: "windows-mingw.tar.xz",
+ os: windows-latest,
+ cc: "gcc"
+ }
+ - {
+ name: "Ubuntu Latest - GCC",
+ artifact: "linux-gcc.tar.xz",
+ os: ubuntu-latest,
+ cc: "gcc",
+ }
+ - {
+ name: "Ubuntu Latest - Clang",
+ artifact: "linux-clang.tar.xz",
+ os: ubuntu-latest,
+ cc: "clang",
+ }
+ - {
+ name: "MacOS Latest",
+ os: macos-latest,
+ cc: "clang",
+ }
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Install Linux Dependencies
+ if: runner.os == 'Linux'
+ run: sudo apt install libgmp-dev
+
+ - name: Install MacOS Dependencies
+ if: runner.os == 'MacOS'
+ run: brew install gmp
+
+ - name: Set MinGW enviroment
+ if: ${{ (runner.os == 'Windows') && (matrix.config.cc == 'gcc') }}
+ uses: msys2/setup-msys2@v2
+ with:
+ msystem: MINGW64
+ install: >-
+ git
+ base-devel
+ gcc
+ cmake
+ gmp
+ update: true
+
+ - name: Run CMake (MingW)
+ if: ${{ (runner.os == 'Windows') && (matrix.config.cc == 'gcc') }}
+ shell: bash
+ run: |
+ mkdir build
+ cd build
+ cmake -DSEED= -DBENCH=0 -DARITH=gmp -G "MinGW Makefiles" ..
+
+ - name: Run CMake (standard)
+ if: ${{ !(runner.os == 'Windows') }}
+ shell: bash
+ run: |
+ mkdir build
+ cd build
+ cmake -DCMAKE_C_COMPILER=${{ matrix.config.cc }} -DSEED= -DBENCH=0 -DARITH=gmp ..
+
+ - name: CMake Build
+ run: cmake --build build
+
+ - name: CMake Test
+ run: |
+ cd build
+ ctest --verbose .
diff --git a/contrib/relic/.github/workflows/label.yml b/contrib/relic/.github/workflows/label.yml
new file mode 100644
index 000000000..213531326
--- /dev/null
+++ b/contrib/relic/.github/workflows/label.yml
@@ -0,0 +1,97 @@
+name: Basic configuration (LABEL)
+
+on:
+ push:
+ branches:
+ - '**' # all branches
+ pull_request:
+ branches:
+ - '**' # all branches
+
+jobs:
+ build:
+ name: ${{ matrix.config.name }}
+ runs-on: ${{ matrix.config.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ config:
+ - {
+ name: "Windows Latest - MSVC",
+ artifact: "windows-msvc.tar.xz",
+ os: windows-latest,
+ cc: "cl",
+ }
+ - {
+ name: "Windows Latest - MinGW",
+ artifact: "windows-mingw.tar.xz",
+ os: windows-latest,
+ cc: "gcc"
+ }
+ - {
+ name: "Ubuntu Latest - GCC",
+ artifact: "linux-gcc.tar.xz",
+ os: ubuntu-latest,
+ cc: "gcc",
+ }
+ - {
+ name: "Ubuntu Latest - Clang",
+ artifact: "linux-clang.tar.xz",
+ os: ubuntu-latest,
+ cc: "clang",
+ }
+ - {
+ name: "MacOS Latest",
+ os: macos-latest,
+ cc: "clang",
+ }
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Set Windows enviroment
+ if: ${{ (runner.os == 'Windows') && (matrix.config.cc == 'cl') }}
+ uses: ilammy/msvc-dev-cmd@v1
+
+ - name: Set MinGW enviroment
+ if: ${{ (runner.os == 'Windows') && (matrix.config.cc == 'gcc') }}
+ uses: msys2/setup-msys2@v2
+ with:
+ msystem: MINGW64
+ install: >-
+ git
+ base-devel
+ gcc
+ cmake
+ update: true
+
+ - name: Run CMake (Win)
+ if: ${{ (runner.os == 'Windows') && (matrix.config.cc == 'cl') }}
+ shell: bash
+ run: |
+ mkdir build
+ cd build
+ cmake -DLABEL=default -DSEED= -DBENCH=0 -G "NMake Makefiles" ..
+
+ - name: Run CMake (MingW)
+ if: ${{ (runner.os == 'Windows') && (matrix.config.cc == 'gcc') }}
+ shell: bash
+ run: |
+ mkdir build
+ cd build
+ cmake -DLABEL=default -DSEED= -DBENCH=0 -G "MinGW Makefiles" ..
+
+ - name: Run CMake (standard)
+ if: ${{ !(runner.os == 'Windows') }}
+ shell: bash
+ run: |
+ mkdir build
+ cd build
+ cmake -DCMAKE_C_COMPILER=${{ matrix.config.cc }} -DSEED= -DBENCH=0 ..
+
+ - name: CMake Build
+ run: cmake --build build
+
+ - name: CMake Test
+ run: |
+ cd build
+ ctest --verbose .
diff --git a/contrib/relic/.travis.yml b/contrib/relic/.travis.yml
index 1f98558c5..330d99299 100644
--- a/contrib/relic/.travis.yml
+++ b/contrib/relic/.travis.yml
@@ -20,9 +20,9 @@ env:
# Build for Edwards curves
- CONFIG="-DSEED= -DBENCH=0 -DFP_PRIME=255 -FP_QNRES=off -DEC_METHD=EDDIE -DED_METHD='PROJC;LWNAF;LWNAF;BASIC' -DWITH='BN;DV;MD;FP;ED,EC;CP'" TEST="-E test_fpx"
# Build Supersingular curves
- - CONFIG="-DSEED= -DBENCH=0 -DBN_PRECI=1536 -DFP_PRIME=1536 -FP_QNRES=on" TEST="-E test_fpx"
+ - CONFIG="-DSEED= -DBENCH=0 -DBN_PRECI=1536 -DFP_PRIME=1536 -DFP_QNRES=on" TEST="-E test_fpx"
# Build BLS12-381
- - CONFIG="-DWSIZE=64 -DARITH=x64-asm-382 -DFP_PRIME=381 -DFP_PMERS=off -DFP_QNRES=on"
+ - CONFIG="-DWSIZE=64 -DARITH=x64-asm-6l -DFP_PRIME=381 -DFP_PMERS=off -DFP_QNRES=on"
# Build with Address Sanityzer
- CONFIG="-DAUSAN=on -DSEED= -DBENCH=0" TEST=""
diff --git a/contrib/relic/CMakeLists.txt b/contrib/relic/CMakeLists.txt
index 0348ccc7a..4997612b9 100644
--- a/contrib/relic/CMakeLists.txt
+++ b/contrib/relic/CMakeLists.txt
@@ -1,12 +1,11 @@
cmake_minimum_required(VERSION 3.1)
-set (CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type.")
if(NOT ${CMAKE_VERSION} VERSION_LESS "3.1")
cmake_policy(SET CMP0054 NEW)
endif()
project(RELIC C CXX)
set(PROJECT_VERSION_MAJOR "0")
-set(PROJECT_VERSION_MINOR "5")
+set(PROJECT_VERSION_MINOR "6")
set(PROJECT_VERSION_PATCH "0")
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
set(VERSION ${PROJECT_VERSION})
diff --git a/contrib/relic/README.md b/contrib/relic/README.md
index 0f76be350..c4f3f258b 100644
--- a/contrib/relic/README.md
+++ b/contrib/relic/README.md
@@ -1,12 +1,17 @@
-![](https://github.com/relic-toolkit/relic/blob/master/art/rlc_logo.png)
+![](https://github.com/relic-toolkit/relic/blob/c56f2cc3529da824e76974ccb5d74cb4ff6cdec7/art/rlc_logo.png)
=====
[![Project stats](https://www.openhub.net/p/relic-toolkit/widgets/project_thin_badge.gif)](https://www.openhub.net/p/relic-toolkit)
-[![Build Status](https://travis-ci.org/relic-toolkit/relic.svg?branch=main)](https://travis-ci.org/relic-toolkit/relic)
[![Code Quality: Cpp](https://img.shields.io/lgtm/grade/cpp/g/relic-toolkit/relic.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/relic-toolkit/relic/context:cpp)
[![Total Alerts](https://img.shields.io/lgtm/alerts/g/relic-toolkit/relic.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/relic-toolkit/relic/alerts)
-RELIC is a modern cryptographic meta-toolkit with emphasis on efficiency and flexibility. RELIC can be used to build efficient and usable cryptographic toolkits tailored for specific security levels and algorithmic choices.
+[![Travis Status](https://travis-ci.org/relic-toolkit/relic.svg?branch=main)](https://travis-ci.org/relic-toolkit/relic)
+[![GHA Status](https://github.com/relic-toolkit/relic/actions/workflows/easy.yml/badge.svg)](https://github.com/relic-toolkit/relic/actions/workflows/easy.yml)
+[![GHA Status](https://github.com/relic-toolkit/relic/actions/workflows/gmp.yml/badge.svg)](https://github.com/relic-toolkit/relic/actions/workflows/gmp.yml)
+[![GHA Status](https://github.com/relic-toolkit/relic/actions/workflows/bls12-381.yml/badge.svg)](https://github.com/relic-toolkit/relic/actions/workflows/bls12-381.yml)
+
+
+RELIC is a modern research-oriented cryptographic meta-toolkit with emphasis on efficiency and flexibility. RELIC can be used to build efficient and usable cryptographic toolkits tailored for specific security levels and algorithmic choices.
### Goals
diff --git a/contrib/relic/bench/bench_bn.c b/contrib/relic/bench/bench_bn.c
index b9acffcf8..63b6b662c 100644
--- a/contrib/relic/bench/bench_bn.c
+++ b/contrib/relic/bench/bench_bn.c
@@ -51,7 +51,7 @@ static void memory(void) {
bn_new(a[i]);
bn_clean(a[i]);
}
- BENCH_FEW("bn_init", bn_init(a[i], RLC_BN_DIGS), 1);
+ BENCH_FEW("bn_make", bn_make(a[i], RLC_BN_DIGS), 1);
for (int i = 0; i < BENCH; i++) {
bn_free(a[i]);
}
@@ -281,21 +281,21 @@ static void util(void) {
}
static void arith(void) {
- bn_t a, b, c, d, e;
+ bn_t a, b, c, d[2];
dig_t f;
int len;
bn_null(a);
bn_null(b);
bn_null(c);
- bn_null(d);
- bn_null(e);
+ bn_null(d[0]);
+ bn_null(d[1]);
bn_new(a);
bn_new(b);
bn_new(c);
- bn_new(d);
- bn_new(e);
+ bn_new(d[0]);
+ bn_new(d[1]);
BENCH_RUN("bn_add") {
bn_rand(a, RLC_POS, RLC_BN_BITS);
@@ -433,7 +433,7 @@ static void arith(void) {
BENCH_RUN("bn_div_rem") {
bn_rand(a, RLC_POS, 2 * RLC_BN_BITS - RLC_DIG / 2);
bn_rand(b, RLC_POS, RLC_BN_BITS);
- BENCH_ADD(bn_div_rem(c, d, a, b));
+ BENCH_ADD(bn_div_rem(c, d[0], a, b));
}
BENCH_END;
@@ -483,9 +483,9 @@ static void arith(void) {
if (bn_is_even(b)) {
bn_add_dig(b, b, 1);
}
- bn_mod_pre(d, b);
+ bn_mod_pre(d[0], b);
#endif
- BENCH_ADD(bn_mod(c, a, b, d));
+ BENCH_ADD(bn_mod(c, a, b, d[0]));
}
BENCH_END;
@@ -501,7 +501,7 @@ static void arith(void) {
#if BN_MOD == BARRT || !defined(STRIP)
BENCH_RUN("bn_mod_pre_barrt") {
bn_rand(b, RLC_POS, RLC_BN_BITS);
- BENCH_ADD(bn_mod_pre_barrt(d, b));
+ BENCH_ADD(bn_mod_pre_barrt(d[0], b));
}
BENCH_END;
#endif
@@ -510,8 +510,8 @@ static void arith(void) {
BENCH_RUN("bn_mod_barrt") {
bn_rand(a, RLC_POS, 2 * RLC_BN_BITS - RLC_DIG / 2);
bn_rand(b, RLC_POS, RLC_BN_BITS);
- bn_mod_pre_barrt(d, b);
- BENCH_ADD(bn_mod_barrt(c, a, b, d));
+ bn_mod_pre_barrt(d[0], b);
+ BENCH_ADD(bn_mod_barrt(c, a, b, d[0]));
}
BENCH_END;
#endif
@@ -522,7 +522,7 @@ static void arith(void) {
if (bn_is_even(b)) {
bn_add_dig(b, b, 1);
}
- BENCH_ADD(bn_mod_pre_monty(d, b));
+ BENCH_ADD(bn_mod_pre_monty(d[0], b));
}
BENCH_END;
@@ -544,8 +544,8 @@ static void arith(void) {
bn_add_dig(b, b, 1);
}
bn_mod(a, a, b);
- bn_mod_pre_monty(d, b);
- BENCH_ADD(bn_mod_monty(c, a, b, d));
+ bn_mod_pre_monty(d[0], b);
+ BENCH_ADD(bn_mod_monty(c, a, b, d[0]));
}
BENCH_END;
@@ -557,8 +557,8 @@ static void arith(void) {
bn_add_dig(b, b, 1);
}
bn_mod(a, a, b);
- bn_mod_pre_monty(d, b);
- BENCH_ADD(bn_mod_monty_basic(c, a, b, d));
+ bn_mod_pre_monty(d[0], b);
+ BENCH_ADD(bn_mod_monty_basic(c, a, b, d[0]));
}
BENCH_END;
#endif
@@ -571,8 +571,8 @@ static void arith(void) {
bn_add_dig(b, b, 1);
}
bn_mod(a, a, b);
- bn_mod_pre_monty(d, b);
- BENCH_ADD(bn_mod_monty_comba(c, a, b, d));
+ bn_mod_pre_monty(d[0], b);
+ BENCH_ADD(bn_mod_monty_comba(c, a, b, d[0]));
}
BENCH_END;
#endif
@@ -584,7 +584,7 @@ static void arith(void) {
bn_add_dig(b, b, 1);
}
bn_mod(a, a, b);
- bn_mod_pre_monty(d, b);
+ bn_mod_pre_monty(d[0], b);
BENCH_ADD(bn_mod_monty_back(c, c, b));
}
BENCH_END;
@@ -596,7 +596,7 @@ static void arith(void) {
bn_set_2b(b, RLC_BN_BITS);
bn_rand(c, RLC_POS, RLC_DIG);
bn_sub(b, b, c);
- BENCH_ADD(bn_mod_pre_pmers(d, b));
+ BENCH_ADD(bn_mod_pre_pmers(d[0], b));
}
BENCH_END;
@@ -605,8 +605,8 @@ static void arith(void) {
bn_set_2b(b, RLC_BN_BITS);
bn_rand(c, RLC_POS, RLC_DIG);
bn_sub(b, b, c);
- bn_mod_pre_pmers(d, b);
- BENCH_ADD(bn_mod_pmers(c, a, b, d));
+ bn_mod_pre_pmers(d[0], b);
+ BENCH_ADD(bn_mod_pmers(c, a, b, d[0]));
}
BENCH_END;
#endif
@@ -656,8 +656,8 @@ static void arith(void) {
BENCH_RUN("bn_mxp_dig") {
bn_rand(a, RLC_POS, RLC_BN_BITS);
- bn_rand(d, RLC_POS, RLC_DIG);
- bn_get_dig(&f, d);
+ bn_rand(d[0], RLC_POS, RLC_DIG);
+ bn_get_dig(&f, d[0]);
BENCH_ADD(bn_mxp_dig(c, a, f, b));
}
BENCH_END;
@@ -713,7 +713,7 @@ static void arith(void) {
BENCH_RUN("bn_gcd_ext") {
bn_rand(a, RLC_POS, RLC_BN_BITS);
bn_rand(b, RLC_POS, RLC_BN_BITS);
- BENCH_ADD(bn_gcd_ext(c, d, e, a, b));
+ BENCH_ADD(bn_gcd_ext(c, d[0], d[1], a, b));
}
BENCH_END;
@@ -721,7 +721,7 @@ static void arith(void) {
BENCH_RUN("bn_gcd_ext_basic") {
bn_rand(a, RLC_POS, RLC_BN_BITS);
bn_rand(b, RLC_POS, RLC_BN_BITS);
- BENCH_ADD(bn_gcd_ext_basic(c, d, e, a, b));
+ BENCH_ADD(bn_gcd_ext_basic(c, d[0], d[1], a, b));
}
BENCH_END;
#endif
@@ -730,7 +730,7 @@ static void arith(void) {
BENCH_RUN("bn_gcd_ext_lehme") {
bn_rand(a, RLC_POS, RLC_BN_BITS);
bn_rand(b, RLC_POS, RLC_BN_BITS);
- BENCH_ADD(bn_gcd_ext_lehme(c, d, e, a, b));
+ BENCH_ADD(bn_gcd_ext_lehme(c, d[0], d[1], a, b));
}
BENCH_END;
#endif
@@ -739,7 +739,7 @@ static void arith(void) {
BENCH_RUN("bn_gcd_ext_stein") {
bn_rand(a, RLC_POS, RLC_BN_BITS);
bn_rand(b, RLC_POS, RLC_BN_BITS);
- BENCH_ADD(bn_gcd_ext_stein(c, d, e, a, b));
+ BENCH_ADD(bn_gcd_ext_stein(c, d[0], d[1], a, b));
}
BENCH_END;
#endif
@@ -747,14 +747,14 @@ static void arith(void) {
BENCH_RUN("bn_gcd_ext_mid") {
bn_rand(a, RLC_POS, RLC_BN_BITS);
bn_rand(b, RLC_POS, RLC_BN_BITS);
- BENCH_ADD(bn_gcd_ext_mid(c, c, d, d, a, b));
+ BENCH_ADD(bn_gcd_ext_mid(c, c, d[0], d[1], a, b));
}
BENCH_END;
BENCH_RUN("bn_gcd_ext_dig") {
bn_rand(a, RLC_POS, RLC_BN_BITS);
bn_rand(b, RLC_POS, RLC_DIG);
- BENCH_ADD(bn_gcd_ext_dig(c, d, e, a, b->dp[0]));
+ BENCH_ADD(bn_gcd_ext_dig(c, d[0], d[1], a, b->dp[0]));
}
BENCH_END;
@@ -769,7 +769,7 @@ static void arith(void) {
BENCH_RUN("bn_smb_leg") {
bn_rand(a, RLC_POS, RLC_BN_BITS);
- BENCH_ADD(bn_smb_leg(c, a, b));
+ BENCH_ADD(bn_smb_leg(a, b));
}
BENCH_END;
@@ -779,7 +779,7 @@ static void arith(void) {
if (bn_is_even(b)) {
bn_add_dig(b, b, 1);
}
- BENCH_ADD(bn_smb_jac(c, a, b));
+ BENCH_ADD(bn_smb_jac(a, b));
}
BENCH_END;
@@ -812,6 +812,14 @@ static void arith(void) {
}
BENCH_END;
+ /* It should be the case that a is prime here. */
+ BENCH_RUN("bn_mod_inv_sim (2)") {
+ bn_rand(d[0], RLC_POS, RLC_BN_BITS);
+ bn_rand(d[1], RLC_POS, RLC_BN_BITS);
+ BENCH_ADD(bn_mod_inv_sim(d, d, a, 2));
+ }
+ BENCH_END;
+
bn_rand(a, RLC_POS, RLC_BN_BITS);
BENCH_ONE("bn_factor", bn_factor(c, a), 1);
@@ -838,7 +846,7 @@ static void arith(void) {
BENCH_END;
BENCH_RUN("bn_rec_naf") {
- signed char naf[RLC_BN_BITS + 1];
+ int8_t naf[RLC_BN_BITS + 1];
int len;
bn_rand(a, RLC_POS, RLC_BN_BITS);
BENCH_ADD((len = RLC_BN_BITS + 1, bn_rec_naf(naf, &len, a, 4)));
@@ -848,10 +856,10 @@ static void arith(void) {
#if defined(WITH_EB) && defined(EB_KBLTZ) && (EB_MUL == LWNAF || EB_MUL == RWNAF || EB_FIX == LWNAF || EB_SIM == INTER || !defined(STRIP))
if (eb_param_set_any_kbltz() == RLC_OK) {
BENCH_RUN("bn_rec_tnaf") {
- signed char tnaf[RLC_FB_BITS + 8];
+ int8_t tnaf[RLC_FB_BITS + 8];
int len = RLC_BN_BITS + 1;
- eb_curve_get_ord(e);
- bn_rand_mod(a, e);
+ eb_curve_get_ord(d[1]);
+ bn_rand_mod(a, d[1]);
if (eb_curve_opt_a() == RLC_ZERO) {
BENCH_ADD((len = RLC_FB_BITS + 8, bn_rec_tnaf(tnaf, &len, a, -1, RLC_FB_BITS, 4)));
} else {
@@ -861,9 +869,9 @@ static void arith(void) {
BENCH_END;
BENCH_RUN("bn_rec_rtnaf") {
- signed char tnaf[RLC_FB_BITS + 8];
- eb_curve_get_ord(e);
- bn_rand_mod(a, e);
+ int8_t tnaf[RLC_FB_BITS + 8];
+ eb_curve_get_ord(d[1]);
+ bn_rand_mod(a, d[1]);
if (eb_curve_opt_a() == RLC_ZERO) {
BENCH_ADD((len = RLC_FB_BITS + 8, bn_rec_rtnaf(tnaf, &len, a, -1, RLC_FB_BITS, 4)));
} else {
@@ -875,7 +883,7 @@ static void arith(void) {
#endif
BENCH_RUN("bn_rec_reg") {
- signed char naf[RLC_BN_BITS + 1];
+ int8_t naf[RLC_BN_BITS + 1];
int len = RLC_BN_BITS + 1;
bn_rand(a, RLC_POS, RLC_BN_BITS);
BENCH_ADD((len = RLC_BN_BITS + 1, bn_rec_reg(naf, &len, a, RLC_BN_BITS, 4)));
@@ -883,7 +891,7 @@ static void arith(void) {
BENCH_END;
BENCH_RUN("bn_rec_jsf") {
- signed char jsf[2 * (RLC_BN_BITS + 1)];
+ int8_t jsf[2 * (RLC_BN_BITS + 1)];
bn_rand(a, RLC_POS, RLC_BN_BITS);
bn_rand(b, RLC_POS, RLC_BN_BITS);
BENCH_ADD((len = 2 * (RLC_BN_BITS + 1), bn_rec_jsf(jsf, &len, a, b)));
@@ -903,9 +911,9 @@ static void arith(void) {
bn_rand(a, RLC_POS, RLC_FP_BITS);
ep_curve_get_v1(v1);
ep_curve_get_v2(v2);
- ep_curve_get_ord(e);
- bn_rand_mod(a, e);
- BENCH_ADD(bn_rec_glv(b, c, a, e, (const bn_t *)v1,
+ ep_curve_get_ord(d[1]);
+ bn_rand_mod(a, d[1]);
+ BENCH_ADD(bn_rec_glv(b, c, a, d[1], (const bn_t *)v1,
(const bn_t *)v2));
}
BENCH_END;
@@ -920,8 +928,8 @@ static void arith(void) {
bn_free(a);
bn_free(b);
bn_free(c);
- bn_free(d);
- bn_free(e);
+ bn_free(d[0]);
+ bn_free(d[1]);
}
int main(void) {
diff --git a/contrib/relic/bench/bench_cp.c b/contrib/relic/bench/bench_cp.c
index 5bf1aafd6..70405f263 100644
--- a/contrib/relic/bench/bench_cp.c
+++ b/contrib/relic/bench/bench_cp.c
@@ -472,6 +472,7 @@ static void vbnn(void) {
}
BENCH_END;
+ bn_free(z);
bn_free(h);
bn_free(msk);
bn_free(ska);
@@ -482,10 +483,389 @@ static void vbnn(void) {
ec_free(pkb);
}
+#define MAX_KEYS RLC_MAX(BENCH, 16)
+#define MIN_KEYS RLC_MIN(BENCH, 16)
+
+static void ers(void) {
+ int size;
+ ec_t pp, pk[MAX_KEYS + 1];
+ bn_t sk[MAX_KEYS + 1], td;
+ ers_t ring[MAX_KEYS + 1];
+ uint8_t m[5] = { 0, 1, 2, 3, 4 };
+
+ bn_null(td);
+ ec_null(pp);
+
+ bn_new(td);
+ ec_new(pp);
+ for (int i = 0; i <= MAX_KEYS; i++) {
+ bn_null(sk[i]);
+ bn_new(sk[i]);
+ ec_null(pk[i]);
+ ec_new(pk[i]);
+ ers_null(ring[i]);
+ ers_new(ring[i]);
+ cp_ers_gen_key(sk[i], pk[i]);
+ }
+
+ cp_ers_gen(pp);
+
+ BENCH_RUN("cp_ers_sig") {
+ BENCH_ADD(cp_ers_sig(td, ring[0], m, 5, sk[0], pk[0], pp));
+ } BENCH_END;
+
+ BENCH_RUN("cp_ers_ver") {
+ BENCH_ADD(cp_ers_ver(td, ring, 1, m, 5, pp));
+ } BENCH_END;
+
+ size = 1;
+ BENCH_FEW("cp_ers_ext", cp_ers_ext(td, ring, &size, m, 5, pk[size], pp), 1);
+
+ size = 1;
+ cp_ers_sig(td, ring[0], m, 5, sk[0], pk[0], pp);
+ for (int j = 1; j < MAX_KEYS && size < BENCH; j = j << 1) {
+ for (int k = 0; k < j && size < BENCH; k++) {
+ cp_ers_ext(td, ring, &size, m, 5, pk[size], pp);
+ }
+ cp_ers_ver(td, ring, size, m, 5, pp);
+ util_print("(%2d exts) ", j);
+ BENCH_FEW("cp_ers_ver", cp_ers_ver(td, ring, size, m, 5, pp), 1);
+ }
+
+ bn_free(td);
+ ec_free(pp);
+ for (int i = 0; i <= MAX_KEYS; i++) {
+ bn_free(sk[i]);
+ ec_free(pk[i]);
+ ers_free(ring[i])
+ }
+}
+
+static void smlers(void) {
+ int size;
+ ec_t pp, pk[MAX_KEYS + 1];
+ bn_t sk[MAX_KEYS + 1], td;
+ smlers_t ring[MAX_KEYS + 1];
+ uint8_t m[5] = { 0, 1, 2, 3, 4 };
+
+ bn_null(td);
+ ec_null(pp);
+
+ bn_new(td);
+ ec_new(pp);
+ for (int i = 0; i <= MAX_KEYS; i++) {
+ bn_null(sk[i]);
+ bn_new(sk[i]);
+ ec_null(pk[i]);
+ ec_new(pk[i]);
+ smlers_null(ring[i]);
+ smlers_new(ring[i]);
+ cp_ers_gen_key(sk[i], pk[i]);
+ }
+
+ cp_ers_gen(pp);
+
+ BENCH_RUN("cp_smlers_sig") {
+ BENCH_ADD(cp_smlers_sig(td, ring[0], m, 5, sk[0], pk[0], pp));
+ } BENCH_END;
+
+ BENCH_RUN("cp_smlers_ver") {
+ BENCH_ADD(cp_smlers_ver(td, ring, 1, m, 5, pp));
+ } BENCH_END;
+
+ size = 1;
+ BENCH_FEW("cp_smlers_ext", cp_smlers_ext(td, ring, &size, m, 5, pk[size], pp), 1);
+
+ size = 1;
+ cp_smlers_sig(td, ring[0], m, 5, sk[0], pk[0], pp);
+ for (int j = 1; j < MAX_KEYS && size < BENCH; j = j << 1) {
+ for (int k = 0; k < j && size < BENCH; k++) {
+ cp_smlers_ext(td, ring, &size, m, 5, pk[size], pp);
+ }
+ cp_smlers_ver(td, ring, size, m, 5, pp);
+ util_print("(%2d exts) ", j);
+ BENCH_FEW("cp_smlers_ver", cp_smlers_ver(td, ring, size, m, 5, pp), 1);
+ }
+
+ bn_free(td);
+ ec_free(pp);
+ for (int i = 0; i <= MAX_KEYS; i++) {
+ bn_free(sk[i]);
+ ec_free(pk[i]);
+ smlers_free(ring[i])
+ }
+}
+
+static void etrs(void) {
+ int size;
+ ec_t pp, pk[MAX_KEYS + 1];
+ bn_t sk[MAX_KEYS + 1], td[MAX_KEYS + 1], y[MAX_KEYS + 1];
+ etrs_t ring[MAX_KEYS + 1];
+ uint8_t m[5] = { 0, 1, 2, 3, 4 };
+
+ ec_null(pp);
+ ec_new(pp);
+ for (int i = 0; i <= MAX_KEYS; i++) {
+ bn_null(td[i]);
+ bn_new(td[i]);
+ bn_null(y[i]);
+ bn_new(y[i]);
+ bn_null(sk[i]);
+ bn_new(sk[i]);
+ ec_null(pk[i]);
+ ec_new(pk[i]);
+ etrs_null(ring[i]);
+ etrs_new(ring[i]);
+ ec_curve_get_ord(sk[i]);
+ bn_rand_mod(td[i], sk[i]);
+ bn_rand_mod(y[i], sk[i]);
+ cp_ers_gen_key(sk[i], pk[i]);
+ }
+
+ cp_ers_gen(pp);
+
+ BENCH_FEW("cp_etrs_sig", cp_etrs_sig(td, y, MIN_KEYS, ring[0], m, 5, sk[0], pk[0], pp), 1);
+
+ BENCH_FEW("cp_etrs_ver", cp_etrs_ver(1, td, y, MIN_KEYS, ring, 1, m, 5, pp), 1);
+
+ size = 1;
+ BENCH_FEW("cp_etrs_ext", (size = 1, cp_etrs_ext(td, y, MIN_KEYS, ring, &size, m, 5, pk[size], pp)), 1);
+
+ size = 1;
+ cp_etrs_sig(td, y, MIN_KEYS, ring[0], m, 5, sk[0], pk[0], pp);
+ BENCH_FEW("cp_etrs_uni", cp_etrs_uni(1, td, y, MIN_KEYS, ring, &size, m, 5, sk[size], pk[size], pp), 1);
+
+ size = 1;
+ cp_etrs_sig(td, y, MIN_KEYS, ring[0], m, 5, sk[0], pk[0], pp);
+ for (int j = 1; j < MIN_KEYS && size < MIN_KEYS; j = j << 1) {
+ for (int k = 0; k < j && size < MIN_KEYS; k++) {
+ cp_etrs_ext(td, y, MIN_KEYS, ring, &size, m, 5, pk[size], pp);
+ }
+ cp_etrs_ver(1, td+size-1, y+size-1, MIN_KEYS-size+1, ring, size, m, 5, pp);
+ util_print("(%2d exts) ", j);
+ BENCH_FEW("cp_etrs_ver", cp_etrs_ver(1, td+size-1, y+size-1, MIN_KEYS-size+1, ring, size, m, 5, pp), 1);
+ }
+
+ ec_free(pp);
+ for (int i = 0; i <= MAX_KEYS; i++) {
+ bn_free(td[i]);
+ bn_free(y[i]);
+ bn_free(sk[i]);
+ ec_free(pk[i]);
+ etrs_free(ring[i])
+ }
+}
+
#endif /* WITH_EC */
#if defined(WITH_PC)
+static void pdpub(void) {
+ bn_t r1, r2;
+ g1_t p, u1, v1;
+ g2_t q, u2, v2, w2;
+ gt_t e, r, g[3];
+
+ bn_null(r1);
+ bn_null(r2);
+ g1_null(p);
+ g1_null(u1);
+ g1_null(v1);
+ g2_null(q);
+ g2_null(u2);
+ g2_null(v2);
+ g2_null(w2);
+ gt_null(e);
+ gt_null(r);
+ gt_null(g[0]);
+ gt_null(g[1]);
+ gt_null(g[2]);
+
+ bn_new(r1);
+ bn_new(r2);
+ g1_new(p);
+ g1_new(u1);
+ g1_new(v1);
+ g2_new(q);
+ g2_new(u2);
+ g2_new(v2);
+ g2_new(w2);
+ gt_new(e);
+ gt_new(r);
+ gt_new(g[0]);
+ gt_new(g[1]);
+ gt_new(g[2]);
+
+ BENCH_RUN("cp_pdpub_gen") {
+ BENCH_ADD(cp_pdpub_gen(r1, r2, u1, u2, v2, e));
+ } BENCH_END;
+
+ BENCH_RUN("cp_pdpub_ask") {
+ g1_rand(p);
+ g2_rand(q);
+ BENCH_ADD(cp_pdpub_ask(v1, w2, p, q, r1, r2, u1, u2, v2));
+ } BENCH_END;
+
+ BENCH_RUN("cp_pdpub_ans") {
+ g1_rand(p);
+ g2_rand(q);
+ BENCH_ADD(cp_pdpub_ans(g, p, q, v1, v2, w2));
+ } BENCH_END;
+
+ BENCH_RUN("cp_pdpub_ver") {
+ g1_rand(p);
+ g2_rand(q);
+ pc_map(e, p, q);
+ BENCH_ADD(cp_pdpub_ver(r, g, r1, e));
+ } BENCH_END;
+
+ BENCH_RUN("cp_lvpub_gen") {
+ BENCH_ADD(cp_lvpub_gen(r2, u1, u2, v2, e));
+ } BENCH_END;
+
+ BENCH_RUN("cp_lvpub_ask") {
+ g1_rand(p);
+ g2_rand(q);
+ BENCH_ADD(cp_lvpub_ask(r1, v1, w2, p, q, r2, u1, u2, v2));
+ } BENCH_END;
+
+ BENCH_RUN("cp_lvpub_ans") {
+ g1_rand(p);
+ g2_rand(q);
+ BENCH_ADD(cp_lvpub_ans(g, p, q, v1, v2, w2));
+ } BENCH_END;
+
+ BENCH_RUN("cp_lvpub_ver") {
+ g1_rand(p);
+ g2_rand(q);
+ pc_map(e, p, q);
+ BENCH_ADD(cp_lvpub_ver(r, g, r1, e));
+ } BENCH_END;
+
+ bn_free(r1);
+ bn_free(r2);
+ g1_free(p);
+ g1_free(u1);
+ g1_free(v1);
+ g2_free(q);
+ g2_free(u2);
+ g2_free(v2);
+ g2_free(w2);
+ gt_free(e);
+ gt_free(r);
+ gt_free(g[0]);
+ gt_free(g[1]);
+ gt_free(g[2]);
+}
+
+static void pdprv(void) {
+ bn_t r1, r2[3];
+ g1_t p, u1[2], v1[3];
+ g2_t q, u2[2], v2[4], w2[4];
+ gt_t e[2], r, g[4];
+
+ bn_null(r1);
+ g1_null(p);
+ g2_null(q);
+ gt_null(r);
+ for (int i = 0; i < 2; i++) {
+ g1_null(u1[i]);
+ g2_null(u2[i]);
+ gt_null(e[i]);
+ }
+ for (int i = 0; i < 3; i++) {
+ g1_null(v1[i]);
+ bn_null(r2[i]);
+ }
+ for (int i = 0; i < 4; i++) {
+ g2_null(v2[i]);
+ g2_null(w2[i]);
+ gt_null(g[i]);
+ }
+
+ bn_new(r1);
+ g1_new(p);
+ g2_new(q);
+ gt_new(r);
+ for (int i = 0; i < 2; i++) {
+ g1_new(u1[i]);
+ g2_new(u2[i]);
+ gt_new(e[i]);
+ }
+ for (int i = 0; i < 3; i++) {
+ g1_new(v1[i]);
+ bn_new(r2[i]);
+ }
+ for (int i = 0; i < 4; i++) {
+ g2_new(v2[i]);
+ g2_new(w2[i]);
+ gt_new(g[i]);
+ }
+
+ BENCH_RUN("cp_pdprv_gen") {
+ BENCH_ADD(cp_pdprv_gen(r1, r2, u1, u2, v2, e));
+ } BENCH_END;
+
+ BENCH_RUN("cp_pdprv_ask") {
+ g1_rand(p);
+ g2_rand(q);
+ BENCH_ADD(cp_pdprv_ask(v1, w2, p, q, r1, r2, u1, u2, v2));
+ } BENCH_END;
+
+ BENCH_RUN("cp_pdprv_ans") {
+ g1_rand(p);
+ g2_rand(q);
+ BENCH_ADD(cp_pdprv_ans(g, v1, w2));
+ } BENCH_END;
+
+ BENCH_RUN("cp_pdprv_ver") {
+ g1_rand(p);
+ g2_rand(q);
+ BENCH_ADD(cp_pdprv_ver(r, g, r1, e));
+ } BENCH_END;
+
+ BENCH_RUN("cp_lvprv_gen") {
+ BENCH_ADD(cp_lvprv_gen(r1, r2, u1, u2, v2, e));
+ } BENCH_END;
+
+ BENCH_RUN("cp_lvprv_ask") {
+ g1_rand(p);
+ g2_rand(q);
+ BENCH_ADD(cp_lvprv_ask(v1, w2, p, q, r1, r2, u1, u2, v2));
+ } BENCH_END;
+
+ BENCH_RUN("cp_lvprv_ans") {
+ g1_rand(p);
+ g2_rand(q);
+ BENCH_ADD(cp_lvprv_ans(g, v1, w2));
+ } BENCH_END;
+
+ BENCH_RUN("cp_lvprv_ver") {
+ g1_rand(p);
+ g2_rand(q);
+ BENCH_ADD(cp_lvprv_ver(r, g, r1, e));
+ } BENCH_END;
+
+ bn_free(r1);
+ g1_free(p);
+ g2_free(q);
+ gt_free(r);
+ for (int i = 0; i < 2; i++) {
+ g1_free(u1[i]);
+ g2_free(u2[i]);
+ gt_free(e[i]);
+ }
+ for (int i = 0; i < 3; i++) {
+ g1_free(v1[i]);
+ bn_free(r2[i]);
+ }
+ for (int i = 0; i < 4; i++) {
+ g2_free(v2[i]);
+ g2_free(w2[i]);
+ gt_free(g[i]);
+ }
+}
+
static void sokaka(void) {
sokaka_t k;
bn_t s;
@@ -1425,6 +1805,76 @@ static void lhs(void) {
}
}
+#define M 5 /* Number of server messages (larger). */
+#define N 2 /* Number of client messages. */
+
+static void psi(void) {
+ bn_t q, r, x[M], y[N], z[M];
+ g1_t d, s[M + 1];
+ g2_t u[M], ss;
+ gt_t t[M];
+ int len;
+
+ bn_new(q);
+ bn_new(r);
+ g1_new(d);
+ g2_new(ss);
+ for (int i = 0; i < M; i++) {
+ bn_null(x[i]);
+ bn_null(z[i]);
+ g1_null(s[i]);
+ bn_new(x[i]);
+ bn_new(z[i]);
+ g1_new(s[i]);
+ }
+ for (int i = 0; i < N; i++) {
+ bn_null(y[i]);
+ g2_null(u[i]);
+ gt_null(t[i]);
+ bn_new(y[i]);
+ g2_new(u[i]);
+ }
+
+ pc_get_ord(q);
+ for (int j = 0; j < M; j++) {
+ bn_rand_mod(x[j], q);
+ }
+ for (int j = 0; j < N; j++) {
+ bn_rand_mod(y[j], q);
+ }
+
+ BENCH_RUN("cp_lapsi_gen (5)") {
+ BENCH_ADD(cp_lapsi_gen(q, ss, s, M));
+ } BENCH_END;
+
+ BENCH_RUN("cp_lapsi_ask (5)") {
+ BENCH_ADD(cp_lapsi_ask(d, r, x, s, M));
+ } BENCH_END;
+
+ BENCH_RUN("cp_lapsi_ans (2)") {
+ BENCH_ADD(cp_lapsi_ans(t, u, d, ss, y, N));
+ } BENCH_END;
+
+ BENCH_RUN("cp_lapsi_int") {
+ BENCH_ADD(cp_lapsi_int(z, &len, q, d, x, M, t, u, N));
+ } BENCH_END;
+
+ bn_free(q);
+ bn_free(r);
+ g1_free(d);
+ g2_free(ss);
+ for (int i = 0; i < M; i++) {
+ bn_free(x[i]);
+ bn_free(z[i]);
+ g1_free(s[i]);
+ }
+ for (int i = 0; i < N; i++) {
+ bn_free(y[i]);
+ g2_free(u[i]);
+ gt_free(t[i]);
+ }
+}
+
#endif /* WITH_PC */
int main(void) {
@@ -1446,22 +1896,25 @@ int main(void) {
#endif
#if defined(WITH_EC)
- util_banner("Protocols based on elliptic curves:\n", 0);
if (ec_param_set_any() == RLC_OK) {
+ util_banner("Protocols based on elliptic curves:\n", 0);
ecdh();
ecmqv();
ecies();
ecdsa();
ecss();
vbnn();
- } else {
- RLC_THROW(ERR_NO_CURVE);
+ ers();
+ smlers();
+ etrs();
}
#endif
#if defined(WITH_PC)
- util_banner("Protocols based on pairings:\n", 0);
if (pc_param_set_any() == RLC_OK) {
+ util_banner("Protocols based on pairings:\n", 0);
+ pdpub();
+ pdprv();
sokaka();
ibe();
bgn();
@@ -1474,8 +1927,7 @@ int main(void) {
#endif
zss();
lhs();
- } else {
- RLC_THROW(ERR_NO_CURVE);
+ psi();
}
#endif
diff --git a/contrib/relic/bench/bench_ed.c b/contrib/relic/bench/bench_ed.c
index 7dfa39424..5dc267dc1 100644
--- a/contrib/relic/bench/bench_ed.c
+++ b/contrib/relic/bench/bench_ed.c
@@ -326,7 +326,7 @@ static void arith(void) {
BENCH_ADD(ed_sub_extnd(r, p, q));
} BENCH_END;
- BENCH_RUN("ed_sub_projc (z2 = 1)") {
+ BENCH_RUN("ed_sub_extnd (z2 = 1)") {
ed_rand(p);
ed_rand(q);
ed_add_extnd(p, p, q);
@@ -335,12 +335,12 @@ static void arith(void) {
BENCH_ADD(ed_sub_extnd(r, p, q));
} BENCH_END;
- BENCH_RUN("ed_sub_projc (z1,z2 = 1)") {
+ BENCH_RUN("ed_sub_extnd (z1,z2 = 1)") {
ed_rand(p);
ed_norm(p, p);
ed_rand(q);
ed_norm(q, q);
- BENCH_ADD(ed_sub_projc(r, p, q));
+ BENCH_ADD(ed_sub_extnd(r, p, q));
} BENCH_END;
#endif
@@ -373,7 +373,7 @@ static void arith(void) {
} BENCH_END;
#endif
-#if ED_ADD == PROJC || !defined(STRIP)
+#if ED_ADD == EXTND || !defined(STRIP)
BENCH_RUN("ed_dbl_extnd") {
ed_rand(p);
ed_rand(q);
diff --git a/contrib/relic/bench/bench_ep.c b/contrib/relic/bench/bench_ep.c
index bd95bb56c..04ccdfc83 100644
--- a/contrib/relic/bench/bench_ep.c
+++ b/contrib/relic/bench/bench_ep.c
@@ -188,7 +188,7 @@ static void util(void) {
static void arith(void) {
ep_t p, q, r, t[RLC_EP_TABLE_MAX];
- bn_t k, l, n;
+ bn_t k, l[2], n;
ep_null(p);
ep_null(q);
@@ -202,7 +202,8 @@ static void arith(void) {
ep_new(r);
bn_new(k);
bn_new(n);
- bn_new(l);
+ bn_new(l[0]);
+ bn_new(l[1]);
ep_curve_get_ord(n);
@@ -498,60 +499,76 @@ static void arith(void) {
}
#endif
BENCH_RUN("ep_mul_sim") {
- bn_rand_mod(k, n);
- bn_rand_mod(l, n);
+ bn_rand_mod(l[0], n);
+ bn_rand_mod(l[1], n);
ep_rand(p);
ep_rand(q);
- BENCH_ADD(ep_mul_sim(r, p, k, q, l));
+ BENCH_ADD(ep_mul_sim(r, p, l[0], q, l[1]));
} BENCH_END;
#if EP_SIM == BASIC || !defined(STRIP)
BENCH_RUN("ep_mul_sim_basic") {
- bn_rand_mod(k, n);
- bn_rand_mod(l, n);
+ bn_rand_mod(l[0], n);
+ bn_rand_mod(l[1], n);
ep_rand(p);
ep_rand(q);
- BENCH_ADD(ep_mul_sim_basic(r, p, k, q, l));
+ BENCH_ADD(ep_mul_sim_basic(r, p, l[0], q, l[1]));
} BENCH_END;
#endif
#if EP_SIM == TRICK || !defined(STRIP)
BENCH_RUN("ep_mul_sim_trick") {
- bn_rand_mod(k, n);
- bn_rand_mod(l, n);
+ bn_rand_mod(l[0], n);
+ bn_rand_mod(l[1], n);
ep_rand(p);
ep_rand(q);
- BENCH_ADD(ep_mul_sim_trick(r, p, k, q, l));
+ BENCH_ADD(ep_mul_sim_trick(r, p, l[0], q, l[1]));
} BENCH_END;
#endif
#if EP_SIM == INTER || !defined(STRIP)
BENCH_RUN("ep_mul_sim_inter") {
- bn_rand_mod(k, n);
- bn_rand_mod(l, n);
+ bn_rand_mod(l[0], n);
+ bn_rand_mod(l[1], n);
ep_rand(p);
ep_rand(q);
- BENCH_ADD(ep_mul_sim_inter(r, p, k, q, l));
+ BENCH_ADD(ep_mul_sim_inter(r, p, l[0], q, l[1]));
} BENCH_END;
#endif
#if EP_SIM == JOINT || !defined(STRIP)
BENCH_RUN("ep_mul_sim_joint") {
- bn_rand_mod(k, n);
- bn_rand_mod(l, n);
+ bn_rand_mod(l[0], n);
+ bn_rand_mod(l[1], n);
ep_rand(p);
ep_rand(q);
- BENCH_ADD(ep_mul_sim_joint(r, p, k, q, l));
+ BENCH_ADD(ep_mul_sim_joint(r, p, l[0], q, l[1]));
} BENCH_END;
#endif
BENCH_RUN("ep_mul_sim_gen") {
- bn_rand_mod(k, n);
- bn_rand_mod(l, n);
+ bn_rand_mod(l[0], n);
+ bn_rand_mod(l[1], n);
ep_rand(q);
- BENCH_ADD(ep_mul_sim_gen(r, k, q, l));
+ BENCH_ADD(ep_mul_sim_gen(r, l[0], q, l[1]));
+ } BENCH_END;
+
+ for (int i = 0; i < 2; i++) {
+ ep_new(t[i]);
+ }
+
+ BENCH_RUN("ep_mul_sim_lot (2)") {
+ bn_rand_mod(l[0], n);
+ bn_rand_mod(l[1], n);
+ ep_rand(t[0]);
+ ep_rand(t[1]);
+ BENCH_ADD(ep_mul_sim_lot(r, t, l, 2));
} BENCH_END;
+ for (int i = 0; i < 2; i++) {
+ ep_free(t[i]);
+ }
+
BENCH_RUN("ep_map") {
uint8_t msg[5];
rand_bytes(msg, 5);
@@ -572,7 +589,8 @@ static void arith(void) {
ep_free(q);
ep_free(r);
bn_free(k);
- bn_free(l);
+ bn_free(l[0]);
+ bn_free(l[1]);
bn_free(n);
}
diff --git a/contrib/relic/bench/bench_epx.c b/contrib/relic/bench/bench_epx.c
index eee40decb..487d3dad6 100644
--- a/contrib/relic/bench/bench_epx.c
+++ b/contrib/relic/bench/bench_epx.c
@@ -34,25 +34,25 @@
#include "relic.h"
#include "relic_bench.h"
-static void memory(void) {
- ep2_t a[BENCH];
+static void memory2(void) {
+ ep4_t a[BENCH];
- BENCH_FEW("ep2_null", ep2_null(a[i]), 1);
+ BENCH_FEW("ep4_null", ep4_null(a[i]), 1);
- BENCH_FEW("ep2_new", ep2_new(a[i]), 1);
+ BENCH_FEW("ep4_new", ep4_new(a[i]), 1);
for (int i = 0; i < BENCH; i++) {
- ep2_free(a[i]);
+ ep4_free(a[i]);
}
for (int i = 0; i < BENCH; i++) {
- ep2_new(a[i]);
+ ep4_new(a[i]);
}
- BENCH_FEW("ep2_free", ep2_free(a[i]), 1);
+ BENCH_FEW("ep4_free", ep4_free(a[i]), 1);
(void)a;
}
-static void util(void) {
+static void util2(void) {
ep2_t p, q, t[2];
uint8_t bin[4 * RLC_FP_BYTES + 1];
int l;
@@ -178,9 +178,9 @@ static void util(void) {
ep2_free(t[1]);
}
-static void arith(void) {
+static void arith2(void) {
ep2_t p, q, r, t[RLC_EPX_TABLE_MAX];
- bn_t k, n, l;
+ bn_t k, n, l[2];
fp2_t s;
ep2_null(p);
@@ -198,7 +198,8 @@ static void arith(void) {
ep2_new(r);
bn_new(k);
bn_new(n);
- bn_new(l);
+ bn_new(l[0]);
+ bn_new(l[1]);
fp2_new(s);
ep2_curve_get_ord(n);
@@ -467,60 +468,76 @@ static void arith(void) {
#endif
BENCH_RUN("ep2_mul_sim") {
- bn_rand_mod(k, n);
- bn_rand_mod(l, n);
+ bn_rand_mod(l[0], n);
+ bn_rand_mod(l[1], n);
ep2_rand(p);
ep2_rand(q);
- BENCH_ADD(ep2_mul_sim(r, p, k, q, l));
+ BENCH_ADD(ep2_mul_sim(r, p, l[0], q, l[1]));
} BENCH_END;
#if EP_SIM == BASIC || !defined(STRIP)
BENCH_RUN("ep2_mul_sim_basic") {
- bn_rand_mod(k, n);
- bn_rand_mod(l, n);
+ bn_rand_mod(l[0], n);
+ bn_rand_mod(l[1], n);
ep2_rand(p);
ep2_rand(q);
- BENCH_ADD(ep2_mul_sim_basic(r, p, k, q, l));
+ BENCH_ADD(ep2_mul_sim_basic(r, p, l[0], q, l[1]));
} BENCH_END;
#endif
#if EP_SIM == TRICK || !defined(STRIP)
BENCH_RUN("ep2_mul_sim_trick") {
- bn_rand_mod(k, n);
- bn_rand_mod(l, n);
+ bn_rand_mod(l[0], n);
+ bn_rand_mod(l[1], n);
ep2_rand(p);
ep2_rand(q);
- BENCH_ADD(ep2_mul_sim_trick(r, p, k, q, l));
+ BENCH_ADD(ep2_mul_sim_trick(r, p, l[0], q, l[1]));
} BENCH_END;
#endif
#if EP_SIM == INTER || !defined(STRIP)
BENCH_RUN("ep2_mul_sim_inter") {
- bn_rand_mod(k, n);
- bn_rand_mod(l, n);
+ bn_rand_mod(l[0], n);
+ bn_rand_mod(l[1], n);
ep2_rand(p);
ep2_rand(q);
- BENCH_ADD(ep2_mul_sim_inter(r, p, k, q, l));
+ BENCH_ADD(ep2_mul_sim_inter(r, p, l[0], q, l[1]));
} BENCH_END;
#endif
#if EP_SIM == JOINT || !defined(STRIP)
BENCH_RUN("ep2_mul_sim_joint") {
- bn_rand_mod(k, n);
- bn_rand_mod(l, n);
+ bn_rand_mod(l[0], n);
+ bn_rand_mod(l[1], n);
ep2_rand(p);
ep2_rand(q);
- BENCH_ADD(ep2_mul_sim_joint(r, p, k, q, l));
+ BENCH_ADD(ep2_mul_sim_joint(r, p, l[0], q, l[1]));
} BENCH_END;
#endif
BENCH_RUN("ep2_mul_sim_gen") {
- bn_rand_mod(k, n);
- bn_rand_mod(l, n);
+ bn_rand_mod(l[0], n);
+ bn_rand_mod(l[1], n);
ep2_rand(q);
- BENCH_ADD(ep2_mul_sim_gen(r, k, q, l));
+ BENCH_ADD(ep2_mul_sim_gen(r, l[0], q, l[1]));
+ } BENCH_END;
+
+ for (int i = 0; i < 2; i++) {
+ ep2_new(t[i]);
+ }
+
+ BENCH_RUN("ep2_mul_sim_lot (2)") {
+ bn_rand_mod(l[0], n);
+ bn_rand_mod(l[1], n);
+ ep2_rand(t[0]);
+ ep2_rand(t[1]);
+ BENCH_ADD(ep2_mul_sim_lot(r, t, l, 2));
} BENCH_END;
+ for (int i = 0; i < 2; i++) {
+ ep2_free(t[i]);
+ }
+
BENCH_RUN("ep2_frb") {
ep2_rand(q);
BENCH_ADD(ep2_frb(r, q, 1));
@@ -547,11 +564,502 @@ static void arith(void) {
ep2_free(r);
bn_free(k);
bn_free(n);
- bn_free(l);
+ bn_free(l[0]);
+ bn_free(l[1]);
fp2_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_dig") {
+ bn_rand(k, RLC_POS, RLC_DIG);
+ bn_rand_mod(k, n);
+ BENCH_ADD(ep4_mul_dig(p, q, 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
+
+ BENCH_RUN("ep4_mul_sim_gen") {
+ bn_rand_mod(k, n);
+ bn_rand_mod(l, n);
+ ep4_rand(q);
+ BENCH_ADD(ep4_mul_sim_gen(r, k, q, l));
+ } BENCH_END;
+
+ BENCH_RUN("ep4_frb") {
+ ep4_rand(q);
+ BENCH_ADD(ep4_frb(r, q, 1));
+ } BENCH_END;
+
+ BENCH_RUN("ep4_map") {
+ uint8_t msg[5];
+ rand_bytes(msg, 5);
+ BENCH_ADD(ep4_map(p, msg, 5));
+ } BENCH_END;
+
+ ep4_free(p);
+ ep4_free(q);
+ ep4_free(r);
+ bn_free(k);
+ bn_free(n);
+ bn_free(l);
+ fp4_free(s);
+}
+
int main(void) {
+ int r0, r1;
if (core_init() != RLC_OK) {
core_clean();
return 1;
@@ -567,20 +1075,33 @@ int main(void) {
return 0;
}
- if (ep2_curve_is_twist() == 0) {
- RLC_THROW(ERR_NO_CURVE);
- core_clean();
- return 0;
+ if ((r0 = ep2_curve_is_twist())) {
+ ep_param_print();
+
+ util_banner("Utilities:", 1);
+ memory2();
+ util2();
+
+ util_banner("Arithmetic:", 1);
+ arith2();
}
- ep_param_print();
+ if ((r1 = ep4_curve_is_twist())) {
+ ep_param_print();
- util_banner("Utilities:", 1);
- memory();
- util();
+ util_banner("Utilities:", 1);
+ memory4();
+ util4();
+
+ util_banner("Arithmetic:", 1);
+ arith4();
+ }
- util_banner("Arithmetic:", 1);
- arith();
+ if (!r0 && !r1) {
+ RLC_THROW(ERR_NO_CURVE);
+ core_clean();
+ return 0;
+ }
core_clean();
return 0;
diff --git a/contrib/relic/bench/bench_fb.c b/contrib/relic/bench/bench_fb.c
index 477850293..41fbb026e 100644
--- a/contrib/relic/bench/bench_fb.c
+++ b/contrib/relic/bench/bench_fb.c
@@ -161,7 +161,8 @@ static void util(void) {
}
static void arith(void) {
- fb_t a, b, c, d[2], t[RLC_FB_TABLE_MAX];
+ fb_t a, b, c, d[2];
+ fb_st t[RLC_FB_TABLE_MAX];
dv_t e;
bn_t f;
int bits;
@@ -171,9 +172,6 @@ static void arith(void) {
fb_null(c);
fb_null(d[0]);
fb_null(d[1]);
- for (int i = 0; i < RLC_FB_TABLE_MAX; i++) {
- fb_null(t[i]);
- }
dv_null(e);
bn_null(f);
@@ -513,22 +511,14 @@ static void arith(void) {
BENCH_END;
#endif
- for (int i = 0; i < RLC_FB_TABLE; i++) {
- fb_new(t[i]);
- }
-
BENCH_RUN("fb_itr") {
fb_rand(a);
bn_rand(f, RLC_POS, 8);
fb_itr_pre(t, f->dp[0]);
- BENCH_ADD(fb_itr(c, a, f->dp[0], (const fb_t *)t));
+ BENCH_ADD(fb_itr(c, a, f->dp[0], t));
}
BENCH_END;
- for (int i = 0; i < RLC_FB_TABLE; i++) {
- fb_free(t[i]);
- }
-
#if FB_ITR == BASIC || !defined(STRIP)
BENCH_RUN("fb_itr_basic") {
fb_rand(a);
@@ -539,19 +529,13 @@ static void arith(void) {
#endif
#if FB_ITR == QUICK || !defined(STRIP)
- for (int i = 0; i < RLC_FB_TABLE_QUICK; i++) {
- fb_new(t[i]);
- }
BENCH_RUN("fb_itr_quick") {
fb_rand(a);
bn_rand(f, RLC_POS, 8);
fb_itr_pre_quick(t, f->dp[0]);
- BENCH_ADD(fb_itr_quick(c, a, (const fb_t *)t));
+ BENCH_ADD(fb_itr_quick(c, a, t));
}
BENCH_END;
- for (int i = 0; i < RLC_FB_TABLE_QUICK; i++) {
- fb_new(t[i]);
- }
#endif
fb_free(a);
diff --git a/contrib/relic/bench/bench_fp.c b/contrib/relic/bench/bench_fp.c
index c2887f650..39204de2f 100644
--- a/contrib/relic/bench/bench_fp.c
+++ b/contrib/relic/bench/bench_fp.c
@@ -526,6 +526,14 @@ static void arith(void) {
BENCH_END;
#endif
+#if FP_INV == JMPDS || !defined(STRIP)
+ BENCH_RUN("fp_inv_jmpds") {
+ fp_rand(a);
+ BENCH_ADD(fp_inv_jmpds(c, a));
+ }
+ BENCH_END;
+#endif
+
#if FP_INV == LOWER || !defined(STRIP)
BENCH_RUN("fp_inv_lower") {
fp_rand(a);
@@ -541,6 +549,49 @@ static void arith(void) {
}
BENCH_END;
+ BENCH_RUN("fp_smb") {
+ fp_rand(a);
+ fp_sqr(a, a);
+ BENCH_ADD(fp_smb(a));
+ }
+ BENCH_END;
+
+#if FP_SMB == BASIC || !defined(STRIP)
+ BENCH_RUN("fp_smb_basic") {
+ fp_rand(a);
+ fp_sqr(a, a);
+ BENCH_ADD(fp_smb_basic(a));
+ }
+ BENCH_END;
+#endif
+
+#if FP_SMB == DIVST || !defined(STRIP)
+ BENCH_RUN("fp_smb_divst") {
+ fp_rand(a);
+ fp_sqr(a, a);
+ BENCH_ADD(fp_smb_divst(a));
+ }
+ BENCH_END;
+#endif
+
+#if FP_SMB == JMPDS || !defined(STRIP)
+ BENCH_RUN("fp_smb_jmpds") {
+ fp_rand(a);
+ fp_sqr(a, a);
+ BENCH_ADD(fp_smb_jmpds(a));
+ }
+ BENCH_END;
+#endif
+
+#if FP_SMB == LOWER || !defined(STRIP)
+ BENCH_RUN("fp_smb_lower") {
+ fp_rand(a);
+ fp_sqr(a, a);
+ BENCH_ADD(fp_smb_lower(a));
+ }
+ BENCH_END;
+#endif
+
BENCH_RUN("fp_exp") {
fp_rand(a);
bn_rand(e, RLC_POS, RLC_FP_BITS);
diff --git a/contrib/relic/bench/bench_fpx.c b/contrib/relic/bench/bench_fpx.c
index 0546808a0..62ee13cc3 100644
--- a/contrib/relic/bench/bench_fpx.c
+++ b/contrib/relic/bench/bench_fpx.c
@@ -909,9 +909,17 @@ static void arith4(void) {
}
BENCH_END;
+ BENCH_RUN("fp4_srt") {
+ fp4_rand(a);
+ fp4_sqr(a, a);
+ BENCH_ADD(fp4_srt(c, a));
+ }
+ BENCH_END;
+
fp4_free(a);
fp4_free(b);
fp4_free(c);
+ bn_free(d);
}
static void memory6(void) {
@@ -2256,25 +2264,47 @@ static void util24(void) {
}
BENCH_END;
- BENCH_RUN("fp24_size_bin") {
+ BENCH_RUN("fp24_size_bin (0)") {
+ fp24_rand(a);
+ BENCH_ADD(fp24_size_bin(a, 0));
+ }
+ BENCH_END;
+
+ BENCH_RUN("fp24_size_bin (1)") {
+ fp24_rand(a);
+ fp24_conv_cyc(a, a);
+ BENCH_ADD(fp24_size_bin(a, 1));
+ }
+ BENCH_END;
+
+ BENCH_RUN("fp24_write_bin (0)") {
fp24_rand(a);
- BENCH_ADD(fp24_size_bin(a));
+ BENCH_ADD(fp24_write_bin(bin, sizeof(bin), a, 0));
}
BENCH_END;
- BENCH_RUN("fp24_write_bin") {
+ BENCH_RUN("fp24_write_bin (1)") {
fp24_rand(a);
- BENCH_ADD(fp24_write_bin(bin, sizeof(bin), a));
+ fp24_conv_cyc(a, a);
+ BENCH_ADD(fp24_write_bin(bin, 32 * RLC_FP_BYTES, a, 1));
}
BENCH_END;
- BENCH_RUN("fp24_read_bin") {
+ BENCH_RUN("fp24_read_bin (0)") {
fp24_rand(a);
- fp24_write_bin(bin, sizeof(bin), a);
+ fp24_write_bin(bin, sizeof(bin), a, 0);
BENCH_ADD(fp24_read_bin(a, bin, sizeof(bin)));
}
BENCH_END;
+ BENCH_RUN("fp24_read_bin (1)") {
+ fp24_rand(a);
+ fp24_conv_cyc(a, a);
+ fp24_write_bin(bin, fp24_size_bin(a, 1), a, 1);
+ BENCH_ADD(fp24_read_bin(a, bin, 32 * RLC_FP_BYTES));
+ }
+ BENCH_END;
+
BENCH_RUN("fp24_cmp") {
fp24_rand(a);
fp24_rand(b);
@@ -2293,12 +2323,14 @@ static void util24(void) {
}
static void arith24(void) {
- fp24_t a, b, c;
+ fp24_t a, b, c, d[2];
bn_t e;
fp24_new(a);
fp24_new(b);
fp24_new(c);
+ fp24_new(d[0]);
+ fp24_new(d[1]);
bn_new(e);
BENCH_RUN("fp24_add") {
@@ -2362,6 +2394,38 @@ static void arith24(void) {
BENCH_END;
#endif
+ BENCH_RUN("fp24_test_cyc") {
+ fp24_rand(a);
+ fp24_conv_cyc(a, a);
+ BENCH_ADD(fp24_test_cyc(a));
+ }
+ BENCH_END;
+
+ BENCH_RUN("fp24_conv_cyc") {
+ fp24_rand(a);
+ BENCH_ADD(fp24_conv_cyc(c, a));
+ }
+ BENCH_END;
+
+ BENCH_RUN("fp24_back_cyc") {
+ fp24_rand(a);
+ BENCH_ADD(fp24_back_cyc(c, a));
+ }
+ BENCH_END;
+
+ BENCH_RUN("fp24_back_cyc (2)") {
+ fp24_rand(d[0]);
+ fp24_rand(d[1]);
+ BENCH_ADD(fp24_back_cyc_sim(d, d, 2));
+ }
+ BENCH_END;
+
+ BENCH_RUN("fp24_conv_cyc") {
+ fp24_rand(a);
+ BENCH_ADD(fp24_conv_cyc(c, a));
+ }
+ BENCH_END;
+
BENCH_RUN("fp24_inv") {
fp24_rand(a);
BENCH_ADD(fp24_inv(c, a));
@@ -2375,15 +2439,70 @@ static void arith24(void) {
}
BENCH_END;
+ BENCH_RUN("fp24_exp (cyc)") {
+ fp24_rand(a);
+ fp24_conv_cyc(a, a);
+ bn_rand(e, RLC_POS, RLC_FP_BITS);
+ BENCH_ADD(fp24_exp(c, a, e));
+ }
+ BENCH_END;
+
+ BENCH_RUN("fp24_exp_cyc (param or sparse)") {
+ fp24_rand(a);
+ fp24_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(fp24_exp_cyc(c, a, e));
+ }
+ BENCH_END;
+
+ BENCH_RUN("fp24_exp_cyc_sps (param)") {
+ const int *k;
+ int l;
+ k = fp_prime_get_par_sps(&l);
+ fp24_rand(a);
+ BENCH_ADD(fp24_exp_cyc_sps(c, a, k, l, RLC_POS));
+ }
+ BENCH_END;
+
+ BENCH_RUN("fp24_exp_dig") {
+ fp24_rand(a);
+ bn_rand(e, RLC_POS, RLC_DIG);
+ BENCH_ADD(fp24_exp_dig(c, a, e->dp[0]));
+ }
+ BENCH_END;
+
BENCH_RUN("fp24_frb") {
fp24_rand(a);
BENCH_ADD(fp24_frb(c, a, 1));
}
BENCH_END;
+ BENCH_RUN("fp24_pck") {
+ fp24_rand(a);
+ fp24_conv_cyc(a, a);
+ BENCH_ADD(fp24_pck(c, a));
+ }
+ BENCH_END;
+
+ BENCH_RUN("fp24_upk") {
+ fp24_rand(a);
+ fp24_conv_cyc(a, a);
+ fp24_pck(a, a);
+ BENCH_ADD(fp24_upk(c, a));
+ }
+ BENCH_END;
+
fp24_free(a);
fp24_free(b);
fp24_free(c);
+ fp24_free(d[0]);
+ fp24_free(d[1]);
bn_free(e);
}
diff --git a/contrib/relic/bench/bench_pc.c b/contrib/relic/bench/bench_pc.c
index 8c4a476f3..ed805a953 100755
--- a/contrib/relic/bench/bench_pc.c
+++ b/contrib/relic/bench/bench_pc.c
@@ -303,7 +303,7 @@ static void memory2(void) {
static void util2(void) {
g2_t p, q;
- uint8_t bin[4 * RLC_PC_BYTES + 1];
+ uint8_t bin[8 * RLC_PC_BYTES + 1];
int l;
g2_null(p);
@@ -519,11 +519,13 @@ 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);
diff --git a/contrib/relic/cmake/arch.cmake b/contrib/relic/cmake/arch.cmake
index 5d41eaef1..0b9df7e28 100644
--- a/contrib/relic/cmake/arch.cmake
+++ b/contrib/relic/cmake/arch.cmake
@@ -24,31 +24,26 @@ message(" ALIGN=16 Align digit vectors into 128-bit boundaries.\n")
# Architecture and memory layout.
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86")
set(ARCH "X86" CACHE STRING "Architecture")
-endif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86")
-if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
+endif()
+if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64")
set(ARCH "X64" CACHE STRING "Architecture")
-endif(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64")
+endif()
if(WORD AND NOT WSIZE)
message(FATAL_ERROR "WORD has been replaced with WSIZE. Please update your configuration")
endif()
-if(ARCH STREQUAL X86)
- set(AFLAGS "-m32")
- set(WSIZE 32)
-endif(ARCH STREQUAL X86)
-if(ARCH STREQUAL X64)
- set(AFLAGS "-m64")
- set(WSIZE 64)
-endif(ARCH STREQUAL X64)
-
if(NOT WSIZE)
- if(MSVC)
- set(WSIZE 32)
- else(MSVC)
- set(WSIZE 64)
- endif(MSVC)
-endif(NOT WSIZE)
+ if(ARCH STREQUAL X86)
+ set(AFLAGS "-m32")
+ set(WSIZE 32)
+ endif()
+ if(ARCH STREQUAL X64)
+ set(AFLAGS "-m64")
+ set(WSIZE 64)
+ endif()
+endif()
+
set(WSIZE ${WSIZE} CACHE STRING "Processor word size")
if(NOT ALIGN)
diff --git a/contrib/relic/cmake/ep.cmake b/contrib/relic/cmake/ep.cmake
index ec7670804..889887bc4 100644
--- a/contrib/relic/cmake/ep.cmake
+++ b/contrib/relic/cmake/ep.cmake
@@ -20,15 +20,16 @@ message(" EP_METHD=PROJC Homogeneous projective coordinates (complete fo
message(" EP_METHD=JACOB Jacobian projective coordinates.\n")
message(" Variable-base scalar multiplication:")
-message(" EP_METHD=BASIC Binary method.")
-message(" EP_METHD=LWNAF Left-to-right window NAF method (GLV for Koblitz curves).\n")
+message(" EP_METHD=SLIDE Sliding window method.")
+message(" EP_METHD=MONTY Montgomery ladder method.")
+message(" EP_METHD=LWNAF Left-to-right window NAF method.")
+message(" EP_METHD=LWREG Left-to-right regular recoding method (GLV for curves with endomorphisms).\n")
message(" Fixed-base scalar multiplication:")
message(" EP_METHD=BASIC Binary method for fixed point multiplication.")
message(" EP_METHD=COMBS Single-table Comb method for fixed point multiplication.")
message(" EP_METHD=COMBD Double-table Comb method for fixed point multiplication.")
-message(" EP_METHD=LWNAF Left-to-right window NAF method (GLV for curves with endomorphisms).")
-message(" EP_METHD=LWREG Left-to-right regular recoding method (GLV for curves with endomorphisms).\n")
+message(" EP_METHD=LWNAF Left-to-right window NAF method (GLV for curves with endomorphisms).\n")
message(" Variable-base simultaneous scalar multiplication:")
message(" EP_METHD=BASIC Multiplication-and-addition simultaneous multiplication.")
diff --git a/contrib/relic/cmake/fp.cmake b/contrib/relic/cmake/fp.cmake
index 781e93635..720b94129 100644
--- a/contrib/relic/cmake/fp.cmake
+++ b/contrib/relic/cmake/fp.cmake
@@ -8,29 +8,29 @@ message(" FP_PMERS=[off|on] Prefer Pseudo-Mersenne primes over random prime
message(" FP_QNRES=[off|on] Use -1 as quadratic non-residue (make sure that p = 3 mod 8).")
message(" FP_WIDTH=w Width w in [2,6] of window processing for exponentiation methods.\n")
-message(" ** Available prime field arithmetic methods (default = BASIC;COMBA;COMBA;MONTY;MONTY;SLIDE):")
+message(" ** Available prime field arithmetic methods (default = BASIC;COMBA;COMBA;MONTY;MONTY;JMPDS;SLIDE):")
-message(" Field addition")
+message(" Field addition:")
message(" FP_METHD=BASIC Schoolbook addition.")
message(" FP_METHD=INTEG Integrated modular addition.\n")
-message(" Field multiplication")
+message(" Field multiplication:")
message(" FP_METHD=BASIC Schoolbook multiplication.")
message(" FP_METHD=INTEG Integrated modular multiplication.")
message(" FP_METHD=COMBA Comba multiplication.\n")
-message(" Field squaring")
+message(" Field squaring:")
message(" FP_METHD=BASIC Schoolbook squaring.")
message(" FP_METHD=INTEG Integrated modular squaring.")
message(" FP_METHD=COMBA Comba squaring.")
message(" FP_METHD=MULTP Reuse multiplication for squaring.\n")
-message(" Modular reduction")
+message(" Modular reduction:")
message(" FP_METHD=BASIC Division-based reduction.")
message(" FP_METHD=QUICK Fast reduction modulo special form prime (2^t - c, c > 0).")
message(" FP_METHD=MONTY Montgomery modular reduction.\n")
-message(" Field inversion")
+message(" Field inversion:")
message(" FP_METHD=BASIC Inversion by Fermat's Little Theorem.")
message(" FP_METHD=BINAR Binary Inversion algorithm.")
message(" FP_METHD=MONTY Montgomery inversion.")
@@ -38,7 +38,14 @@ message(" FP_METHD=EXGCD Inversion by the Extended Euclidean algorithm."
message(" FP_METHD=DIVST Constant-time inversion by division steps.")
message(" FP_METHD=LOWER Pass inversion to the lower level.\n")
-message(" Field exponentiation")
+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")
+
+message(" Field exponentiation:")
message(" FP_METHD=BASIC Binary exponentiation.")
message(" FP_METHD=SLIDE Sliding window exponentiation.")
message(" FP_METHD=MONTY Constant-time Montgomery powering ladder.\n")
@@ -65,17 +72,18 @@ option(FP_QNRES "Use -1 as quadratic non-residue." off)
# Choose the arithmetic methods.
if (NOT FP_METHD)
- set(FP_METHD "INTEG;INTEG;INTEG;MONTY;MONTY;SLIDE")
+ set(FP_METHD "INTEG;INTEG;INTEG;MONTY;MONTY;JMPDS;SLIDE")
endif(NOT FP_METHD)
list(LENGTH FP_METHD FP_LEN)
-if (FP_LEN LESS 6)
+if (FP_LEN LESS 7)
message(FATAL_ERROR "Incomplete FP_METHD specification: ${FP_METHD}")
-endif(FP_LEN LESS 6)
+endif(FP_LEN LESS 7)
list(GET FP_METHD 0 FP_ADD)
list(GET FP_METHD 1 FP_MUL)
list(GET FP_METHD 2 FP_SQR)
list(GET FP_METHD 3 FP_RDC)
list(GET FP_METHD 4 FP_INV)
-list(GET FP_METHD 5 FP_EXP)
+list(GET FP_METHD 5 FP_SMB)
+list(GET FP_METHD 6 FP_EXP)
set(FP_METHD ${FP_METHD} CACHE STRING "Method for prime field arithmetic.")
diff --git a/contrib/relic/cmake/gmp.cmake b/contrib/relic/cmake/gmp.cmake
index 01e32e989..abb00c44c 100644
--- a/contrib/relic/cmake/gmp.cmake
+++ b/contrib/relic/cmake/gmp.cmake
@@ -10,7 +10,7 @@
# 2. Redistributions in binary form must reproduce the copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
-# 3. The name of the author may not be used to endorse or promote products
+# 3. The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
@@ -38,17 +38,17 @@ endif (GMP_INCLUDE_DIR AND GMP_LIBRARIES)
find_path(GMP_INCLUDE_DIR NAMES gmp.h)
if(STBIN)
- find_library(GMP_LIBRARIES NAMES libgmp.a gmp)
+ find_library(GMP_LIBRARIES NAMES libgmp.a gmp.lib libgmp-10 libgmp gmp)
else(STBIN)
- find_library(GMP_LIBRARIES NAMES libgmp.so gmp)
+ find_library(GMP_LIBRARIES NAMES libgmp.so gmp.lib libgmp-10 libgmp gmp)
endif(STBIN)
if(GMP_INCLUDE_DIR AND GMP_LIBRARIES)
set(GMP_FOUND TRUE)
-endif(GMP_INCLUDE_DIR AND GMP_LIBRARIES)
+endif()
if(GMP_FOUND)
- message(STATUS "Configured GMP: ${GMP_LIBRARIES}")
+ message(STATUS "Configured GMP: -I${GMP_INCLUDE_DIR} -L${GMP_LIBRARIES}")
else(GMP_FOUND)
message(STATUS "Could NOT find GMP")
endif(GMP_FOUND)
diff --git a/contrib/relic/demo/ers-etrs/Makefile b/contrib/relic/demo/ers-etrs/Makefile
new file mode 100644
index 000000000..5f625d7de
--- /dev/null
+++ b/contrib/relic/demo/ers-etrs/Makefile
@@ -0,0 +1,13 @@
+CFLAGS=-O3 -march=native -mtune=native -ggdb
+RELIC_ROOT = ../..
+
+all: lib
+ gcc ${CFLAGS} -c test-bench.c -o test-bench.o -I ${RELIC_ROOT}/include -I target/include
+ gcc ${CFLAGS} -o test-bench test-bench.o target/lib/librelic_s.a -lgmp
+
+lib:
+ mkdir -p target
+ cd target; ${RELIC_ROOT}/../preset/x64-ecc-128.sh ${RELIC_ROOT}/../; cmake -DEP_METHD='JACOB;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
+
+clean:
+ rm -rf target *.o test-bench
diff --git a/contrib/relic/demo/ers-etrs/test-bench.c b/contrib/relic/demo/ers-etrs/test-bench.c
new file mode 100644
index 000000000..796e62b70
--- /dev/null
+++ b/contrib/relic/demo/ers-etrs/test-bench.c
@@ -0,0 +1,333 @@
+/*
+ * 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
+ *
+ * Benchmarks for cryptographic protocols.
+ *
+ * @version $Id$
+ * @ingroup bench
+ */
+
+#include
+
+#include "relic.h"
+#include "relic_bench.h"
+
+#define MAX_KEYS 2048
+
+#include "assert.h"
+
+static void ers(void) {
+ int size;
+ ec_t pp, pk[MAX_KEYS], *ptr;
+ bn_t sk[MAX_KEYS], td;
+ ers_t ring[MAX_KEYS];
+ uint8_t m[5] = { 0, 1, 2, 3, 4 };
+
+ bn_null(td);
+ ec_null(pp);
+
+ bn_new(td);
+ ec_new(pp);
+ for (int i = 0; i < MAX_KEYS; i++) {
+ bn_null(sk[i]);
+ bn_new(sk[i]);
+ ec_null(pk[i]);
+ ec_new(pk[i]);
+ ers_null(ring[i]);
+ ers_new(ring[i]);
+ cp_ers_gen_key(sk[i], pk[i]);
+ }
+
+ cp_ers_gen(pp);
+
+ bench_reset();
+ for (int j = 0; j < BENCH; j++) {
+ BENCH_ADD(cp_ers_sig(td, ring[0], m, 5, sk[0], pk[0], pp));
+ }
+ bench_compute(BENCH * BENCH);
+ util_print("{\"1\": {\"time\": %lf, \"size\": null}", bench_total()/(double)1000000);
+
+ for (int j = 1; j < MAX_KEYS; j = j << 1) {
+ size = j;
+ bench_before();
+ for (int k = 0; k < j; k++) {
+ cp_ers_ext(td, ring, &size, m, 5, pk[size], pp);
+ }
+ bench_after();
+ bench_compute(1);
+ util_print(", \"%d\": {\"time\": %lf, \"size\": null}", size, bench_total()/(double)1000000);
+ assert(cp_ers_ver(td, ring, size, m, 5, pp));
+ }
+ util_print("}\n\n");
+
+ /* Recompute the signature for verification. */
+ cp_ers_sig(td, ring[0], m, 5, sk[0], pk[0], pp);
+ bench_reset();
+ for (int j = 0; j < BENCH; j++) {
+ BENCH_ADD(assert(cp_ers_ver(td, ring, 1, m, 5, pp)));
+ }
+ bench_compute(BENCH * BENCH);
+ util_print("{\"1\": {\"time\": %lf, \"size\": %d}", bench_total()/(double)1000000, 9 * RLC_FP_BYTES);
+
+ for (int j = 1; j < MAX_KEYS; j = j << 1) {
+ size = j;
+ /* Recompute the signatures for verification. */
+ for (int k = 0; k < j; k++) {
+ assert(cp_ers_ext(td, ring, &size, m, 5, pk[size], pp) == RLC_OK);
+ }
+ assert(cp_ers_ver(td, ring, size, m, 5, pp));
+ bench_reset();
+ for (int i = 0; i < BENCH; i++) {
+ BENCH_ADD(cp_ers_ver(td, ring, size, m, 5, pp));
+ }
+ bench_compute(BENCH * BENCH);
+ util_print(", \"%d\": {\"time\": %lf, \"size\": %d}", size, bench_total()/(double)1000000, size * 9 * RLC_FP_BYTES);
+ }
+ util_print("}");
+
+ bn_free(td);
+ ec_free(pp);
+ for (int i = 0; i < MAX_KEYS; i++) {
+ bn_free(sk[i]);
+ ec_free(pk[i]);
+ ers_free(ring[i])
+ }
+}
+
+static void smlers(void) {
+ int size;
+ ec_t pp, pk[MAX_KEYS], *ptr;
+ bn_t sk[MAX_KEYS], td[MAX_KEYS], y[MAX_KEYS];
+ smlers_t ring[MAX_KEYS];
+ uint8_t m[5] = { 0, 1, 2, 3, 4 };
+
+ ec_null(pp);
+ ec_new(pp);
+ for (int i = 0; i < MAX_KEYS; i++) {
+ bn_null(y[i]);
+ bn_new(y[i]);
+ bn_null(td[i]);
+ bn_new(td[i]);
+ bn_null(sk[i]);
+ bn_new(sk[i]);
+ ec_null(pk[i]);
+ ec_new(pk[i]);
+ smlers_null(ring[i]);
+ smlers_new(ring[i]);
+ cp_ers_gen_key(sk[i], pk[i]);
+ }
+
+ cp_ers_gen(pp);
+
+ for (int l = 1; l <= 8; l = l << 1) {
+ util_print("{");
+ for (int j = l; j <= MAX_KEYS; j = j << 1) {
+ bench_reset();
+ bench_before();
+ size = 1;
+ for (int k = 0; k < l; k++) {
+ cp_smlers_sig(td[0], ring[0], m, 5, sk[0], pk[0], pp);
+ }
+ for (int k = l; k < j; k++) {
+ cp_smlers_ext(td[0], ring, &size, m, 5, pk[size], pp);
+ }
+ bench_after();
+ bench_compute(1);
+ util_print("\"%d\": {\"time\": %lf, \"size\": null}", j, bench_total()/(double)1000000);
+ if (j < MAX_KEYS) {
+ util_print(", ");
+ }
+ for (int k = 0; k < l; k++) {
+ assert(cp_smlers_ver(td[0], ring, size, m, 5, pp));
+ }
+ }
+ util_print("}\n\n");
+ }
+
+ for (int l = 1; l <= 8; l = l << 1) {
+ util_print("{");
+ for (int j = l; j <= MAX_KEYS; j = j << 1) {
+ size = 1;
+ for (int k = 0; k < l; k++) {
+ cp_smlers_sig(td[0], ring[0], m, 5, sk[0], pk[0], pp);
+ }
+ for (int k = l; k < l; k++) {
+ cp_smlers_ext(td[0], ring, &size, m, 5, pk[size], pp);
+ }
+ bench_reset();
+ bench_before();
+ for (int i = 0; i < BENCH; i++) {
+ for (int k = 0; k < j; k++) {
+ cp_smlers_ver(td[0], ring, size, m, 5, pp);
+ }
+ }
+ bench_after();
+ bench_compute(BENCH);
+ util_print("\"%d\": {\"time\": %lf, \"size\": null}", j, bench_total()/(double)1000000);
+ if (j < MAX_KEYS) {
+ util_print(", ");
+ }
+ }
+ util_print("}\n\n");
+ }
+
+ ec_free(pp);
+ for (int i = 0; i < MAX_KEYS; i++) {
+ bn_free(td[i]);
+ bn_free(y[i]);
+ bn_free(sk[i]);
+ ec_free(pk[i]);
+ smlers_free(ring[i]);
+ }
+}
+
+#undef MAX_KEYS
+#define MAX_KEYS 2048
+#define MIN_KEYS 64
+
+static void etrs(void) {
+ int size;
+ ec_t pp, pk[MAX_KEYS], *ptr;
+ bn_t sk[MAX_KEYS], td[MAX_KEYS], y[MAX_KEYS];
+ etrs_t ring[MAX_KEYS];
+ uint8_t m[5] = { 0, 1, 2, 3, 4 };
+
+ ec_null(pp);
+ ec_new(pp);
+ for (int i = 0; i < MAX_KEYS; i++) {
+ bn_null(y[i]);
+ bn_new(y[i]);
+ bn_null(td[i]);
+ bn_new(td[i]);
+ bn_null(sk[i]);
+ bn_new(sk[i]);
+ ec_null(pk[i]);
+ ec_new(pk[i]);
+ ers_null(ring[i]);
+ ers_new(ring[i]);
+ cp_ers_gen_key(sk[i], pk[i]);
+ }
+
+ cp_ers_gen(pp);
+
+ util_print("{");
+ bench_reset();
+ for (int i = 0; i < BENCH; i++) {
+ BENCH_ADD(cp_etrs_sig(td, y, 1, ring[0], m, 5, sk[0], pk[0], pp));
+ }
+ bench_compute(BENCH * BENCH);
+ util_print("\"1\": {\"time\": %lf, \"size\": null}", bench_total()/(double)1000000);
+ assert(cp_etrs_ver(1, td, y, 1, ring, 1, m, 5, pp));
+
+ for (int j = 2; j <= MAX_KEYS; j = j << 1) {
+ bench_reset();
+ bench_before();
+ for (int i = 0; i < BENCH; i++) {
+ cp_etrs_sig(td, y, j, ring[0], m, 5, sk[0], pk[0], pp);
+ }
+ bench_after();
+ bench_compute(BENCH);
+ util_print(", \"%d\": {\"time\": %lf, \"size\": null}", j, bench_total()/(double)1000000);
+ assert(cp_etrs_ver(1, td, y, j, ring, 1, m, 5, pp));
+ }
+ util_print("}\n\n");
+
+ for (int l = 2; l <= 8; l = l << 1) {
+ util_print("{");
+ for (int j = l; j <= MAX_KEYS; j = j << 1) {
+ bench_reset();
+ bench_before();
+ size = 1;
+ cp_etrs_sig(td, y, j, ring[0], m, 5, sk[0], pk[0], pp);
+ for (int k = 1; k < j; k++) {
+ cp_etrs_ext(td, y, j, ring, &size, m, 5, pk[size], pp);
+ }
+ bench_after();
+ bench_compute(1);
+ util_print("\"%d\": {\"time\": %lf, \"size\": null}", j, bench_total()/(double)1000000);
+ if (j < MAX_KEYS) {
+ util_print(", ");
+ }
+ assert(cp_etrs_ver(1, td+size-1, y+size-1, j-size+1, ring, size, m, 5, pp));
+ }
+ util_print("}\n\n");
+ }
+
+ for (int l = 1; l <= 8; l = l << 1) {
+ util_print("{");
+ for (int j = l; j <= MAX_KEYS; j = j << 1) {
+ size = 1;
+ cp_etrs_sig(td, y, j, ring[0], m, 5, sk[0], pk[0], pp);
+ for (int k = 0; k < l; k++) {
+ cp_etrs_ext(td, y, j, ring, &size, m, 5, pk[size], pp);
+ }
+ bench_reset();
+ bench_before();
+ for (int i = 0; i < BENCH; i++) {
+ cp_etrs_ver(1, td+size-1, y+size-1, j-size+1, ring, size, m, 5, pp);
+ }
+ bench_after();
+ bench_compute(BENCH);
+ util_print("\"%d\": {\"time\": %lf, \"size\": null}", j, bench_total()/(double)1000000);
+ if (j < MAX_KEYS) {
+ util_print(", ");
+ }
+ }
+ util_print("}\n\n");
+ }
+
+ ec_free(pp);
+ for (int i = 0; i < MAX_KEYS; i++) {
+ bn_free(td[i]);
+ bn_free(y[i]);
+ bn_free(sk[i]);
+ ec_free(pk[i]);
+ etrs_free(ring[i])
+ }
+}
+
+int main(void) {
+ if (core_init() != RLC_OK) {
+ core_clean();
+ return 1;
+ }
+
+ conf_print();
+
+ if (ec_param_set_any() == RLC_OK) {
+ util_banner("ERS module", 1);
+ ers();
+ util_banner("SMLERS module", 1);
+ smlers();
+ util_banner("ETRS module", 1);
+ etrs();
+ } else {
+ RLC_THROW(ERR_NO_CURVE);
+ }
+
+ core_clean();
+ return 0;
+}
diff --git a/contrib/relic/include/low/relic_bn_low.h b/contrib/relic/include/low/relic_bn_low.h
index d8b4226e7..7c1747c0d 100644
--- a/contrib/relic/include/low/relic_bn_low.h
+++ b/contrib/relic/include/low/relic_bn_low.h
@@ -172,6 +172,18 @@ dig_t bn_rsh1_low(dig_t *c, const dig_t *a, int size);
*/
dig_t bn_rshb_low(dig_t *c, const dig_t *a, int size, int bits);
+/**
+ * Shifts a signed digit vector to the right by an amount smaller than a digit.
+ * Computes c = a >> bits.
+ *
+ * @param[out] c - the result
+ * @param[in] a - the signed digit vector to shift.
+ * @param[in] size - the number of digits to shift.
+ * @param[in] bits - the shift amount.
+ * @return the carry of the last digit shift.
+ */
+dig_t bn_rshs_low(dig_t *c, const dig_t *a, int size, int bits);
+
/**
* Multiplies a digit vector by a digit and adds this result to another digit
* vector. Computes c = c + a * digit.
@@ -196,6 +208,19 @@ dig_t bn_mula_low(dig_t *c, const dig_t *a, dig_t digit, int size);
*/
dig_t bn_mul1_low(dig_t *c, const dig_t *a, dig_t digit, int size);
+/**
+ * Multiplies a signed digit vector by a signed digit and stores this result in
+ * another digit vector. Computes c = (-1)^sa * a * digit.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the first digit vector to multiply.
+ * @param[in] sa - the sign of the first digit vector.
+ * @param[in] digit - the digit to multiply.
+ * @param[in] size - the number of digits to multiply.
+ * @return the most significant digit.
+ */
+dig_t bn_muls_low(dig_t *c, const dig_t *a, dig_t sa, dis_t digit, int size);
+
/**
* Multiplies two digit vectors of the same size. Computes c = a * b.
*
diff --git a/contrib/relic/include/low/relic_fp_low.h b/contrib/relic/include/low/relic_fp_low.h
index cad9bb766..f31f305f0 100644
--- a/contrib/relic/include/low/relic_fp_low.h
+++ b/contrib/relic/include/low/relic_fp_low.h
@@ -321,6 +321,14 @@ void fp_rdcn_low(dig_t *c, dig_t *a);
*/
void fp_invm_low(dig_t *c, const dig_t *a);
+/**
+ * Computes the Legendre symbol of a digit vector and the configured prime.
+ *
+ * @param[in] a - the digit vector to invert.
+ * @return the result.
+ */
+int fp_smbm_low(const dig_t *a);
+
#endif /* ASM */
#endif /* !RLC_FP_LOW_H */
diff --git a/contrib/relic/include/low/relic_fpx_low.h b/contrib/relic/include/low/relic_fpx_low.h
index 41b8351d7..42cbf7b47 100644
--- a/contrib/relic/include/low/relic_fpx_low.h
+++ b/contrib/relic/include/low/relic_fpx_low.h
@@ -367,7 +367,7 @@ void fp3_mulm_low(fp3_t c, fp3_t a, fp3_t b);
* @param[out] c - the result.
* @param[in] a - the field element to square.
*/
-void fp3_sqrn_low(dv2_t c, fp3_t a);
+void fp3_sqrn_low(dv3_t c, fp3_t a);
/**
* Squares a cubic extension field element with integrated modular
diff --git a/contrib/relic/include/relic_bench.h b/contrib/relic/include/relic_bench.h
index ceb841875..5d5167706 100644
--- a/contrib/relic/include/relic_bench.h
+++ b/contrib/relic/include/relic_bench.h
@@ -214,6 +214,6 @@ void bench_print(void);
*
* @return the last benchmark.
*/
-ull_t ben_total(void);
+ull_t bench_total(void);
#endif /* !RLC_BENCH_H */
diff --git a/contrib/relic/include/relic_bn.h b/contrib/relic/include/relic_bn.h
index d99174058..1509700aa 100644
--- a/contrib/relic/include/relic_bn.h
+++ b/contrib/relic/include/relic_bn.h
@@ -148,11 +148,11 @@ typedef bn_st *bn_t;
if ((A) == NULL) { \
RLC_THROW(ERR_NO_MEMORY); \
} \
- bn_init(A, RLC_BN_SIZE); \
+ bn_make(A, RLC_BN_SIZE); \
#elif ALLOC == AUTO
#define bn_new(A) \
- bn_init(A, RLC_BN_SIZE); \
+ bn_make(A, RLC_BN_SIZE); \
#endif
@@ -172,11 +172,11 @@ typedef bn_st *bn_t;
if (A == NULL) { \
RLC_THROW(ERR_NO_MEMORY); \
} \
- bn_init(A, D); \
+ bn_make(A, D); \
#elif ALLOC == AUTO
#define bn_new_size(A, D) \
- bn_init(A, D); \
+ bn_make(A, D); \
#endif
@@ -374,7 +374,7 @@ typedef bn_st *bn_t;
* @throw ERR_PRECISION - if the required precision cannot be represented
* by the library.
*/
-void bn_init(bn_t a, int digits);
+void bn_make(bn_t a, int digits);
/**
* Cleans a multiple precision integer.
@@ -857,6 +857,17 @@ void bn_div_rem_dig(bn_t c, dig_t *d, const bn_t a, const dig_t b);
*/
void bn_mod_inv(bn_t c, const bn_t a, const bn_t b);
+/**
+ * Computes the modular inverse of multiple precision integers simultaneously.
+ * Computes c_i such that a_i * c_i mod b = 1.
+ *
+ * @param[out] c - the results.
+ * @param[in] a - the elements to invert.
+ * param[in] b - the modulus.
+ * @param[in] n - the number of elements.
+ */
+void bn_mod_inv_sim(bn_t *c, const bn_t *a, const bn_t b, int n);
+
/**
* Reduces a multiple precision integer modulo a power of 2. Computes
* c = a mod 2^b.
@@ -1145,20 +1156,22 @@ void bn_lcm(bn_t c, const bn_t a, const bn_t b);
/**
* Computes the Legendre symbol c = (a|b), b prime.
*
- * @param[out] c - the result.
* @param[in] a - the first parameter.
* @param[in] b - the second parameter.
+ * @throw ERR_NO_VALID - if there input is negative.
+ * @return the result.
*/
-void bn_smb_leg(bn_t c, const bn_t a, const bn_t b);
+int bn_smb_leg(const bn_t a, const bn_t b);
/**
* Computes the Jacobi symbol c = (a|b).
*
- * @param[out] c - the result.
* @param[in] a - the first parameter.
* @param[in] b - the second parameter.
+ * @throw ERR_NO_VALID - if there input is even or negative.
+ * @return the result.
*/
-void bn_smb_jac(bn_t c, const bn_t a, const bn_t b);
+int bn_smb_jac(const bn_t a, const bn_t b);
/**
* Returns a small precomputed prime from a given position in the list of prime
@@ -1375,4 +1388,17 @@ void bn_rec_jsf(int8_t *jsf, int *len, const bn_t k, const bn_t l);
void bn_rec_glv(bn_t k0, bn_t k1, const bn_t k, const bn_t n, const bn_t v1[],
const bn_t v2[]);
+/**
+ * Recodes a scalar in subscalars according to Frobenius endomorphism.
+ *
+ * @param[out] ki - the recoded subscalars.
+ * @param[in] sub - the number of subscalars.
+ * @param[in] k - the scalar to recode.
+ * @param[in] x - the elliptic curve parameter.
+ * @param[in] n - the elliptic curve group order.
+ * @param[in] bls - flag to indicate if it is a BLS12 curve.
+ */
+void bn_rec_frb(bn_t *ki, int sub, const bn_t k, const bn_t x, const bn_t n,
+ int bls);
+
#endif /* !RLC_BN_H */
diff --git a/contrib/relic/include/relic_conf.h.in b/contrib/relic/include/relic_conf.h.in
index 7db6f5b50..b13c65223 100644
--- a/contrib/relic/include/relic_conf.h.in
+++ b/contrib/relic/include/relic_conf.h.in
@@ -254,11 +254,26 @@
#define EXGCD 4
/** Constant-time inversion by Bernstein-Yang division steps. */
#define DIVST 5
+/** Constant-time inversion by Bernstein-Yang jump division steps. */
+#define JMPDS 6
/** Use implementation provided by the lower layer. */
#define LOWER 8
/** Chosen prime field inversion method. */
#define FP_INV @FP_INV@
+/** 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. */
+#define JMPDS 6
+/** Use implementation provided by the lower layer. */
+#define LOWER 8
+/** Chosen prime field inversion method. */
+#define FP_SMB @FP_SMB@
+
/** Binary modular exponentiation. */
#define BASIC 1
/** Sliding window modular exponentiation. */
@@ -671,8 +686,8 @@
#define DROID 5
/** Arduino platform. */
#define DUINO 6
-/** OpenBSD operating system. */
-#define OPENBSD 7
+/** NetBSD operating system. */
+#define NETBSD 7
/** Detected operation system. */
#cmakedefine OPSYS @OPSYS@
diff --git a/contrib/relic/include/relic_core.h b/contrib/relic/include/relic_core.h
index eee9bc6a4..fa212d774 100644
--- a/contrib/relic/include/relic_core.h
+++ b/contrib/relic/include/relic_core.h
@@ -170,7 +170,7 @@ typedef struct _ctx_t {
/** Square root of z. */
fb_st fb_srz;
#ifdef FB_PRECO
- /** Multiplication table for the z^(1/2). */
+ /** Multiplication table for the polynomial z^(1/2). */
fb_st fb_tab_srz[256];
#endif /* FB_PRECO */
#endif /* FB_SRT == QUICK */
@@ -181,8 +181,6 @@ typedef struct _ctx_t {
int chain_len;
/** Tables for repeated squarings. */
fb_st fb_tab_sqr[RLC_TERMS][RLC_FB_TABLE];
- /** Pointers to the elements in the tables of repeated squarings. */
- fb_st *fb_tab_ptr[RLC_TERMS][RLC_FB_TABLE];
#endif /* FB_INV == ITOHT */
#endif /* WITH_FB */
@@ -230,6 +228,10 @@ typedef struct _ctx_t {
/** Value of constant one in Montgomery form. */
bn_st one;
#endif /* FP_RDC == MONTY */
+#if FP_INV == JUMPDS || !defined(STRIP)
+ /** Value of constant for divstep-based inversion. */
+ bn_st inv;
+#endif /* FP_INV */
/** Prime modulus modulo 8. */
dig_t mod8;
/** Value derived from the prime used for modular reduction. */
@@ -317,6 +319,8 @@ typedef struct _ctx_t {
fp2_t ep2_map_u;
/** The constants needed for hashing. */
fp2_t ep2_map_c[4];
+ /** The constants needed for Frobenius. */
+ fp2_t ep2_frb[2];
/** Optimization identifier for the a-coefficient. */
int ep2_opt_a;
/** Optimization identifier for the b-coefficient. */
@@ -335,6 +339,28 @@ typedef struct _ctx_t {
/** The isogeny map coefficients for the SSWU mapping. */
iso2_st ep2_iso;
#endif /* EP_CTMAP */
+ /** The generator of the elliptic curve. */
+ ep4_t ep4_g;
+ /** The 'a' coefficient of the curve. */
+ fp4_t ep4_a;
+ /** The 'b' coefficient of the curve. */
+ fp4_t ep4_b;
+ /** The order of the group of points in the elliptic curve. */
+ bn_st ep4_r;
+ /** The cofactor of the group order in the elliptic curve. */
+ bn_st ep4_h;
+ /** Optimization identifier for the a-coefficient. */
+ int ep4_opt_a;
+ /** Optimization identifier for the b-coefficient. */
+ int ep4_opt_b;
+ /** Flag that stores if the prime curve is a twist. */
+ int ep4_is_twist;
+#ifdef EP_PRECO
+ /** Precomputation table for generator multiplication.*/
+ ep4_st ep4_pre[RLC_EP_TABLE];
+ /** Array of pointers to the precomputation table. */
+ ep4_st *ep4_ptr[RLC_EP_TABLE];
+ #endif /* EP_PRECO */
#endif /* WITH_EPX */
#ifdef WITH_ED
@@ -367,6 +393,7 @@ typedef struct _ctx_t {
/** Constants for computing Frobenius maps in higher extensions. @{ */
fp2_st fp2_p1[5];
fp2_st fp2_p2[3];
+ fp2_st fp4_p1;
/** @} */
/** Constants for computing Frobenius maps in higher extensions. @{ */
int frb3[3];
diff --git a/contrib/relic/include/relic_cp.h b/contrib/relic/include/relic_cp.h
index 2054feda3..47da43113 100644
--- a/contrib/relic/include/relic_cp.h
+++ b/contrib/relic/include/relic_cp.h
@@ -30,7 +30,7 @@
*
* Interface of cryptographic protocols.
*
- * @ingroup bn
+ * @ingroup cp
*/
#ifndef RLC_CP_H
@@ -38,6 +38,7 @@
#include "relic_conf.h"
#include "relic_types.h"
+#include "relic_util.h"
#include "relic_bn.h"
#include "relic_ec.h"
#include "relic_pc.h"
@@ -187,6 +188,78 @@ typedef bgn_st bgn_t[1];
typedef bgn_st *bgn_t;
#endif
+/**
+ * Represents an extendable ring signature.
+ */
+typedef struct _ers_st {
+ /** The ephemeral public key in the signature. */
+ ec_t h;
+ /** The public key associated to the signature. */
+ ec_t pk;
+ /** The first component of the signature of knowledge. */
+ bn_t c[2];
+ /** The second component of the signature of knowledge. */
+ bn_t r[2];
+} ers_st;
+
+/**
+ * Pointer to an extendable ring signature.
+ */
+#if ALLOC == AUTO
+typedef ers_st ers_t[1];
+#else
+typedef ers_st *ers_t;
+#endif
+
+/**
+ * Represents an extendable ring signature.
+ */
+typedef struct _smlers_st {
+ /** The extendable ring signature. */
+ ers_t sig;
+ /** The linkability tag. */
+ ec_t tau;
+ /** The first component of the signature of knowledge. */
+ bn_t c[2];
+ /** The second component of the signature of knowledge. */
+ bn_t r[2];
+} smlers_st;
+
+/**
+ * Pointer to an extendable ring signature.
+ */
+#if ALLOC == AUTO
+typedef smlers_st smlers_t[1];
+#else
+typedef smlers_st *smlers_t;
+#endif
+
+/**
+ * Represents an extendable threshold ring signature.
+ */
+typedef struct _etrs_st {
+ /** The secret. */
+ bn_t y;
+ /** The ephemeral public key in the signature. */
+ ec_t h;
+ /** The public key associated to the signature. */
+ ec_t pk;
+ /** The first component of the signature of knowledge. */
+ bn_t c[2];
+ /** The second component of the signature of knowledge. */
+ bn_t r[2];
+} etrs_st;
+
+/**
+ * Pointer to an extendable ring signature.
+ */
+#if ALLOC == AUTO
+typedef etrs_st etrs_t[1];
+#else
+typedef etrs_st *etrs_t;
+#endif
+
+
/*============================================================================*/
/* Macro definitions */
/*============================================================================*/
@@ -196,11 +269,7 @@ typedef bgn_st *bgn_t;
*
* @param[out] A - the moduli to initialize.
*/
-#if ALLOC == AUTO
-#define crt_null(A) /* empty */
-#else
-#define crt_null(A) A = NULL;
-#endif
+#define crt_null(A) RLC_NULL(A)
/**
* Calls a function to allocate and initialize a Rabin key pair.
@@ -250,7 +319,7 @@ typedef bgn_st *bgn_t;
}
#elif ALLOC == AUTO
-#define crt_free(A) /* empty */
+#define crt_free(A) /* empty */
#endif
@@ -259,11 +328,7 @@ typedef bgn_st *bgn_t;
*
* @param[out] A - the key pair to initialize.
*/
-#if ALLOC == AUTO
-#define rsa_null(A) /* empty */
-#else
-#define rsa_null(A) A = NULL;
-#endif
+#define rsa_null(A) RLC_NULL(A)
/**
* Calls a function to allocate and initialize an RSA key pair.
@@ -315,11 +380,7 @@ typedef bgn_st *bgn_t;
*
* @param[out] A - the key pair to initialize.
*/
-#if ALLOC == AUTO
-#define rabin_null(A) /* empty */
-#else
-#define rabin_null(A) A = NULL;
-#endif
+#define rabin_null(A) RLC_NULL(A)
/**
* Calls a function to allocate and initialize a Rabin key pair.
@@ -340,11 +401,7 @@ typedef bgn_st *bgn_t;
*
* @param[out] A - the key pair to initialize.
*/
-#if ALLOC == AUTO
-#define phpe_null(A) /* empty */
-#else
-#define phpe_null(A) A = NULL;
-#endif
+#define phpe_null(A) RLC_NULL(A)
/**
* Calls a function to allocate and initialize a Paillier key pair.
@@ -359,16 +416,13 @@ typedef bgn_st *bgn_t;
* @param[out] A - the key pair to clean and free.
*/
#define phpe_free(A) crt_free(A)
+
/**
* Initializes a Benaloh's key pair with a null value.
*
* @param[out] A - the key pair to initialize.
*/
-#if ALLOC == AUTO
-#define bdpe_null(A) /* empty */
-#else
-#define bdpe_null(A) A = NULL;
-#endif
+#define bdpe_null(A) RLC_NULL(A)
/**
* Calls a function to allocate and initialize a Benaloh's key pair.
@@ -416,7 +470,6 @@ typedef bgn_st *bgn_t;
#elif ALLOC == AUTO
#define bdpe_free(A) /* empty */
-
#endif
/**
@@ -424,11 +477,7 @@ typedef bgn_st *bgn_t;
*
* @param[out] A - the key pair to initialize.
*/
-#if ALLOC == AUTO
-#define sokaka_null(A) /* empty */
-#else
-#define sokaka_null(A) A = NULL;
-#endif
+#define sokaka_null(A) RLC_NULL(A)
/**
* Calls a function to allocate and initialize a SOKAKA key pair.
@@ -446,7 +495,6 @@ typedef bgn_st *bgn_t;
#elif ALLOC == AUTO
#define sokaka_new(A) /* empty */
-
#endif
/**
@@ -465,7 +513,6 @@ typedef bgn_st *bgn_t;
#elif ALLOC == AUTO
#define sokaka_free(A) /* empty */
-
#endif
/**
@@ -473,11 +520,7 @@ typedef bgn_st *bgn_t;
*
* @param[out] A - the key pair to initialize.
*/
-#if ALLOC == AUTO
-#define bgn_null(A) /* empty */
-#else
-#define bgn_null(A) A = NULL;
-#endif
+#define bgn_null(A) RLC_NULL(A)
/**
* Calls a function to allocate and initialize a BGN key pair.
@@ -502,7 +545,6 @@ typedef bgn_st *bgn_t;
#elif ALLOC == AUTO
#define bgn_new(A) /* empty */
-
#endif
/**
@@ -528,7 +570,162 @@ typedef bgn_st *bgn_t;
#elif ALLOC == AUTO
#define bgn_free(A) /* empty */
+#endif
+
+/**
+ * Initializes a BGN key pair with a null value.
+ *
+ * @param[out] A - the key pair to initialize.
+ */
+#define ers_null(A) RLC_NULL(A)
+
+/**
+ * Calls a function to allocate and initialize an extendable signature ring.
+ *
+ * @param[out] A - the new signature ring.
+ */
+#if ALLOC == DYNAMIC
+#define ers_new(A) \
+ A = (ers_t)calloc(1, sizeof(ers_st)); \
+ if (A == NULL) { \
+ RLC_THROW(ERR_NO_MEMORY); \
+ } \
+ ec_new((A)->h); \
+ ec_new((A)->pk); \
+ bn_new((A)->c[0]); \
+ bn_new((A)->c[1]); \
+ bn_new((A)->r[0]); \
+ bn_new((A)->r[1]); \
+#elif ALLOC == AUTO
+#define ers_new(A) /* empty */
+#endif
+
+/**
+ * Calls a function to clean and free an extendable signature ring.
+ *
+ * @param[out] A - the signature ring to clean and free.
+ */
+#if ALLOC == DYNAMIC
+#define ers_free(A) \
+ if (A != NULL) { \
+ ec_free((A)->h); \
+ ec_free((A)->pk); \
+ bn_free((A)->c[0]); \
+ bn_free((A)->c[1]); \
+ bn_free((A)->r[0]); \
+ bn_free((A)->r[1]); \
+ free(A); \
+ A = NULL; \
+ }
+
+#elif ALLOC == AUTO
+#define ers_free(A) /* empty */
+#endif
+
+/**
+ * Initializes a BGN key pair with a null value.
+ *
+ * @param[out] A - the key pair to initialize.
+ */
+#define smlers_null(A) RLC_NULL(A)
+
+/**
+ * Calls a function to allocate and initialize an extendable signature ring.
+ *
+ * @param[out] A - the new signature ring.
+ */
+#if ALLOC == DYNAMIC
+#define smlers_new(A) \
+ A = (smlers_t)calloc(1, sizeof(ers_st)); \
+ if (A == NULL) { \
+ RLC_THROW(ERR_NO_MEMORY); \
+ } \
+ ers_new((A)->sig); \
+ ec_new((A)->tau); \
+ bn_new((A)->c[0]); \
+ bn_new((A)->c[1]); \
+ bn_new((A)->r[0]); \
+ bn_new((A)->r[1]); \
+
+#elif ALLOC == AUTO
+#define smlers_new(A) /* empty */
+#endif
+
+/**
+ * Calls a function to clean and free an extendable signature ring.
+ *
+ * @param[out] A - the signature ring to clean and free.
+ */
+#if ALLOC == DYNAMIC
+#define smlers_free(A) \
+ if (A != NULL) { \
+ ers_free((A)->sig); \
+ ec_free((A)->tau); \
+ bn_free((A)->c[0]); \
+ bn_free((A)->c[1]); \
+ bn_free((A)->r[0]); \
+ bn_free((A)->r[1]); \
+ free(A); \
+ A = NULL; \
+ }
+
+#elif ALLOC == AUTO
+#define smlers_free(A) /* empty */
+#endif
+
+/**
+ * Initializes a BGN key pair with a null value.
+ *
+ * @param[out] A - the key pair to initialize.
+ */
+#define etrs_null(A) RLC_NULL(A)
+
+/**
+ * Calls a function to allocate and initialize an extendable signature ring.
+ *
+ * @param[out] A - the new signature ring.
+ */
+#if ALLOC == DYNAMIC
+#define etrs_new(A) \
+ A = (etrs_t)calloc(1, sizeof(etrs_st)); \
+ if (A == NULL) { \
+ RLC_THROW(ERR_NO_MEMORY); \
+ } \
+ bn_new((A)->y); \
+ ec_new((A)->h); \
+ ec_new((A)->pk); \
+ bn_new((A)->c[0]); \
+ bn_new((A)->c[1]); \
+ bn_new((A)->r[0]); \
+ bn_new((A)->r[1]); \
+
+#elif ALLOC == AUTO
+#define etrs_new(A) /* empty */
+
+#endif
+
+/**
+ * Calls a function to clean and free an extendable signature ring.
+ *
+ * @param[out] A - the signature ring to clean and free.
+ */
+#if ALLOC == DYNAMIC
+#define etrs_free(A) \
+ if (A != NULL) { \
+ bn_free((A)->y); \
+ ec_free((A)->h); \
+ ec_free((A)->pk); \
+ bn_free((A)->c[0]); \
+ bn_free((A)->c[1]); \
+ bn_free((A)->r[0]); \
+ bn_free((A)->r[1]); \
+ free(A); \
+ A = NULL; \
+ }
+
+#elif ALLOC == AUTO
+#define etrs_free(A) /* empty */
#endif
/*============================================================================*/
@@ -569,8 +766,7 @@ int cp_rsa_enc(uint8_t *out, int *out_len, uint8_t *in, int in_len, rsa_t pub);
* @param[in] prv - the private key.
* @return RLC_OK if no errors occurred, RLC_ERR otherwise.
*/
-int cp_rsa_dec(uint8_t *out, int *out_len, uint8_t *in, int in_len,
- rsa_t prv);
+int cp_rsa_dec(uint8_t *out, int *out_len, uint8_t *in, int in_len, rsa_t prv);
/**
* Signs using the basic RSA signature algorithm. The flag must be non-zero if
@@ -586,7 +782,7 @@ int cp_rsa_dec(uint8_t *out, int *out_len, uint8_t *in, int in_len,
* @return RLC_OK if no errors occurred, RLC_ERR otherwise.
*/
int cp_rsa_sig(uint8_t *sig, int *sig_len, uint8_t *msg, int msg_len,
- int hash, rsa_t prv);
+ int hash, rsa_t prv);
/**
* Verifies an RSA signature. The flag must be non-zero if the message being
@@ -601,7 +797,7 @@ int cp_rsa_sig(uint8_t *sig, int *sig_len, uint8_t *msg, int msg_len,
* @return a boolean value indicating if the signature is valid.
*/
int cp_rsa_ver(uint8_t *sig, int sig_len, uint8_t *msg, int msg_len, int hash,
- rsa_t pub);
+ rsa_t pub);
/**
* Generates a key pair for the Rabin cryptosystem.
@@ -624,7 +820,7 @@ int cp_rabin_gen(rabin_t pub, rabin_t prv, int bits);
* @return RLC_OK if no errors occurred, RLC_ERR otherwise.
*/
int cp_rabin_enc(uint8_t *out, int *out_len, uint8_t *in, int in_len,
- rabin_t pub);
+ rabin_t pub);
/**
* Decrypts using the Rabin cryptosystem.
@@ -637,7 +833,7 @@ int cp_rabin_enc(uint8_t *out, int *out_len, uint8_t *in, int in_len,
* @return RLC_OK if no errors occurred, RLC_ERR otherwise.
*/
int cp_rabin_dec(uint8_t *out, int *out_len, uint8_t *in, int in_len,
- rabin_t prv);
+ rabin_t prv);
/**
* Generates a key pair for Benaloh's Dense Probabilistic Encryption.
@@ -778,7 +974,7 @@ int cp_ecmqv_gen(bn_t d, ec_t q);
* @return RLC_OK if no errors occurred, RLC_ERR otherwise.
*/
int cp_ecmqv_key(uint8_t *key, int key_len, bn_t d1, bn_t d2, ec_t q2u,
- ec_t q1v, ec_t q2v);
+ ec_t q1v, ec_t q2v);
/**
* Generates an ECIES key pair.
@@ -802,7 +998,7 @@ int cp_ecies_gen(bn_t d, ec_t q);
* @return RLC_OK if no errors occurred, RLC_ERR otherwise.
*/
int cp_ecies_enc(ec_t r, uint8_t *out, int *out_len, uint8_t *in, int in_len,
- ec_t q);
+ ec_t q);
/**
* Decrypts using the ECIES cryptosystem.
@@ -816,7 +1012,7 @@ int cp_ecies_enc(ec_t r, uint8_t *out, int *out_len, uint8_t *in, int in_len,
* @return RLC_OK if no errors occurred, RLC_ERR otherwise.
*/
int cp_ecies_dec(uint8_t *out, int *out_len, ec_t r, uint8_t *in, int in_len,
- bn_t d);
+ bn_t d);
/**
* Generates an ECDSA key pair.
@@ -887,6 +1083,228 @@ int cp_ecss_sig(bn_t e, bn_t s, uint8_t *msg, int len, bn_t d);
*/
int cp_ecss_ver(bn_t e, bn_t s, uint8_t *msg, int len, ec_t q);
+/**
+ * Generate parameters for the DCKKS pairing delegation protocol described at
+ * "Secure and Efficient Delegationof Pairings with Online Inputs" (CARDIS 2020)
+ *
+ * @param[out] c - the challenge.
+ * @param[out] r - the randomness.
+ * @param[out] u1 - the U1 precomputed value in G_1.
+ * @param[out] u2 - the U2 precomputed value in G_2.
+ * @param[out] v2 - the image of the randomness in G_2.
+ * @param[out] e - the precomputed values e(U1, U2).
+ * @return RLC_OK if no errors occurred, RLC_ERR otherwise.
+ */
+int cp_pdpub_gen(bn_t c, bn_t r, g1_t u1, g2_t u2, g2_t v2, gt_t e);
+
+/**
+ * Execute the client-side request for the DCKKS pairing delegation protocol.
+ *
+ * @param[out] v1 - the blinded element in G_1.
+ * @param[out] w2 - the blinded element in G_2.
+ * @param[in] p - the first argument of the pairing.
+ * @param[in] q - the second argument of the pairing.
+ * @param[in] c - the challenge.
+ * @param[in] r - the randomness.
+ * @param[in] u1 - the U1 precomputed value in G_1.
+ * @param[in] u2 - the U2 precomputed value in G_2.
+ * @param[in] v2 - the image of the randomness in G_2.
+ * @return RLC_OK if no errors occurred, RLC_ERR otherwise.
+ */
+int cp_pdpub_ask(g1_t v1, g2_t w2, g1_t p, g2_t q, bn_t c, bn_t r, g1_t u1,
+ g2_t u2, g2_t v2);
+
+/**
+ * Execute the server-side response for the DCKKS pairing delegation protocol.
+ *
+ * @param[out] g - the group elements computed by the server.
+ * @param[in] p - the first argument of the pairing.
+ * @param[in] q - the second argument of the pairing.
+ * @param[in] v1 - the blinded element in G_1.
+ * @param[in] v2 - the image of the randomness in G_2.
+ * @param[in] w2 - the blinded element in G_2.
+ * @return RLC_OK if no errors occurred, RLC_ERR otherwise.
+ */
+int cp_pdpub_ans(gt_t g[3], g1_t p, g2_t q, g1_t v1, g2_t v2, g2_t w2);
+
+/**
+ * Verifies the result of the DCKKS pairing delegation protocol.
+ *
+ * @param[out] r - the result of the computation.
+ * @param[in] g - the group elements returned by the server.
+ * @param[in] c - the challenge.
+ * @param[out] e - the precomputed values e(U1, U2).
+ * @return a boolean value indicating if the computation is correct.
+ */
+int cp_pdpub_ver(gt_t r, gt_t g[3], bn_t c, gt_t e);
+
+/**
+ * Generate parameters for the DCKKS pairing delegation protocol described at
+ * "Secure and Efficient Delegationof Pairings with Online Inputs" (CARDIS 2020)
+ *
+ * @param[out] c - the challenge.
+ * @param[out] r - the randomness.
+ * @param[out] u1 - the U1 precomputed value in G_1.
+ * @param[out] u2 - the U2 precomputed value in G_2.
+ * @param[out] v2 - the image of the randomness in G_2.
+ * @param[out] e - the precomputed values e(U1, U2).
+ * @return RLC_OK if no errors occurred, RLC_ERR otherwise.
+ */
+int cp_pdprv_gen(bn_t c, bn_t r[3], g1_t u1[2], g2_t u2[2], g2_t v2[4],
+ gt_t e[2]);
+
+/**
+ * Execute the client-side request for the DCKKS pairing delegation protocol.
+ *
+ * @param[out] v1 - the blinded element in G_1.
+ * @param[out] w2 - the blinded element in G_2.
+ * @param[in] p - the first argument of the pairing.
+ * @param[in] q - the second argument of the pairing.
+ * @param[in] c - the challenge.
+ * @param[in] r - the randomness.
+ * @param[in] u1 - the U1 precomputed value in G_1.
+ * @param[in] u2 - the U2 precomputed value in G_2.
+ * @param[in] v2 - the image of the randomness in G_2.
+ * @return RLC_OK if no errors occurred, RLC_ERR otherwise.
+ */
+int cp_pdprv_ask(g1_t v1[3], g2_t w2[4], g1_t p, g2_t q, bn_t c, bn_t r[3],
+ g1_t u1[2], g2_t u2[2], g2_t v2[4]);
+
+/**
+ * Execute the server-side response for the DCKKS pairing delegation protocol.
+ *
+ * @param[out] g - the group elements computed by the server.
+ * @param[in] p - the first argument of the pairing.
+ * @param[in] q - the second argument of the pairing.
+ * @param[in] v1 - the blinded element in G_1.
+ * @param[in] v2 - the image of the randomness in G_2.
+ * @param[in] w2 - the blinded element in G_2.
+ * @return RLC_OK if no errors occurred, RLC_ERR otherwise.
+ */
+int cp_pdprv_ans(gt_t g[4], g1_t v1[3], g2_t w2[4]);
+
+/**
+ * Verifies the result of the DCKKS pairing delegation protocol.
+ *
+ * @param[out] r - the result of the computation.
+ * @param[in] g - the group elements returned by the server.
+ * @param[in] c - the challenge.
+ * @param[out] e - the precomputed values e(U1, U2).
+ * @return a boolean value indicating if the computation is correct.
+ */
+int cp_pdprv_ver(gt_t r, gt_t g[4], bn_t c, gt_t e[2]);
+
+/**
+ * Generate parameters for the AMORE pairing delegation protocol with public
+ * inputs.
+ *
+ * @param[out] r - the randomness.
+ * @param[out] u1 - the U1 precomputed value in G_1.
+ * @param[out] u2 - the U2 precomputed value in G_2.
+ * @param[out] v2 - the image of the randomness in G_2.
+ * @param[out] e - the precomputed values e(U1, U2).
+ * @return RLC_OK if no errors occurred, RLC_ERR otherwise.
+ */
+int cp_lvpub_gen(bn_t r, g1_t u1, g2_t u2, g2_t v2, gt_t e);
+
+/**
+ * Execute the client-side request for the AMORE pairing delegation protocol.
+ *
+ * @param[out] c - the challenge.
+ * @param[out] v1 - the blinded element in G_1.
+ * @param[out] w2 - the blinded element in G_2.
+ * @param[in] p - the first argument of the pairing.
+ * @param[in] q - the second argument of the pairing.
+ * @param[in] c - the challenge.
+ * @param[in] r - the randomness.
+ * @param[in] u1 - the U1 precomputed value in G_1.
+ * @param[in] u2 - the U2 precomputed value in G_2.
+ * @param[in] v2 - the image of the randomness in G_2.
+ * @return RLC_OK if no errors occurred, RLC_ERR otherwise.
+ */
+int cp_lvpub_ask(bn_t c, g1_t v1, g2_t w2, g1_t p, g2_t q, bn_t r, g1_t u1,
+ g2_t u2, g2_t v2);
+
+/**
+ * Execute the server-side response for the AMORE pairing delegation protocol.
+ *
+ * @param[out] g - the group elements computed by the server.
+ * @param[in] p - the first argument of the pairing.
+ * @param[in] q - the second argument of the pairing.
+ * @param[in] v1 - the blinded element in G_1.
+ * @param[in] v2 - the image of the randomness in G_2.
+ * @param[in] w2 - the blinded element in G_2.
+ * @return RLC_OK if no errors occurred, RLC_ERR otherwise.
+ */
+int cp_lvpub_ans(gt_t g[2], g1_t p, g2_t q, g1_t v1, g2_t v2, g2_t w2);
+
+/**
+ * Verifies the result of the AMORE pairing delegation protocol.
+ *
+ * @param[out] r - the result of the computation.
+ * @param[in] g - the group elements returned by the server.
+ * @param[in] c - the challenge.
+ * @param[out] e - the precomputed values e(U1, U2).
+ * @return a boolean value indicating if the computation is correct.
+ */
+int cp_lvpub_ver(gt_t r, gt_t g[2], bn_t c, gt_t e);
+
+/**
+ * Generate parameters for the AMORE pairing delegation protocol with private
+ * inputs.
+ *
+ * @param[out] c - the challenge.
+ * @param[out] r - the randomness.
+ * @param[out] u1 - the U1 precomputed value in G_1.
+ * @param[out] u2 - the U2 precomputed value in G_2.
+ * @param[out] v2 - the image of the randomness in G_2.
+ * @param[out] e - the precomputed values e(U1, U2).
+ * @return RLC_OK if no errors occurred, RLC_ERR otherwise.
+ */
+int cp_lvprv_gen(bn_t c, bn_t r[3], g1_t u1[2], g2_t u2[2], g2_t v2[4],
+ gt_t e[2]);
+
+/**
+ * Execute the client-side request for the AMORE pairing delegation protocol.
+ *
+ * @param[out] v1 - the blinded element in G_1.
+ * @param[out] w2 - the blinded element in G_2.
+ * @param[in] p - the first argument of the pairing.
+ * @param[in] q - the second argument of the pairing.
+ * @param[in] c - the challenge.
+ * @param[in] r - the randomness.
+ * @param[in] u1 - the U1 precomputed value in G_1.
+ * @param[in] u2 - the U2 precomputed value in G_2.
+ * @param[in] v2 - the image of the randomness in G_2.
+ * @return RLC_OK if no errors occurred, RLC_ERR otherwise.
+ */
+int cp_lvprv_ask(g1_t v1[3], g2_t w2[4], g1_t p, g2_t q, bn_t c, bn_t r[3],
+ g1_t u1[2], g2_t u2[2], g2_t v2[4]);
+
+/**
+ * Execute the server-side response for the AMORE pairing delegation protocol.
+ *
+ * @param[out] g - the group elements computed by the server.
+ * @param[in] p - the first argument of the pairing.
+ * @param[in] q - the second argument of the pairing.
+ * @param[in] v1 - the blinded element in G_1.
+ * @param[in] v2 - the image of the randomness in G_2.
+ * @param[in] w2 - the blinded element in G_2.
+ * @return RLC_OK if no errors occurred, RLC_ERR otherwise.
+ */
+int cp_lvprv_ans(gt_t g[4], g1_t v1[3], g2_t w2[4]);
+
+/**
+ * Verifies the result of the AMORE pairing delegation protocol.
+ *
+ * @param[out] r - the result of the computation.
+ * @param[in] g - the group elements returned by the server.
+ * @param[in] c - the challenge.
+ * @param[out] e - the precomputed values e(U1, U2).
+ * @return a boolean value indicating if the computation is correct.
+ */
+int cp_lvprv_ver(gt_t r, gt_t g[4], bn_t c, gt_t e[2]);
+
/**
* Generates a master key for the SOKAKA identity-based non-interactive
* authenticated key agreement protocol.
@@ -917,7 +1335,7 @@ int cp_sokaka_gen_prv(sokaka_t k, char *id, bn_t master);
* @return RLC_OK if no errors occurred, RLC_ERR otherwise.
*/
int cp_sokaka_key(uint8_t *key, unsigned int key_len, char *id1,
- sokaka_t k, char *id2);
+ sokaka_t k, char *id2);
/**
* Generates a key pair for the Boneh-Go-Nissim (BGN) cryptosystem.
@@ -1030,7 +1448,7 @@ int cp_ibe_gen_prv(g2_t prv, char *id, bn_t master);
* @return RLC_OK if no errors occurred, RLC_ERR otherwise.
*/
int cp_ibe_enc(uint8_t *out, int *out_len, uint8_t *in, int in_len, char *id,
- g1_t pub);
+ g1_t pub);
/**
* Decrypts a message using the BF-IBE protocol.
@@ -1372,7 +1790,7 @@ int cp_psb_gen(bn_t r, bn_t s[], g2_t g, g2_t x, g2_t y[], int l);
* @param[in] l - the number of messages to sign.
* @return RLC_OK if no errors occurred, RLC_ERR otherwise.
*/
-int cp_psb_sig(g1_t a, g1_t b, bn_t ms[], bn_t r, bn_t s[], int l);
+int cp_psb_sig(g1_t a, g1_t b, bn_t ms[], bn_t r, bn_t s[], int l);
/**
* Verifies a block of messages signed using the PSB protocol.
@@ -1416,7 +1834,7 @@ int cp_mpsb_gen(bn_t r[2], bn_t s[][2], g2_t h, g2_t x[2], g2_t y[][2], int l);
* @return RLC_OK if no errors occurred, RLC_ERR otherwise.
*/
int cp_mpsb_sig(g1_t a, g1_t b[2], bn_t m[][2], bn_t r[2], bn_t s[][2],
- mt_t mul_tri[2], mt_t sm_tri[2], int l);
+ mt_t mul_tri[2], mt_t sm_tri[2], int l);
/**
* Opens public values in the MPSS protocols, in this case public keys.
@@ -1535,6 +1953,273 @@ int cp_vbnn_sig(ec_t r, bn_t z, bn_t h, uint8_t *id, int id_len, uint8_t *msg,
int cp_vbnn_ver(ec_t r, bn_t z, bn_t h, uint8_t *id, int id_len, uint8_t *msg,
int msg_len, ec_t mpk);
+/**
+ * Computes the proof of knowledge of a discrete logarithm of an elliptic curve
+ * point to a generator. Proves that y = [x]G.
+ *
+ * @param[out] c - the challenge.
+ * @param[out] r - the response.
+ * @param[in] y - the elliptic curve point
+ * @param[in] x - the discrete logarithm to prove.
+ * @return RLC_OK if no errors occurred, RLC_ERR otherwise.
+ */
+int cp_pokdl_prv(bn_t c, bn_t r, ec_t y, bn_t x);
+
+/**
+ * Verifies the proof of knowledge of a discrete logarithm of an elliptic curve
+ * point to a generator. Verifies that y = [x]G.
+ *
+ * @param[in] c - the challenge.
+ * @param[in] r - the response.
+ * @param[in] y - the elliptic curve point.
+ * @return a boolean value indicating the verification result.
+ */
+int cp_pokdl_ver(bn_t c, bn_t r, ec_t y);
+
+/**
+ * Computes the proof of knowledge of a discrete logarithm of an elliptic curve
+ * point to a generator. Proves that y0 = [x]G or y[1] = [x]G.
+ *
+ * @param[out] c - the challenges.
+ * @param[out] r - the responses.
+ * @param[in] y - the elliptic curve points.
+ * @param[in] x - the discrete logarithm to prove.
+ * @return RLC_OK if no errors occurred, RLC_ERR otherwise.
+ */
+int cp_pokor_prv(bn_t c[2], bn_t r[2], ec_t y[2], bn_t x);
+
+/**
+ * Verifies the proof of knowledge of a discrete logarithm of an elliptic curve
+ * point to a generator. Verifies that y = [x]G.
+ *
+ * @param[in] c - the challenges.
+ * @param[in] r - the responses.
+ * @param[in] y - the elliptic curve points.
+ * @return a boolean value indicating the verification result.
+ */
+int cp_pokor_ver(bn_t c[2], bn_t r[2], ec_t y[2]);
+
+/**
+ * Computes the proof of knowledge of a discrete logarithm of an elliptic curve
+ * point to a generator. Proves that y = [x]G.
+ *
+ * @param[out] c - the challenge.
+ * @param[out] r - the response.
+ * @param[in] msg - the message to sign.
+ * @param[in] len - the length of the message.
+ * @param[in] y - the elliptic curve point
+ * @param[in] x - the discrete logarithm to prove.
+ * @return RLC_OK if no errors occurred, RLC_ERR otherwise.
+ */
+int cp_sokdl_sig(bn_t c, bn_t r, uint8_t *msg, int len, ec_t y, bn_t x);
+
+/**
+ * Verifies the proof of knowledge of a discrete logarithm of an elliptic curve
+ * point to a generator. Verifies that y = [x]G.
+ *
+ * @param[in] c - the challenge.
+ * @param[in] r - the response.
+ * @param[in] msg - the message to sign.
+ * @param[in] len - the length of the message.
+ * @param[in] y - the elliptic curve point.
+ * @return a boolean value indicating the verification result.
+ */
+int cp_sokdl_ver(bn_t c, bn_t r, uint8_t *msg, int len, ec_t y);
+
+/**
+ * Computes the proof of knowledge of a discrete logarithm of an elliptic curve
+ * point to a generator. Proves that y0 = [x]G or y1 = [x]G.
+ *
+ * @param[out] c - the challenges.
+ * @param[out] r - the responses.
+ * @param[in] msg - the message to sign.
+ * @param[in] len - the length of the message.
+ * @param[in] y - the elliptic curve points.
+ * @param[in] g - the elliptic curve generators.
+ * @param[in] x - the discrete logarithm to prove.
+ * @param[in] first - the flag to indicate the point for which the
+ * discrete logarithm is known.
+ * @return RLC_OK if no errors occurred, RLC_ERR otherwise.
+ */
+int cp_sokor_sig(bn_t c[2], bn_t r[2], uint8_t *msg, int len, ec_t y[2],
+ ec_t g[2], bn_t x, int first);
+
+/**
+ * Verifies the proof of knowledge of a discrete logarithm of an elliptic curve
+ * point to a generator. Verifies that y = [x]G.
+ *
+ * @param[in] c - the challenges.
+ * @param[in] r - the responses.
+ * @param[in] msg - the message to sign.
+ * @param[in] len - the length of the message.
+ * @param[in] y - the elliptic curve points.
+ * @param[in] g - the elliptic curve generators.
+ * @return a boolean value indicating the verification result.
+ */
+int cp_sokor_ver(bn_t c[2], bn_t r[2], uint8_t *msg, int len, ec_t y[2],
+ ec_t g[2]);
+
+/**
+ * Generates the public parameters of the extendable ring signature.
+ *
+ * @Ã¥aram[out] pp - the public parameters.
+ */
+int cp_ers_gen(ec_t pp);
+
+/**
+ * Generates a key pair for the extendable ring signature.
+ *
+ * @Ã¥aram[out] sk - the private key.
+ * @param[out] pk - the public key.
+ */
+int cp_ers_gen_key(bn_t sk, ec_t pk);
+
+/**
+ * Signs a message using the extendable ring signature scheme.
+ *
+ * @param[out] td - the signature trapdoor.
+ * @param[out] p - the resulting signature.
+ * @param[in] msg - the message to sign.
+ * @param[in] len - the message length.
+ * @param[in] sk - the signer's private key.
+ * @param[in] pk - the singer's public key.
+ * @param[in] pp - the public parameters.
+ */
+int cp_ers_sig(bn_t td, ers_t p, uint8_t *msg, int len, bn_t sk, ec_t pk,
+ ec_t pp);
+
+/**
+ * Verifies an extendable ring signature scheme over some messages.
+ *
+ * @param[in] td - the signature trapdoor.
+ * @param[in] s - the ring of signatures.
+ * @param[in] size - the number of signatures in the ring.
+ * @param[in] msg - the message to sign.
+ * @param[in] len - the message length.
+ * @param[in] pp - the public parameters.
+ */
+int cp_ers_ver(bn_t td, ers_t *s, int size, uint8_t *msg, int len, ec_t pp);
+
+/**
+ * Extends an extendable ring signature with a new signature.
+ *
+ * @param[in] td - the signature trapdoor.
+ * @param[in] p - the ring of signatures.
+ * @param[in] size - the number of signatures in the ring.
+ * @param[in] msg - the message to sign.
+ * @param[in] len - the message length.
+ * @param[in] pk - the singer's public key.
+ * @param[in] pp - the public parameters.
+ */
+int cp_ers_ext(bn_t td, ers_t *p, int *size, uint8_t *msg, int len, ec_t pk,
+ ec_t pp);
+
+/**
+ * Signs a message using the same-message linkable extendable ring signature
+ * scheme.
+ *
+ * @param[out] td - the signature trapdoor.
+ * @param[out] p - the resulting signature.
+ * @param[in] msg - the message to sign.
+ * @param[in] len - the message length.
+ * @param[in] sk - the signer's private key.
+ * @param[in] pk - the singer's public key.
+ * @param[in] pp - the public parameters.
+ */
+int cp_smlers_sig(bn_t td, smlers_t p, uint8_t *msg, int len, bn_t sk, ec_t pk,
+ ec_t pp);
+
+/**
+ * Verifies a same-message linkable extendable ring signature.
+ *
+ * @param[in] td - the signature trapdoor.
+ * @param[in] s - the ring of signatures.
+ * @param[in] size - the number of signatures in the ring.
+ * @param[in] msg - the message to sign.
+ * @param[in] len - the message length.
+ * @param[in] pp - the public parameters.
+ */
+int cp_smlers_ver(bn_t td, smlers_t *s, int size, uint8_t *msg, int len,
+ ec_t pp);
+
+/**
+ * Extends a same-message extendable ring signature with a new signature.
+ *
+ * @param[in] td - the signature trapdoor.
+ * @param[in] p - the ring of signatures.
+ * @param[in] size - the number of signatures in the ring.
+ * @param[in] msg - the message to sign.
+ * @param[in] len - the message length.
+ * @param[in] pk - the singer's public key.
+ * @param[in] pp - the public parameters.
+ */
+int cp_smlers_ext(bn_t td, smlers_t *p, int *size, uint8_t *msg, int len,
+ ec_t pk, ec_t pp);
+
+/**
+ * Signs a message using the extendable threshold ring signature scheme.
+ *
+ * @param[out] td - the signature trapdoors.
+ * @param[out] y - the signature randomness.
+ * @param[out] max - the maximum number of extensions.
+ * @param[out] p - the resulting signature.
+ * @param[in] msg - the message to sign.
+ * @param[in] len - the message length.
+ * @param[in] sk - the signer's private key.
+ * @param[in] pk - the singer's public key.
+ * @param[in] pp - the public parametetrs.
+ */
+int cp_etrs_sig(bn_t *td, bn_t *y, int max, etrs_t p, uint8_t *msg, int len,
+ bn_t sk, ec_t pk, ec_t pp);
+
+/**
+ * Verifies an extendable threshold ring signature scheme over some messages.
+ *
+ * @param[in] thres - the specified threshold.
+ * @param[in] td - the signature trapdoors.
+ * @param[in] y - the signature randomness.
+ * @param[in] max - the maximum number of extensions.
+ * @param[in] s - the ring of signatures.
+ * @param[in] size - the number of signatures in the ring.
+ * @param[in] msg - the message to sign.
+ * @param[in] len - the message length.
+ * @param[in] pp - the public parametetrs.
+ */
+int cp_etrs_ver(int thres, bn_t *td, bn_t *y, int max, etrs_t *s, int size,
+ uint8_t *msg, int len, ec_t pp);
+
+/**
+ * Extends an extendable threshold ring signature with a new signature.
+ *
+ * @param[in] td - the signature trapdoors.
+ * @param[in] y - the signature randomness.
+ * @param[in] max - the maximum number of extensions.
+ * @param[in] p - the ring of signatures.
+ * @param[in] size - the number of signatures in the ring.
+ * @param[in] msg - the message to sign.
+ * @param[in] len - the message length.
+ * @param[in] pk - the singer's public key.
+ * @param[in] pp - the public parametetrs.
+ */
+int cp_etrs_ext(bn_t *td, bn_t *y, int max, etrs_t *p, int *size, uint8_t *msg,
+ int len, ec_t pk, ec_t pp);
+/**
+ * Joins an extendable threshold ring signature with a new signature.
+ *
+ * @param[in] thres - the specified threshold.
+ * @param[in] td - the signature trapdoors.
+ * @param[in] y - the signature randomness.
+ * @param[in] max - the maximum number of extensions.
+ * @param[in] p - the ring of signatures.
+ * @param[in] size - the number of signatures in the ring.
+ * @param[in] msg - the message to sign.
+ * @param[in] len - the message length.
+ * @param[in] sk - the signer's private key.
+ * @param[in] pk - the singer's public key.
+ * @param[in] pp - the public parametetrs.
+ */
+int cp_etrs_uni(int thres, bn_t *td, bn_t *y, int max, etrs_t *p, int *size,
+ uint8_t *msg, int len, bn_t sk, ec_t pk, ec_t pp);
/**
* Initialize the Context-hiding Multi-key Homomorphic Signature scheme (CMLHS).
* The scheme due to Schabhuser et al. signs a vector of messages.
@@ -1633,7 +2318,7 @@ int cp_cmlhs_evl(g1_t r, g2_t s, g1_t rs[], g2_t ss[], dig_t f[], int len);
* @return a boolean value indicating the verification result.
*/
int cp_cmlhs_ver(g1_t r, g2_t s, g1_t sig[], g2_t z[], g1_t a[], g1_t c[],
- bn_t m, char *data, g1_t h, int label[], gt_t *hs[],
+ bn_t m, char *data, g1_t h, int label[], gt_t * hs[],
dig_t *f[], int flen[], g2_t y[], g2_t pk[], int slen);
/**
@@ -1650,8 +2335,8 @@ int cp_cmlhs_ver(g1_t r, g2_t s, g1_t sig[], g2_t z[], g1_t a[], g1_t c[],
* @param[in] slen - the number of signatures.
* @return a boolean value indicating the verification result.
*/
-void cp_cmlhs_off(gt_t vk, g1_t h, int label[], gt_t *hs[], dig_t *f[],
- int flen[], g2_t y[], g2_t pk[], int slen);
+void cp_cmlhs_off(gt_t vk, g1_t h, int label[], gt_t * hs[], dig_t *f[],
+ int flen[], g2_t y[], g2_t pk[], int slen);
/**
* Perform the online verification of a CMLHS signature over a set of messages.
@@ -1730,7 +2415,7 @@ int cp_mklhs_evl(g1_t sig, g1_t s[], dig_t f[], int len);
* @return a boolean value indicating the verification result.
*/
int cp_mklhs_ver(g1_t sig, bn_t m, bn_t mu[], char *data, char *id[],
- char *tag[], dig_t *f[], int flen[], g2_t pk[], int slen);
+ char *tag[], dig_t *f[], int flen[], g2_t pk[], int slen);
/**
* Computes the offline part of veryfying a MKLHS signature over a set of
@@ -1746,7 +2431,7 @@ int cp_mklhs_ver(g1_t sig, bn_t m, bn_t mu[], char *data, char *id[],
* @return RLC_OK if no errors occurred, RLC_ERR otherwise.
*/
int cp_mklhs_off(g1_t h[], dig_t ft[], char *id[], char *tag[], dig_t *f[],
- int flen[], int slen);
+ int flen[], int slen);
/**
* Computes the online part of veryfying a MKLHS signature over a set of
@@ -1764,6 +2449,57 @@ int cp_mklhs_off(g1_t h[], dig_t ft[], char *id[], char *tag[], dig_t *f[],
* @return a boolean value indicating the verification result.
*/
int cp_mklhs_onv(g1_t sig, bn_t m, bn_t mu[], char *data, char *id[], g1_t h[],
- dig_t ft[], g2_t pk[], int slen);
+ dig_t ft[], g2_t pk[], int slen);
+
+/**
+ * Generates the secrets and its consecutive powers for the Laconic Private Set
+ * Intersection (LaPSI) protocol, given the maximum set size.
+ *
+ * @param[out] sk - the sender's secret key.
+ * @param[out] ss - the secret power in G_2.
+ * @param[out] s - the consecutive powers in G_1.
+ * @param[in] m - the maximum set size.
+ */
+int cp_lapsi_gen(bn_t sk, g2_t ss, g1_t s[], int m);
+
+/**
+ * Computes the receiver part of the LaPSI protocol, given its input set.
+ *
+ * @param[out] d - the polynomial interpolation in the exponent.
+ * @param[out] r - the random nonce.
+ * @param[in] x - the receiver's input set.
+ * @param[in] s - the consecutive powers.
+ * @param[in] m - the receiver's input set size.
+ */
+int cp_lapsi_ask(g1_t d, bn_t r, bn_t x[], g1_t s[], int m);
+
+/**
+ * Computes the sender part of the LaPSI protocol, given its input set.
+ *
+ * @param[out] t - the pairing results.
+ * @param[out] u - the missing elements in the exponent.
+ * @param[in] d - the polynomial interpolation in the exponent.
+ * @param[in] ss - the secret power.
+ * @param[in] y - the server's input set.
+ * @param[in] n - the sender's input set size.
+ */
+int cp_lapsi_ans(gt_t t[], g2_t u[], g1_t d, g2_t ss, bn_t y[], int n);
+
+/**
+ * Computes the intersaction as the final part of the LaPSI protocol.
+ *
+ * @param[out] z - the elements in the intersection.
+ * @param[out] len - the cardinality of the resulting intersection.
+ * @param[in] sk - the sender's secret key.
+ * @param[in] d - the polynomial interpolation in the exponent.
+ * @param[in] x - the receiver's input set.
+ * @param[in] s - the consecutive powers.
+ * @param[in] m - the receiver's input set size.
+ * @param[in] t - the pairing results.
+ * @param[in] u - the missing elements in the exponent.
+ * @param[in] n - the sender's input set size.
+ */
+int cp_lapsi_int(bn_t z[], int *len, bn_t sk, g1_t d, bn_t x[], int m,
+ gt_t t[], g2_t u[], int n);
#endif /* !RLC_CP_H */
diff --git a/contrib/relic/include/relic_eb.h b/contrib/relic/include/relic_eb.h
index 20201af6f..b43650f1f 100644
--- a/contrib/relic/include/relic_eb.h
+++ b/contrib/relic/include/relic_eb.h
@@ -144,8 +144,12 @@ typedef struct {
#if ALLOC == AUTO
typedef eb_st eb_t[1];
#else
+#ifdef CHECK
+typedef eb_st *volatile eb_t;
+#else
typedef eb_st *eb_t;
#endif
+#endif
/*============================================================================*/
/* Macro definitions */
diff --git a/contrib/relic/include/relic_ed.h b/contrib/relic/include/relic_ed.h
index 911ea92f2..a458e4a00 100644
--- a/contrib/relic/include/relic_ed.h
+++ b/contrib/relic/include/relic_ed.h
@@ -80,7 +80,7 @@ enum {
* Size of a precomputation table using the chosen algorithm.
*/
#if ED_FIX == BASIC
-#define RLC_ED__TABLE RLC_ED_TABLE_BASIC
+#define RLC_ED_TABLE RLC_ED_TABLE_BASIC
#elif ED_FIX == COMBS
#define RLC_ED_TABLE RLC_ED_TABLE_COMBS
#elif ED_FIX == COMBD
@@ -126,8 +126,12 @@ typedef struct {
#if ALLOC == AUTO
typedef ed_st ed_t[1];
#else
+#ifdef CHECK
+typedef ed_st *volatile ed_t;
+#else
typedef ed_st *ed_t;
#endif
+#endif
/*============================================================================*/
/* Macro definitions */
diff --git a/contrib/relic/include/relic_ep.h b/contrib/relic/include/relic_ep.h
index 71a157d53..bc9418d28 100644
--- a/contrib/relic/include/relic_ep.h
+++ b/contrib/relic/include/relic_ep.h
@@ -32,7 +32,7 @@
*
* The scalar multiplication functions are only guaranteed to work
* in the large prime order subgroup. If you need a generic scalar
- * multiplication function, use ep_mul_basic().
+ * multiplication function, use ep_mul_basic.
*
* @ingroup ep
*/
@@ -97,24 +97,28 @@ enum {
BN_P254,
/** Barreto-Naehrig curve with negative x. */
BN_P256,
+ /** Barreto-Naehrig curve standardized in China. */
+ SM9_P256,
/** Barreto-Lynn-Scott curve with embedding degree 12 (ZCash curve). */
B12_P381,
/** Barreto-Naehrig curve with negative x. */
BN_P382,
+ /** Barreto-Lynn-Scott curve with embedding degree 12 (GT-strong). */
+ B12_P383,
/** Barreto-Naehrig curve with embedding degree 12. */
BN_P446,
/** Barreto-Lynn-Scott curve with embedding degree 12. */
B12_P446,
/** Barreto-Lynn-Scott curve with embedding degree 12. */
B12_P455,
- /** Barreto-Lynn-Scott curve with embedding degree 24. */
- B24_P477,
/** Kachisa-Schafer-Scott with negative x. */
KSS_P508,
+ /** Barreto-Lynn-Scott curve with embedding degree 24. */
+ B24_P509,
/** Optimal TNFS-secure curve with embedding degree 8. */
OT8_P511,
/** Cocks-pinch curve with embedding degree 8. */
- CP8_P544,
+ GMT8_P544,
/** Kachisa-Scott-Schaefer curve with embedding degree 54. */
K54_P569,
/** Barreto-Lynn-Scott curve with embedding degree 48. */
@@ -142,7 +146,7 @@ enum {
/* Optimal TNFS-secure. */
EP_OT8,
/* Cocks-Pinch curve. */
- EP_CP8,
+ EP_GMT8,
/* Barreto-Lynn-Scott with embedding degree 12. */
EP_B12,
/* Kachisa-Schafer-Scott with embedding degree 16. */
@@ -235,15 +239,18 @@ typedef struct {
int coord;
} ep_st;
-
/**
* Pointer to an elliptic curve point.
*/
#if ALLOC == AUTO
typedef ep_st ep_t[1];
#else
+#ifdef CHECK
+typedef ep_st *volatile ep_t;
+#else
typedef ep_st *ep_t;
#endif
+#endif
/**
* Data structure representing an isogeny map.
@@ -286,7 +293,7 @@ typedef iso_st *iso_t;
* @param[out] A - the point to initialize.
*/
#if ALLOC == AUTO
-#define ep_null(A) /* empty */
+#define ep_null(A) /* empty */
#else
#define ep_null(A) A = NULL;
#endif
@@ -305,7 +312,7 @@ typedef iso_st *iso_t;
} \
#elif ALLOC == AUTO
-#define ep_new(A) /* empty */
+#define ep_new(A) /* empty */
#endif
@@ -322,7 +329,7 @@ typedef iso_st *iso_t;
}
#elif ALLOC == AUTO
-#define ep_free(A) /* empty */
+#define ep_free(A) /* empty */
#endif
@@ -1141,14 +1148,15 @@ void ep_mul_sim_joint(ep_t r, const ep_t p, const bn_t k, const ep_t q,
const bn_t m);
/**
- * Multiplies simultaneously elements from G_2. Computes R = \Sum_i=0..n k_iP_i.
+ * Multiplies and adds multiple elliptic curve points simultaneously.
+ * Computes R = \Sum_i=0..n [k_i]P_i.
*
* @param[out] r - the result.
- * @param[out] p - the G_2 elements to multiply.
+ * @param[out] p - the elements to multiply.
* @param[out] k - the integer scalars.
* @param[out] n - the number of elements to multiply.
*/
-void ep_mul_sim_lot(ep_t r, ep_t p[], const bn_t k[], int n);
+void ep_mul_sim_lot(ep_t r, const ep_t p[], const bn_t k[], int n);
/**
* Multiplies and adds the generator and a prime elliptic curve point
@@ -1163,14 +1171,14 @@ void ep_mul_sim_gen(ep_t r, const bn_t k, const ep_t q, const bn_t m);
/**
* Multiplies prime elliptic curve points by small scalars.
- * Computes R = \sum k_iP_i.
+ * Computes R = \Sum_i=0..n [k_i]P_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.
+ * @param[in] n - the number of points to multiply.
*/
-void ep_mul_sim_dig(ep_t r, const ep_t p[], const dig_t k[], int len);
+void ep_mul_sim_dig(ep_t r, const ep_t p[], const dig_t k[], int n);
/**
* Converts a point to affine coordinates.
@@ -1190,25 +1198,25 @@ void ep_norm(ep_t r, const ep_t p);
void ep_norm_sim(ep_t *r, const ep_t *t, int n);
/**
- * Maps a byte array to a point in a prime elliptic curve.
- *
+ * 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] msg - the byte array to map.
+ * @param[in] uniform_bytes - the array of uniform bytes to map.
* @param[in] len - the array length in bytes.
*/
-void ep_map(ep_t p, const uint8_t *msg, int len);
+void ep_map_from_field(ep_t p, const uint8_t *uniform_bytes, int len);
/**
- * Maps a byte array to a point in a prime elliptic curve using
- * an explicit domain separation tag.
+ * Maps a byte array to a point in a prime elliptic curve.
*
* @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, int len, const uint8_t *dst, int dst_len);
+void ep_map(ep_t p, const uint8_t *msg, int len);
/**
* Maps a byte array to a point in a prime elliptic curve with specified
@@ -1220,7 +1228,8 @@ void ep_map_dst(ep_t p, const uint8_t *msg, int len, const uint8_t *dst, int dst
* @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, int len, const uint8_t *dst, int dst_len);
+void ep_map_dst(ep_t p, const uint8_t *msg, int len, const uint8_t *dst,
+ int dst_len);
/**
* Compresses a point.
diff --git a/contrib/relic/include/relic_epx.h b/contrib/relic/include/relic_epx.h
index 5162afeb7..f51f3ec7e 100644
--- a/contrib/relic/include/relic_epx.h
+++ b/contrib/relic/include/relic_epx.h
@@ -136,8 +136,8 @@ typedef struct {
fp3_t y;
/** The third coordinate (projective representation). */
fp3_t z;
- /** Flag to indicate that this point is normalized. */
- int norm;
+ /** Flag to indicate the coordinate system of this point. */
+ int coord;
} ep3_st;
/**
@@ -149,6 +149,30 @@ typedef ep3_st ep3_t[1];
typedef ep3_st *ep3_t;
#endif
+/**
+ * Represents an elliptic curve point over a quartic extension over a prime
+ * field.
+ */
+typedef struct {
+ /** The first coordinate. */
+ fp4_t x;
+ /** The second coordinate. */
+ fp4_t y;
+ /** The third coordinate (projective representation). */
+ fp4_t z;
+ /** Flag to indicate the coordinate system of this point. */
+ int coord;
+} ep4_st;
+
+/**
+ * Pointer to an elliptic curve point.
+ */
+#if ALLOC == AUTO
+typedef ep4_st ep4_t[1];
+#else
+typedef ep4_st *ep4_t;
+#endif
+
/**
* Coefficients of an isogeny map for a curve over a quadratic extension.
*/
@@ -189,11 +213,7 @@ typedef iso2_st *iso2_t;
*
* @param[out] A - the point to initialize.
*/
-#if ALLOC == AUTO
-#define ep2_null(A) /* empty */
-#else
-#define ep2_null(A) A = NULL
-#endif
+#define ep2_null(A) RLC_NULL(A)
/**
* Calls a function to allocate a point on an elliptic curve.
@@ -238,6 +258,56 @@ typedef iso2_st *iso2_t;
#define ep2_free(A) /* empty */
#endif
+/**
+ * Initializes a point on an elliptic curve with a null value.
+ *
+ * @param[out] A - the point to initialize.
+ */
+#define ep4_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 ep4_new(A) \
+ A = (ep4_t)calloc(1, sizeof(ep4_st)); \
+ if (A == NULL) { \
+ RLC_THROW(ERR_NO_MEMORY); \
+ } \
+ fp4_null((A)->x); \
+ fp4_null((A)->y); \
+ fp4_null((A)->z); \
+ fp4_new((A)->x); \
+ fp4_new((A)->y); \
+ fp4_new((A)->z); \
+
+#elif ALLOC == AUTO
+#define ep4_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 ep4_free(A) \
+ if (A != NULL) { \
+ fp4_free((A)->x); \
+ fp4_free((A)->y); \
+ fp4_free((A)->z); \
+ free(A); \
+ A = NULL; \
+ } \
+
+#elif ALLOC == AUTO
+#define ep4_free(A) /* empty */
+#endif
+
/**
* Adds two points in an elliptic curve over a quadratic extension field.
* Computes R = P + Q.
@@ -289,7 +359,7 @@ typedef iso2_st *iso2_t;
#define ep2_mul(R, P, K) ep2_mul_slide(R, P, K)
#elif EP_MUL == MONTY
#define ep2_mul(R, P, K) ep2_mul_monty(R, P, K)
-#elif EP_MUL == LWNAF || EP2_MUL == LWREG
+#elif EP_MUL == LWNAF || EP_MUL == LWREG
#define ep2_mul(R, P, K) ep2_mul_lwnaf(R, P, K)
#endif
@@ -350,6 +420,118 @@ typedef iso2_st *iso2_t;
#define ep2_mul_sim(R, P, K, Q, M) ep2_mul_sim_joint(R, P, K, Q, M)
#endif
+/**
+ * Adds two points in an elliptic curve over a quadratic 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 ep4_add(R, P, Q) ep4_add_basic(R, P, Q);
+#elif EP_ADD == PROJC || EP_ADD == JACOB
+#define ep4_add(R, P, Q) ep4_add_projc(R, P, Q);
+#endif
+
+/**
+ * Doubles a point in an elliptic curve over a quadratic extension field.
+ * Computes R = 2P.
+ *
+ * @param[out] R - the result.
+ * @param[in] P - the point to double.
+ */
+#if EP_ADD == BASIC
+#define ep4_dbl(R, P) ep4_dbl_basic(R, P);
+#elif EP_ADD == PROJC || EP_ADD == JACOB
+#define ep4_dbl(R, P) ep4_dbl_projc(R, P);
+#endif
+
+/**
+ * Multiplies a point in an elliptic curve over a quadratic extension field by
+ * an unrestricted integer scalar. Computes R = [k]P.
+ *
+ * @param[out] R - the result.
+ * @param[in] P - the point to multiply.
+ * @param[in] K - the integer.
+ */
+#define ep4_mul_big(R, P, K) ep4_mul_basic(R, P, K)
+
+/**
+ * Multiplies a point in an elliptic curve over a quadratic 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 ep4_mul(R, P, K) ep4_mul_basic(R, P, K)
+#elif EP_MUL == SLIDE
+#define ep4_mul(R, P, K) ep4_mul_slide(R, P, K)
+#elif EP_MUL == MONTY
+#define ep4_mul(R, P, K) ep4_mul_monty(R, P, K)
+#elif EP_MUL == LWNAF || EP_MUL == LWREG
+#define ep4_mul(R, P, K) ep4_mul_lwnaf(R, P, K)
+#endif
+
+/**
+ * Builds a precomputation table for multiplying a fixed prime elliptic point
+ * over a quadratic extension.
+ *
+ * @param[out] T - the precomputation table.
+ * @param[in] P - the point to multiply.
+ */
+#if EP_FIX == BASIC
+#define ep4_mul_pre(T, P) ep4_mul_pre_basic(T, P)
+#elif EP_FIX == COMBS
+#define ep4_mul_pre(T, P) ep4_mul_pre_combs(T, P)
+#elif EP_FIX == COMBD
+#define ep4_mul_pre(T, P) ep4_mul_pre_combd(T, P)
+#elif EP_FIX == LWNAF
+//TODO: implement ep4_mul_pre_glv
+#define ep4_mul_pre(T, P) ep4_mul_pre_lwnaf(T, P)
+#endif
+
+/**
+ * Multiplies a fixed prime elliptic point over a quadratic 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 ep4_mul_fix(R, T, K) ep4_mul_fix_basic(R, T, K)
+#elif EP_FIX == COMBS
+#define ep4_mul_fix(R, T, K) ep4_mul_fix_combs(R, T, K)
+#elif EP_FIX == COMBD
+#define ep4_mul_fix(R, T, K) ep4_mul_fix_combd(R, T, K)
+#elif EP_FIX == LWNAF
+//TODO: implement ep4_mul_fix_glv
+#define ep4_mul_fix(R, T, K) ep4_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 ep4_mul_sim(R, P, K, Q, M) ep4_mul_sim_basic(R, P, K, Q, M)
+#elif EP_SIM == TRICK
+#define ep4_mul_sim(R, P, K, Q, M) ep4_mul_sim_trick(R, P, K, Q, M)
+#elif EP_SIM == INTER
+#define ep4_mul_sim(R, P, K, Q, M) ep4_mul_sim_inter(R, P, K, Q, M)
+#elif EP_SIM == JOINT
+#define ep4_mul_sim(R, P, K, Q, M) ep4_mul_sim_joint(R, P, K, Q, M)
+#endif
+
/*============================================================================*/
/* Function prototypes */
/*============================================================================*/
@@ -625,7 +807,7 @@ void ep2_add_projc(ep2_t r, ep2_t p, ep2_t q);
* @param[in] p - the first point.
* @param[in] q - the point to subtract.
*/
- void ep2_sub(ep2_t r, ep2_t p, ep2_t q);
+void ep2_sub(ep2_t r, ep2_t p, ep2_t q);
/**
* Doubles a points represented in affine coordinates in an elliptic curve over
@@ -942,6 +1124,18 @@ void ep2_norm(ep2_t r, ep2_t p);
*/
void ep2_norm_sim(ep2_t *r, 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.
+ *
+ * @param[out] p - the result.
+ * @param[in] uniform_bytes - the array of uniform bytes to map.
+ * @param[in] len - the array length in bytes.
+ */
+void ep2_map_from_field(ep2_t p, const uint8_t *uniform_bytes, int len);
+
/**
* Maps a byte array to a point in an elliptic curve over a quadratic extension.
*
@@ -994,4 +1188,632 @@ void ep2_pck(ep2_t r, ep2_t p);
*/
int ep2_upk(ep2_t r, ep2_t p);
+/**
+ * Initializes the elliptic curve over quartic extension.
+ */
+void ep4_curve_init(void);
+
+/**
+ * Finalizes the elliptic curve over quartic extension.
+ */
+void ep4_curve_clean(void);
+
+/**
+ * Returns the 'a' coefficient of the currently configured elliptic curve.
+ *
+ * @return the 'a' coefficient of the elliptic curve.
+ */
+void ep4_curve_get_a(fp4_t a);
+
+/**
+ * Returns the 'b' coefficient of the currently configured elliptic curve.
+ *
+ * @param[out] b - the 'b' coefficient of the elliptic curve.
+ */
+void ep4_curve_get_b(fp4_t b);
+
+/**
+ * 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.
+ *
+ * @return the optimization identifier.
+ */
+int ep4_curve_opt_a(void);
+
+/**
+ * Returns b optimization identifier based on the 'b' coefficient of the curve.
+ *
+ * @return the optimization identifier.
+ */
+int ep4_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 ep4_curve_is_twist(void);
+
+/**
+ * Returns the generator of the group of points in the elliptic curve.
+ *
+ * @param[out] g - the returned generator.
+ */
+void ep4_curve_get_gen(ep4_t g);
+
+/**
+ * Returns the precomputation table for the generator.
+ *
+ * @return the table.
+ */
+ep4_t *ep4_curve_get_tab(void);
+
+/**
+ * Returns the order of the group of points in the elliptic curve.
+ *
+ * @param[out] n - the returned order.
+ */
+void ep4_curve_get_ord(bn_t n);
+
+/**
+ * Returns the cofactor of the group order in the elliptic curve.
+ *
+ * @param[out] h - the returned cofactor.
+ */
+void ep4_curve_get_cof(bn_t h);
+
+/**
+ * Configures an elliptic curve over a quartic extension by its coefficients.
+ *
+ * @param[in] a - the 'a' coefficient of the curve.
+ * @param[in] b - the 'b' coefficient of the curve.
+ * @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 ep4_curve_set(fp4_t a, fp4_t b, ep4_t g, bn_t r, 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 ep4_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 ep4_is_infty(ep4_t p);
+
+/**
+ * Assigns an elliptic curve point to the point at infinity.
+ *
+ * @param[out] p - the point to assign.
+ */
+void ep4_set_infty(ep4_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 ep4_copy(ep4_t r, ep4_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 ep4_cmp(ep4_t p, ep4_t q);
+
+/**
+ * Assigns a random value to an elliptic curve point.
+ *
+ * @param[out] p - the elliptic curve point to assign.
+ */
+void ep4_rand(ep4_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 ep4_blind(ep4_t r, ep4_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 ep4_rhs(fp4_t rhs, ep4_t p);
+
+/**
+ * Tests if a point is in the curve.
+ *
+ * @param[in] p - the point to test.
+ */
+int ep4_on_curve(ep4_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 ep4_tab(ep4_t *t, ep4_t p, int w);
+
+/**
+ * Prints an elliptic curve point.
+ *
+ * @param[in] p - the elliptic curve point to print.
+ */
+void ep4_print(ep4_t p);
+
+/**
+ * Returns the number of bytes necessary to store a prime elliptic curve point
+ * over a quartic 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 ep4_size_bin(ep4_t a, int pack);
+
+/**
+ * Reads a prime elliptic curve point over a quartic 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 ep4_read_bin(ep4_t a, const uint8_t *bin, int len);
+
+/**
+ * Writes a prime elliptic curve pointer over a quartic extension to a byte
+ * vector in big-endian format with optional point compression.
+ *
+ * @param[out] bin - the byte vector.
+ * @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 ep4_write_bin(uint8_t *bin, int len, ep4_t a, int pack);
+
+/**
+ * Negates a point represented in affine coordinates in an elliptic curve over
+ * a quartic extension.
+ *
+ * @param[out] r - the result.
+ * @param[out] p - the point to negate.
+ */
+void ep4_neg(ep4_t r, ep4_t p);
+
+/**
+ * Adds to points represented in affine coordinates in an elliptic curve over a
+ * quartic extension.
+ *
+ * @param[out] r - the result.
+ * @param[in] p - the first point to add.
+ * @param[in] q - the second point to add.
+ */
+void ep4_add_basic(ep4_t r, ep4_t p, ep4_t q);
+
+/**
+ * Adds to points represented in affine coordinates in an elliptic curve over a
+ * quartic extension and returns the computed slope.
+ *
+ * @param[out] r - the result.
+ * @param[out] s - the slope.
+ * @param[in] p - the first point to add.
+ * @param[in] q - the second point to add.
+ */
+void ep4_add_slp_basic(ep4_t r, fp4_t s, ep4_t p, ep4_t q);
+
+/**
+ * Adds two points represented in projective coordinates in an elliptic curve
+ * over a quartic extension.
+ *
+ * @param[out] r - the result.
+ * @param[in] p - the first point to add.
+ * @param[in] q - the second point to add.
+ */
+void ep4_add_projc(ep4_t r, ep4_t p, ep4_t q);
+
+ /**
+ * Subtracts a point i an elliptic curve over a quartic extension from
+ * another.
+ *
+ * @param[out] r - the result.
+ * @param[in] p - the first point.
+ * @param[in] q - the point to subtract.
+ */
+void ep4_sub(ep4_t r, ep4_t p, ep4_t q);
+
+/**
+ * Doubles a points represented in affine coordinates in an elliptic curve over
+ * a quartic extension.
+ *
+ * @param[out] r - the result.
+ * @param[int] p - the point to double.
+ */
+void ep4_dbl_basic(ep4_t r, ep4_t p);
+
+/**
+ * Doubles a points represented in affine coordinates in an elliptic curve over
+ * a quartic extension and returns the computed slope.
+ *
+ * @param[out] r - the result.
+ * @param[out] s - the slope.
+ * @param[in] p - the point to double.
+ */
+void ep4_dbl_slp_basic(ep4_t r, fp4_t s, ep4_t p);
+
+/**
+ * Doubles a points represented in projective coordinates in an elliptic curve
+ * over a quartic extension.
+ *
+ * @param[out] r - the result.
+ * @param[in] p - the point to double.
+ */
+void ep4_dbl_projc(ep4_t r, ep4_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 ep4_mul_basic(ep4_t r, ep4_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 ep4_mul_slide(ep4_t r, ep4_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 ep4_mul_monty(ep4_t r, ep4_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 ep4_mul_lwnaf(ep4_t r, ep4_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 ep4_mul_lwreg(ep4_t r, ep4_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 ep4_mul_gen(ep4_t r, 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 ep4_mul_dig(ep4_t r, ep4_t p, dig_t k);
+
+
+/**
+ * Multiplies a point in an elliptic curve over a quartic extension field by
+ * the curve cofactor or a small multiple for which a short vector exists.
+ * In short, it takes a point in the curve to the large prime-order subgroup.
+ *
+ * @param[out] R - the result.
+ * @param[in] P - the point to multiply.
+ */
+void ep4_mul_cof(ep4_t r, ep4_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 ep4_mul_pre_basic(ep4_t *t, ep4_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 ep4_mul_pre_yaowi(ep4_t *t, ep4_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 ep4_mul_pre_nafwi(ep4_t *t, ep4_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 ep4_mul_pre_combs(ep4_t *t, ep4_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 ep4_mul_pre_combd(ep4_t *t, ep4_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 ep4_mul_pre_lwnaf(ep4_t *t, ep4_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 ep4_mul_fix_basic(ep4_t r, ep4_t *t, 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 ep4_mul_fix_yaowi(ep4_t r, ep4_t *t, 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 ep4_mul_fix_nafwi(ep4_t r, ep4_t *t, 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 ep4_mul_fix_combs(ep4_t r, ep4_t *t, 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 ep4_mul_fix_combd(ep4_t r, ep4_t *t, 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 ep4_mul_fix_lwnaf(ep4_t r, ep4_t *t, 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 ep4_mul_sim_basic(ep4_t r, ep4_t p, bn_t k, ep4_t q, 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 ep4_mul_sim_trick(ep4_t r, ep4_t p, bn_t k, ep4_t q, 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 ep4_mul_sim_inter(ep4_t r, ep4_t p, bn_t k, ep4_t q, 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 ep4_mul_sim_joint(ep4_t r, ep4_t p, bn_t k, ep4_t q, 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[out] p - the points to multiply.
+ * @param[out] k - the integer scalars.
+ * @param[out] n - the number of elements to multiply.
+ */
+void ep4_mul_sim_lot(ep4_t r, ep4_t p[], const bn_t k[], int 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 ep4_mul_sim_gen(ep4_t r, bn_t k, ep4_t q, 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 ep4_mul_sim_dig(ep4_t r, ep4_t p[], dig_t k[], int len);
+
+/**
+ * Converts a point to affine coordinates.
+ *
+ * @param[out] r - the result.
+ * @param[in] p - the point to convert.
+ */
+void ep4_norm(ep4_t r, ep4_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 ep4_norm_sim(ep4_t *r, ep4_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 ep4_map(ep4_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.
+ *
+ * @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, int len, const uint8_t *dst, int 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
+ * Frobenius map of a point represented in affine coordinates in an elliptic
+ * curve over a quartic exension. Computes Frob^i(P) = (p^i)P.
+ *
+ * @param[out] r - the result in affine coordinates.
+ * @param[in] p - a point in affine coordinates.
+ * @param[in] i - the power of the Frobenius map.
+ */
+void ep4_frb(ep4_t r, ep4_t p, int i);
+
+/**
+ * Compresses a point in an elliptic curve over a quartic extension.
+ *
+ * @param[out] r - the result.
+ * @param[in] p - the point to compress.
+ */
+void ep4_pck(ep4_t r, ep4_t p);
+
+/**
+ * Decompresses a point in an elliptic curve over a quartic extension.
+ *
+ * @param[out] r - the result.
+ * @param[in] p - the point to decompress.
+ * @return if the decompression was successful
+ */
+int ep4_upk(ep4_t r, ep4_t p);
+
#endif /* !RLC_EPX_H */
diff --git a/contrib/relic/include/relic_err.h b/contrib/relic/include/relic_err.h
index 55596f617..e16f71fe0 100644
--- a/contrib/relic/include/relic_err.h
+++ b/contrib/relic/include/relic_err.h
@@ -71,6 +71,8 @@ enum errors {
ERR_NO_CURVE,
/** Occurs when the library configuration is incorrect. */
ERR_NO_CONFIG,
+ /** Occurs when the PRNG is stuck at one value. */
+ ERR_NO_RAND,
/** Constant to indicate the number of errors. */
ERR_MAX
};
@@ -160,9 +162,9 @@ typedef struct _sts_t {
/**
* Implements the THROW clause of the error-handling routines.
*
- * If the error pointer is not NULL but there is no surrounding TRY-CATCH
- * block, then the code threw an exception after an exception was thrown.
- * In this case, we finish execution.
+ * First we make sure that the error pointer is NULL (new exception) or
+ * there is a surrounding try-catch block (block = 1). If this is not the case,
+ * then it is the second exception thrown in sequence without handling.
*
* If the error pointer is NULL, the error was thrown outside of a TRY-CATCH
* block. An error message is printed and the function returns.
@@ -178,21 +180,20 @@ typedef struct _sts_t {
{ \
ctx_t *_ctx = core_get(); \
_ctx->code = RLC_ERR; \
- if (_ctx->last != NULL && _ctx->last->block == 0) { \
- exit(E); \
- } \
- if (_ctx->last == NULL) { \
- _ctx->last = &(_ctx->error); \
- _ctx->error.error = &(_ctx->number); \
- _ctx->error.block = 0; \
- _ctx->number = E; \
- RLC_ERR_PRINT(E); \
- } else { \
- for (; ; longjmp(_ctx->last->addr, 1)) { \
+ if (_ctx->last == NULL || _ctx->last->block == 1) { \
+ if (_ctx->last == NULL) { \
+ _ctx->last = &(_ctx->error); \
+ _ctx->error.error = &(_ctx->number); \
+ _ctx->error.block = 0; \
+ _ctx->number = E; \
RLC_ERR_PRINT(E); \
- if (_ctx->last->error) { \
- if (E != ERR_CAUGHT) { \
- *(_ctx->last->error) = E; \
+ } else { \
+ for (; ; longjmp(_ctx->last->addr, 1)) { \
+ RLC_ERR_PRINT(E); \
+ if (_ctx->last->error) { \
+ if (E != ERR_CAUGHT) { \
+ *(_ctx->last->error) = E; \
+ } \
} \
} \
} \
@@ -261,7 +262,7 @@ typedef struct _sts_t {
#else
#define RLC_THROW(E) \
core_get()->code = RLC_ERR; \
- util_print("FATAL ERROR in %s:%d\n", RLC_FILE, __LINE__); \
+ util_print("ERROR THROWN in %s:%d\n", RLC_FILE, __LINE__); \
#endif
#endif
diff --git a/contrib/relic/include/relic_fb.h b/contrib/relic/include/relic_fb.h
index caa0bcb6a..48fe45b80 100644
--- a/contrib/relic/include/relic_fb.h
+++ b/contrib/relic/include/relic_fb.h
@@ -435,7 +435,7 @@ const dig_t *fb_poly_tab_srz(int i);
* @param the number of the table.
* @return the precomputed result.
*/
-const fb_t *fb_poly_tab_sqr(int i);
+const fb_st *fb_poly_tab_sqr(int i);
/**
* Returns an addition chain for (RLC_FB_BITS - 1).
@@ -973,7 +973,7 @@ void fb_itr_basic(fb_t c, const fb_t a, int b);
* @param[out] t - the precomputed table.
* @param[in] b - the exponent.
*/
-void fb_itr_pre_quick(fb_t *t, int b);
+void fb_itr_pre_quick(fb_st *t, int b);
/**
* Computes the iterated squaring/square-root of a binary field element by
@@ -983,6 +983,6 @@ void fb_itr_pre_quick(fb_t *t, int b);
* @param[in] a - the basis.
* @param[in] t - the precomputed table.
*/
-void fb_itr_quick(fb_t c, const fb_t a, const fb_t *t);
+void fb_itr_quick(fb_t c, const fb_t a, const fb_st *t);
#endif /* !RLC_FB_H */
diff --git a/contrib/relic/include/relic_fp.h b/contrib/relic/include/relic_fp.h
index 4fb779c4b..fbbd3fc5f 100644
--- a/contrib/relic/include/relic_fp.h
+++ b/contrib/relic/include/relic_fp.h
@@ -98,6 +98,8 @@ enum {
PRIME_383187,
/** NIST 384-bit fast reduction polynomial. */
NIST_384,
+ /** Curve448 prime. */
+ PRIME_448,
/** Curve511187 511-bit prime modulus. */
PRIME_511187,
/** NIST 521-bit fast reduction polynomial. */
@@ -108,10 +110,14 @@ enum {
BN_254,
/** 256-bit prime provided in Barreto et al. for BN curves. */
BN_256,
+ /** 256-bit prime provided for BN curve standardized in China. */
+ SM9_256,
/** 381-bit prime for BLS curve of embedding degree 12 (Zcash). */
B12_381,
/** 382-bit prime provided by Barreto for BN curve. */
BN_382,
+ /** 383-bit prime for GT-strong BLS curve of embedding degree 12. */
+ B12_383,
/** 446-bit prime provided by Barreto for BN curve. */
BN_446,
/** 446-bit prime for BLS curve of embedding degree 12. */
@@ -119,13 +125,13 @@ enum {
/** 455-bit prime for BLS curve of embedding degree 12. */
B12_455,
/** 477-bit prime for BLS curve of embedding degree 24. */
- B24_477,
+ B24_509,
/** 508-bit prime for KSS16 curve. */
KSS_508,
/** 511-bit prime for Optimal TNFS-secure curve. */
OT_511,
/** Random 544-bit prime for Cocks-Pinch curve with embedding degree 8. */
- CP8_544,
+ GMT8_544,
/** 569-bit prime for KSS curve with embedding degree 54. */
K54_569,
/** 575-bit prime for BLS curve with embedding degree 48. */
@@ -354,10 +360,30 @@ typedef rlc_align dig_t fp_st[RLC_FP_DIGS + RLC_PAD(RLC_FP_BYTES)/(RLC_DIG / 8)]
#define fp_inv(C, A) fp_inv_exgcd(C, A)
#elif FP_INV == DIVST
#define fp_inv(C, A) fp_inv_divst(C, A)
+#elif FP_INV == JMPDS
+#define fp_inv(C, A) fp_inv_jmpds(C, A)
#elif FP_INV == LOWER
#define fp_inv(C, A) fp_inv_lower(C, A)
#endif
+/**
+ * Computes the Legendre symbol of a prime field element. Computes C = (A|P).
+ *
+ * @param[out] C - the result.
+ * @param[in] A - the prime field element to compute.
+ */
+#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
+#define fp_smb(A) fp_smb_jmpds(A)
+#elif FP_SMB == LOWER
+#define fp_smb(A) fp_smb_lower(A)
+#endif
+
/**
* Exponentiates a prime field element. Computes C = A^B (mod p).
*
@@ -1023,6 +1049,16 @@ void fp_inv_exgcd(fp_t c, const fp_t a);
*/
void fp_inv_divst(fp_t c, const fp_t a);
+/**
+ * Inverts a prime field element using the constant-time jump division step
+ * by Bernstein and Bo-Yin Yang.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the prime field element to invert.
+ * @throw ERR_NO_VALID - if the field element is not invertible.
+ */
+void fp_inv_jmpds(fp_t c, const fp_t a);
+
/**
* Inverts a prime field element using a direct call to the lower layer.
*
@@ -1041,6 +1077,49 @@ void fp_inv_lower(fp_t c, const fp_t a);
*/
void fp_inv_sim(fp_t *c, const fp_t *a, int n);
+/**
+ * Computes Legendre symbol of a prime field element using exponentiation.
+ *
+ * @param[in] a - the prime field element to compute.
+ * @return the result.
+ */
+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.
+ *
+ * @param[in] a - the prime field element to compute.
+ * @return the result.
+ */
+int fp_smb_divst(const fp_t a);
+
+/**
+ * Computes Legendre symbol of a prime field element using the constant-time
+ * jump division step approach by Bernstein and Bo-Yin Yang.
+ *
+ * @param[in] a - the prime field element to compute.
+ * @return the result.
+ */
+int fp_smb_jmpds(const fp_t a);
+
+/**
+ * Computes Legendre symbol a prime field element using a direct call to the
+ * lower layer.
+ *
+ * @param[in] a - the prime field element to invert.
+ * @return the result.
+ */
+int fp_smb_lower(const fp_t a);
+
/**
* Exponentiates a prime field element using the binary
* method.
diff --git a/contrib/relic/include/relic_fpx.h b/contrib/relic/include/relic_fpx.h
index c1d623664..f1f139ca1 100644
--- a/contrib/relic/include/relic_fpx.h
+++ b/contrib/relic/include/relic_fpx.h
@@ -1038,6 +1038,32 @@ void fp2_sub_dig(fp2_t c, const fp2_t a, dig_t b);
#define fp24_sqr(C, A) fp24_sqr_lazyr(C, A)
#endif
+/**
+ * Squares a 24-degree extension field element in the cyclotomic subgroup.
+ * Computes C = A * A.
+ *
+ * @param[out] C - the result.
+ * @param[in] A - the 24-degree extension field element to square.
+ */
+#if FPX_RDC == BASIC
+#define fp24_sqr_cyc(C, A) fp24_sqr_cyc_basic(C, A)
+#elif FPX_RDC == LAZYR
+#define fp24_sqr_cyc(C, A) fp24_sqr_cyc_lazyr(C, A)
+#endif
+
+/**
+ * Squares a 24-degree extension field element in the cyclotomic subgroup in
+ * compressed form. Computes C = A * A.
+ *
+ * @param[out] C - the result.
+ * @param[in] A - the 24-degree extension field element to square.
+ */
+#if FPX_RDC == BASIC
+#define fp24_sqr_pck(C, A) fp24_sqr_pck_basic(C, A)
+#elif FPX_RDC == LAZYR
+#define fp24_sqr_pck(C, A) fp24_sqr_pck_lazyr(C, A)
+#endif
+
/**
* Initializes a double-precision 48-degree extension field with null.
*
@@ -1870,6 +1896,11 @@ void fp3_frb(fp3_t c, fp3_t a, int i);
*/
int fp3_srt(fp3_t c, fp3_t a);
+/**
+ * Initializes the quartic extension field arithmetic module.
+ */
+void fp4_field_init(void);
+
/**
* Copies the second argument to the first argument.
*
@@ -2037,6 +2068,17 @@ void fp4_mul_lazyr(fp4_t c, fp4_t a, fp4_t b);
*/
void fp4_mul_art(fp4_t c, fp4_t a);
+/**
+ * Multiplies a quartic 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 fp4_mul_frb(fp4_t c, fp4_t a, int i, int j);
+
/**
* Multiples a dense quartic extension field element by a sparse element.
*
@@ -2053,7 +2095,7 @@ void fp4_mul_dxs(fp4_t c, fp4_t a, fp4_t b);
* @param[out] c - the result.
* @param[in] a - the quartic extension field element to square.
*/
-void fp4_sqr_unr(dv6_t c, fp4_t a);
+void fp4_sqr_unr(dv4_t c, fp4_t a);
/**
* Computes the squares of a quartic extension field element using basic
@@ -2080,6 +2122,15 @@ void fp4_sqr_lazyr(fp4_t c, fp4_t a);
*/
void fp4_inv(fp4_t c, fp4_t a);
+/**
+ * Inverts multiple quartic extension field elements simultaneously.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the quartic extension field elements to invert.
+ * @param[in] n - the number of elements.
+ */
+void fp4_inv_sim(fp4_t *c, fp4_t *a, int n);
+
/**
* Computes the inverse of a cyclotomic quartic extension field element.
*
@@ -2110,6 +2161,16 @@ void fp4_exp(fp4_t c, fp4_t a, bn_t b);
*/
void fp4_frb(fp4_t c, fp4_t a, int i);
+/**
+ * Extracts the square root of a quartic 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 fp4_srt(fp4_t c, fp4_t a);
+
/**
* Copies the second argument to the first argument.
*
@@ -3582,9 +3643,10 @@ void fp24_print(fp24_t a);
* element.
*
* @param[in] a - the extension field element.
+ * @param[in] pack - the flag to indicate compression.
* @return the number of bytes.
*/
-int fp24_size_bin(fp24_t a);
+int fp24_size_bin(fp24_t a, int pack);
/**
* Reads a 24-degree extension field element from a byte vector in big-endian
@@ -3604,9 +3666,10 @@ void fp24_read_bin(fp24_t a, const uint8_t *bin, int len);
* @param[out] bin - the byte vector.
* @param[in] len - the buffer capacity.
* @param[in] a - the extension field element to write.
+ * @param[in] pack - the flag to indicate compression.
* @throw ERR_NO_BUFFER - if the buffer capacity is not correct.
*/
-void fp24_write_bin(uint8_t *bin, int len, fp24_t a);
+void fp24_write_bin(uint8_t *bin, int len, fp24_t a, int pack);
/**
* Returns the result of a comparison between two 24-degree extension field
@@ -3743,6 +3806,84 @@ void fp24_sqr_basic(fp24_t c, fp24_t a);
*/
void fp24_sqr_lazyr(fp24_t c, fp24_t a);
+/**
+ * Computes the square of a cyclotomic 24-extension field element using
+ * basic arithmetic.
+ *
+ * A cyclotomic element is one raised to the (p^6 - 1)(p^2 + 1)-th power.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the cyclotomic extension element to square.
+ */
+void fp24_sqr_cyc_basic(fp24_t c, fp24_t a);
+
+/**
+ * Computes the square of a cyclotomic 24-extension field element using
+ * lazy reduction.
+ *
+ * A cyclotomic element is one raised to the (p^6 - 1)(p^2 + 1)-th power.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the cyclotomic extension element to square.
+ */
+void fp24_sqr_cyc_lazyr(fp24_t c, fp24_t a);
+
+/**
+ * Computes the square of a compressed cyclotomic extension field element.
+ *
+ * A cyclotomic element is one raised to the (p^6 - 1)(p^2 + 1)-th power.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the cyclotomic extension element to square.
+ */
+void fp24_sqr_pck_basic(fp24_t c, fp24_t a);
+
+/**
+ * Computes the square of a compressed cyclotomic extension field element using
+ * lazy reduction.
+ *
+ * A cyclotomic element is one raised to the (p^6 - 1)(p^2 + 1)-th power.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the cyclotomic extension element to square.
+ */
+void fp24_sqr_pck_lazyr(fp24_t c, fp24_t a);
+
+/**
+ * Tests if a 24-extension field element belongs to the cyclotomic
+ * subgroup.
+ *
+ * @param[in] a - the 24-extension field element to test.
+ * @return 1 if the extension field element is in the subgroup, 0 otherwise.
+ */
+int fp24_test_cyc(fp24_t a);
+
+/**
+ * Converts a 24-extension field element to a cyclotomic element.
+ * Computes c = a^(p^6 - 1)*(p^2 + 1).
+ *
+ * @param[out] c - the result.
+ * @param[in] a - a 24-extension field element.
+ */
+void fp24_conv_cyc(fp24_t c, fp24_t a);
+
+/**
+ * Decompresses a compressed cyclotomic extension field element.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the 24-extension field element to decompress.
+ */
+void fp24_back_cyc(fp24_t c, fp24_t a);
+
+/**
+ * Decompresses multiple compressed cyclotomic extension field elements.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the 24 field elements to decompress.
+ * @param[in] n - the number of field elements to decompress.
+ */
+void fp24_back_cyc_sim(fp24_t *c, fp24_t *a, int n);
+
/**
* Inverts a 24-degree extension field element. Computes c = 1/a.
*
@@ -3751,6 +3892,16 @@ void fp24_sqr_lazyr(fp24_t c, fp24_t a);
*/
void fp24_inv(fp24_t c, fp24_t a);
+/**
+ * Computes the inverse of a cyclotomic octdecic extension field element.
+ * For unitary elements, this is equivalent to computing the conjugate.
+ * A unitary element is one previously raised to the (p^12 - 1)-th power.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the 24-degree extension field element to invert.
+ */
+void fp24_inv_cyc(fp24_t c, fp24_t a);
+
/**
* Computes the Frobenius endomorphism of a 24-degree extension element.
* Computes c = a^p.
@@ -3771,6 +3922,64 @@ void fp24_frb(fp24_t c, fp24_t a, int i);
*/
void fp24_exp(fp24_t c, fp24_t a, bn_t b);
+/**
+ * Computes a power of a 24-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 fp24_exp_dig(fp24_t c, fp24_t a, dig_t b);
+
+/**
+ * Computes a power of a cyclotomic 24-extension field element.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the basis.
+ * @param[in] b - the exponent.
+ */
+void fp24_exp_cyc(fp24_t c, fp24_t a, bn_t b);
+
+/**
+ * Computes a power of a cyclotomic dodecic extension field element.
+ *
+ * @param[out] e - the result.
+ * @param[in] a - the first element to exponentiate.
+ * @param[in] b - the first exponent.
+ * @param[in] c - the second element to exponentiate.
+ * @param[in] d - the second exponent.
+ */
+void fp24_exp_cyc_sim(fp24_t e, fp24_t a, bn_t b, fp24_t c, bn_t d);
+
+/**
+ * Computes a power of a cyclotomic 24-extension field element.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the basis.
+ * @param[in] b - the exponent in sparse form.
+ * @param[in] l - the length of the exponent in sparse form.
+ * @param[in] s - the sign of the exponent.
+ */
+void fp24_exp_cyc_sps(fp24_t c, fp24_t a, const int *b, int l, int s);
+
+/**
+ * Compresses a 24-extension field element.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the 24-extension field element to compress.
+ */
+void fp24_pck(fp24_t c, fp24_t a);
+
+/**
+ * Decompresses a 24-extension field element.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the 24-extension field element to decompress.
+ * @return if the decompression was successful
+ */
+int fp24_upk(fp24_t c, fp24_t a);
+
/**
* Copies the second argument to the first argument.
*
@@ -4055,15 +4264,6 @@ void fp48_inv(fp48_t c, fp48_t a);
*/
void fp48_inv_cyc(fp48_t c, fp48_t a);
-/**
- * Converts a 48-extension field element to a cyclotomic element. Computes
- * c = a^(p^6 - 1).
- *
- * @param[out] c - the result.
- * @param[in] a - the 48-extension field element.
- */
-void fp48_conv_cyc(fp48_t c, fp48_t a);
-
/**
* Computes the Frobenius endomorphism of a 48-extension element.
* Computes c = a^p.
@@ -4415,15 +4615,6 @@ void fp54_inv(fp54_t c, fp54_t a);
*/
void fp54_inv_cyc(fp54_t c, fp54_t a);
-/**
- * Converts a 54-extension field element to a cyclotomic element. Computes
- * c = a^(p^6 - 1).
- *
- * @param[out] c - the result.
- * @param[in] a - the 54-extension field element.
- */
-void fp54_conv_cyc(fp54_t c, fp54_t a);
-
/**
* Computes the Frobenius endomorphism of a 54-extension element.
* Computes c = a^p.
diff --git a/contrib/relic/include/relic_label.h b/contrib/relic/include/relic_label.h
index 7b1822876..18d88c5fa 100644
--- a/contrib/relic/include/relic_label.h
+++ b/contrib/relic/include/relic_label.h
@@ -81,6 +81,7 @@
#undef bench_after
#undef bench_compute
#undef bench_print
+#undef bench_total
#define bench_init RLC_PREFIX(bench_init)
#define bench_clean RLC_PREFIX(bench_clean)
@@ -90,6 +91,7 @@
#define bench_after RLC_PREFIX(bench_after)
#define bench_compute RLC_PREFIX(bench_compute)
#define bench_print RLC_PREFIX(bench_print)
+#define bench_total RLC_PREFIX(bench_total)
#undef err_simple_msg
#undef err_full_msg
@@ -105,12 +107,14 @@
#undef rand_clean
#undef rand_seed
#undef rand_seed
+#undef rand_check
#undef rand_bytes
#define rand_init RLC_PREFIX(rand_init)
#define rand_clean RLC_PREFIX(rand_clean)
#define rand_seed RLC_PREFIX(rand_seed)
#define rand_seed RLC_PREFIX(rand_seed)
+#define rand_check RLC_PREFIX(rand_check)
#define rand_bytes RLC_PREFIX(rand_bytes)
#undef test_fail
@@ -174,7 +178,7 @@
#define bn_st RLC_PREFIX(bn_st)
#define bn_t RLC_PREFIX(bn_t)
-#undef bn_init
+#undef bn_make
#undef bn_clean
#undef bn_grow
#undef bn_trim
@@ -227,6 +231,7 @@
#undef bn_div_dig
#undef bn_div_rem_dig
#undef bn_mod_inv
+#undef bn_mod_inv_sim
#undef bn_mod_2b
#undef bn_mod_dig
#undef bn_mod_basic
@@ -276,8 +281,9 @@
#undef bn_rec_reg
#undef bn_rec_jsf
#undef bn_rec_glv
+#undef bn_rec_frb
-#define bn_init RLC_PREFIX(bn_init)
+#define bn_make RLC_PREFIX(bn_make)
#define bn_clean RLC_PREFIX(bn_clean)
#define bn_grow RLC_PREFIX(bn_grow)
#define bn_trim RLC_PREFIX(bn_trim)
@@ -330,6 +336,7 @@
#define bn_div_dig RLC_PREFIX(bn_div_dig)
#define bn_div_rem_dig RLC_PREFIX(bn_div_rem_dig)
#define bn_mod_inv RLC_PREFIX(bn_mod_inv)
+#define bn_mod_inv_sim RLC_PREFIX(bn_mod_inv_sim)
#define bn_mod_2b RLC_PREFIX(bn_mod_2b)
#define bn_mod_dig RLC_PREFIX(bn_mod_dig)
#define bn_mod_basic RLC_PREFIX(bn_mod_basic)
@@ -379,6 +386,7 @@
#define bn_rec_reg RLC_PREFIX(bn_rec_reg)
#define bn_rec_jsf RLC_PREFIX(bn_rec_jsf)
#define bn_rec_glv RLC_PREFIX(bn_rec_glv)
+#define bn_rec_frb RLC_PREFIX(bn_rec_frb)
#undef bn_add1_low
#undef bn_addn_low
@@ -390,8 +398,10 @@
#undef bn_lshb_low
#undef bn_rsh1_low
#undef bn_rshb_low
+#undef bn_rshs_low
#undef bn_mula_low
#undef bn_mul1_low
+#undef bn_muls_low
#undef bn_muln_low
#undef bn_muld_low
#undef bn_sqra_low
@@ -410,8 +420,10 @@
#define bn_lshb_low RLC_PREFIX(bn_lshb_low)
#define bn_rsh1_low RLC_PREFIX(bn_rsh1_low)
#define bn_rshb_low RLC_PREFIX(bn_rshb_low)
+#define bn_rshs_low RLC_PREFIX(bn_rshs_low)
#define bn_mula_low RLC_PREFIX(bn_mula_low)
#define bn_mul1_low RLC_PREFIX(bn_mul1_low)
+#define bn_muls_low RLC_PREFIX(bn_muls_low)
#define bn_muln_low RLC_PREFIX(bn_muln_low)
#define bn_muld_low RLC_PREFIX(bn_muld_low)
#define bn_sqra_low RLC_PREFIX(bn_sqra_low)
@@ -502,8 +514,14 @@
#undef fp_inv_monty
#undef fp_inv_exgcd
#undef fp_inv_divst
+#undef fp_inv_jmpds
#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
@@ -586,8 +604,14 @@
#define fp_inv_monty RLC_PREFIX(fp_inv_monty)
#define fp_inv_exgcd RLC_PREFIX(fp_inv_exgcd)
#define fp_inv_divst RLC_PREFIX(fp_inv_divst)
+#define fp_inv_jmpds RLC_PREFIX(fp_inv_jmpds)
#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)
@@ -621,6 +645,7 @@
#undef fp_rdcs_low
#undef fp_rdcn_low
#undef fp_invm_low
+#undef fp_smbm_low
#define fp_add1_low RLC_PREFIX(fp_add1_low)
#define fp_addn_low RLC_PREFIX(fp_addn_low)
@@ -650,6 +675,7 @@
#define fp_rdcs_low RLC_PREFIX(fp_rdcs_low)
#define fp_rdcn_low RLC_PREFIX(fp_rdcn_low)
#define fp_invm_low RLC_PREFIX(fp_invm_low)
+#define fp_smbm_low RLC_PREFIX(fp_smbm_low)
#undef fp_st
#undef fp_t
@@ -908,6 +934,7 @@
#undef ep_dbl_slp_basic
#undef ep_dbl_projc
#undef ep_dbl_jacob
+#undef ep_psi
#undef ep_mul_basic
#undef ep_mul_slide
#undef ep_mul_monty
@@ -936,13 +963,12 @@
#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_dst
#undef ep_pck
#undef ep_upk
- multiplication function, #define ep_mul_basic RLC_PREFIX(ep_mul_basic)
#define ep_curve_init RLC_PREFIX(ep_curve_init)
#define ep_curve_clean RLC_PREFIX(ep_curve_clean)
#define ep_curve_get_a RLC_PREFIX(ep_curve_get_a)
@@ -1002,6 +1028,7 @@
#define ep_dbl_slp_basic RLC_PREFIX(ep_dbl_slp_basic)
#define ep_dbl_projc RLC_PREFIX(ep_dbl_projc)
#define ep_dbl_jacob RLC_PREFIX(ep_dbl_jacob)
+#define ep_psi RLC_PREFIX(ep_psi)
#define ep_mul_basic RLC_PREFIX(ep_mul_basic)
#define ep_mul_slide RLC_PREFIX(ep_mul_slide)
#define ep_mul_monty RLC_PREFIX(ep_mul_monty)
@@ -1030,9 +1057,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_dst RLC_PREFIX(ep_map_dst)
#define ep_pck RLC_PREFIX(ep_pck)
#define ep_upk RLC_PREFIX(ep_upk)
@@ -1223,8 +1250,7 @@
#undef eb_dbl_basic
#undef eb_dbl_projc
#undef eb_hlv
-#undef eb_frb_basic
-#undef eb_frb_projc
+#undef eb_frb
#undef eb_mul_basic
#undef eb_mul_lodah
#undef eb_mul_lwnaf
@@ -1296,8 +1322,7 @@
#define eb_dbl_basic RLC_PREFIX(eb_dbl_basic)
#define eb_dbl_projc RLC_PREFIX(eb_dbl_projc)
#define eb_hlv RLC_PREFIX(eb_hlv)
-#define eb_frb_basic RLC_PREFIX(eb_frb_basic)
-#define eb_frb_projc RLC_PREFIX(eb_frb_projc)
+#define eb_frb RLC_PREFIX(eb_frb)
#define eb_mul_basic RLC_PREFIX(eb_mul_basic)
#define eb_mul_lodah RLC_PREFIX(eb_mul_lodah)
#define eb_mul_lwnaf RLC_PREFIX(eb_mul_lwnaf)
@@ -1366,7 +1391,7 @@
#undef ep2_add_basic
#undef ep2_add_slp_basic
#undef ep2_add_projc
- #undef ep2_sub
+#undef ep2_sub
#undef ep2_dbl_basic
#undef ep2_dbl_slp_basic
#undef ep2_dbl_projc
@@ -1399,6 +1424,7 @@
#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_frb
@@ -1438,7 +1464,7 @@
#define ep2_add_basic RLC_PREFIX(ep2_add_basic)
#define ep2_add_slp_basic RLC_PREFIX(ep2_add_slp_basic)
#define ep2_add_projc RLC_PREFIX(ep2_add_projc)
- #define ep2_sub RLC_PREFIX(ep2_sub)
+#define ep2_sub RLC_PREFIX(ep2_sub)
#define ep2_dbl_basic RLC_PREFIX(ep2_dbl_basic)
#define ep2_dbl_slp_basic RLC_PREFIX(ep2_dbl_slp_basic)
#define ep2_dbl_projc RLC_PREFIX(ep2_dbl_projc)
@@ -1471,6 +1497,7 @@
#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_frb RLC_PREFIX(ep2_frb)
@@ -1766,6 +1793,7 @@
#define fp3_sqrm_low RLC_PREFIX(fp3_sqrm_low)
#define fp3_rdcn_low RLC_PREFIX(fp3_rdcn_low)
+#undef fp4_field_init
#undef fp4_copy
#undef fp4_zero
#undef fp4_is_zero
@@ -1785,15 +1813,19 @@
#undef fp4_mul_basic
#undef fp4_mul_lazyr
#undef fp4_mul_art
+#undef fp4_mul_frb
#undef fp4_mul_dxs
#undef fp4_sqr_unr
#undef fp4_sqr_basic
#undef fp4_sqr_lazyr
#undef fp4_inv
+#undef fp4_inv_sim
#undef fp4_inv_cyc
#undef fp4_exp
#undef fp4_frb
+#undef fp4_srt
+#define fp4_field_init RLC_PREFIX(fp4_field_init)
#define fp4_copy RLC_PREFIX(fp4_copy)
#define fp4_zero RLC_PREFIX(fp4_zero)
#define fp4_is_zero RLC_PREFIX(fp4_is_zero)
@@ -1813,14 +1845,17 @@
#define fp4_mul_basic RLC_PREFIX(fp4_mul_basic)
#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_dxs RLC_PREFIX(fp4_mul_dxs)
#define fp4_sqr_unr RLC_PREFIX(fp4_sqr_unr)
#define fp4_sqr_basic RLC_PREFIX(fp4_sqr_basic)
#define fp4_sqr_lazyr RLC_PREFIX(fp4_sqr_lazyr)
#define fp4_inv RLC_PREFIX(fp4_inv)
+#define fp4_inv_sim RLC_PREFIX(fp4_inv_sim)
#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_srt RLC_PREFIX(fp4_srt)
#undef fp6_copy
#undef fp6_zero
@@ -2171,9 +2206,24 @@
#undef fp24_sqr_unr
#undef fp24_sqr_basic
#undef fp24_sqr_lazyr
+#undef fp24_sqr_cyc_basic
+#undef fp24_sqr_cyc_lazyr
+#undef fp24_sqr_pck_basic
+#undef fp24_sqr_pck_lazyr
+#undef fp24_test_cyc
+#undef fp24_conv_cyc
+#undef fp24_back_cyc
+#undef fp24_back_cyc_sim
#undef fp24_inv
+#undef fp24_inv_cyc
#undef fp24_frb
#undef fp24_exp
+#undef fp24_exp_dig
+#undef fp24_exp_cyc
+#undef fp24_exp_cyc_sim
+#undef fp24_exp_cyc_sps
+#undef fp24_pck
+#undef fp24_upk
#define fp24_copy RLC_PREFIX(fp24_copy)
#define fp24_zero RLC_PREFIX(fp24_zero)
@@ -2198,9 +2248,24 @@
#define fp24_sqr_unr RLC_PREFIX(fp24_sqr_unr)
#define fp24_sqr_basic RLC_PREFIX(fp24_sqr_basic)
#define fp24_sqr_lazyr RLC_PREFIX(fp24_sqr_lazyr)
+#define fp24_sqr_cyc_basic RLC_PREFIX(fp24_sqr_cyc_basic)
+#define fp24_sqr_cyc_lazyr RLC_PREFIX(fp24_sqr_cyc_lazyr)
+#define fp24_sqr_pck_basic RLC_PREFIX(fp24_sqr_pck_basic)
+#define fp24_sqr_pck_lazyr RLC_PREFIX(fp24_sqr_pck_lazyr)
+#define fp24_test_cyc RLC_PREFIX(fp24_test_cyc)
+#define fp24_conv_cyc RLC_PREFIX(fp24_conv_cyc)
+#define fp24_back_cyc RLC_PREFIX(fp24_back_cyc)
+#define fp24_back_cyc_sim RLC_PREFIX(fp24_back_cyc_sim)
#define fp24_inv RLC_PREFIX(fp24_inv)
+#define fp24_inv_cyc RLC_PREFIX(fp24_inv_cyc)
#define fp24_frb RLC_PREFIX(fp24_frb)
#define fp24_exp RLC_PREFIX(fp24_exp)
+#define fp24_exp_dig RLC_PREFIX(fp24_exp_dig)
+#define fp24_exp_cyc RLC_PREFIX(fp24_exp_cyc)
+#define fp24_exp_cyc_sim RLC_PREFIX(fp24_exp_cyc_sim)
+#define fp24_exp_cyc_sps RLC_PREFIX(fp24_exp_cyc_sps)
+#define fp24_pck RLC_PREFIX(fp24_pck)
+#define fp24_upk RLC_PREFIX(fp24_upk)
#undef fp48_copy
#undef fp48_zero
@@ -2388,6 +2453,8 @@
#undef pp_add_k12_projc_basic
#undef pp_add_k12_projc_lazyr
#undef pp_add_lit_k12
+#undef pp_add_k24_basic
+#undef pp_add_k24_projc
#undef pp_add_k48_basic
#undef pp_add_k48_projc
#undef pp_add_k54_basic
@@ -2401,6 +2468,8 @@
#undef pp_dbl_k12_basic
#undef pp_dbl_k12_projc_basic
#undef pp_dbl_k12_projc_lazyr
+#undef pp_dbl_k24_basic
+#undef pp_dbl_k24_projc
#undef pp_dbl_k48_basic
#undef pp_dbl_k48_projc
#undef pp_dbl_k54_basic
@@ -2409,11 +2478,13 @@
#undef pp_exp_k2
#undef pp_exp_k8
#undef pp_exp_k12
+#undef pp_exp_k24
#undef pp_exp_k48
#undef pp_exp_k54
#undef pp_norm_k2
#undef pp_norm_k8
#undef pp_norm_k12
+#undef pp_norm_k24
#undef pp_map_tatep_k2
#undef pp_map_sim_tatep_k2
#undef pp_map_weilp_k2
@@ -2425,6 +2496,8 @@
#undef pp_map_sim_weilp_k12
#undef pp_map_oatep_k12
#undef pp_map_sim_oatep_k12
+#undef pp_map_k24
+#undef pp_map_sim_k24
#undef pp_map_k48
#undef pp_map_k54
@@ -2440,6 +2513,8 @@
#define pp_add_k12_projc_basic RLC_PREFIX(pp_add_k12_projc_basic)
#define pp_add_k12_projc_lazyr RLC_PREFIX(pp_add_k12_projc_lazyr)
#define pp_add_lit_k12 RLC_PREFIX(pp_add_lit_k12)
+#define pp_add_k24_basic RLC_PREFIX(pp_add_k24_basic)
+#define pp_add_k24_projc RLC_PREFIX(pp_add_k24_projc)
#define pp_add_k48_basic RLC_PREFIX(pp_add_k48_basic)
#define pp_add_k48_projc RLC_PREFIX(pp_add_k48_projc)
#define pp_add_k54_basic RLC_PREFIX(pp_add_k54_basic)
@@ -2453,6 +2528,8 @@
#define pp_dbl_k12_basic RLC_PREFIX(pp_dbl_k12_basic)
#define pp_dbl_k12_projc_basic RLC_PREFIX(pp_dbl_k12_projc_basic)
#define pp_dbl_k12_projc_lazyr RLC_PREFIX(pp_dbl_k12_projc_lazyr)
+#define pp_dbl_k24_basic RLC_PREFIX(pp_dbl_k24_basic)
+#define pp_dbl_k24_projc RLC_PREFIX(pp_dbl_k24_projc)
#define pp_dbl_k48_basic RLC_PREFIX(pp_dbl_k48_basic)
#define pp_dbl_k48_projc RLC_PREFIX(pp_dbl_k48_projc)
#define pp_dbl_k54_basic RLC_PREFIX(pp_dbl_k54_basic)
@@ -2461,11 +2538,13 @@
#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)
+#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_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_k24 RLC_PREFIX(pp_norm_k24)
#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_k2 RLC_PREFIX(pp_map_weilp_k2)
@@ -2477,6 +2556,8 @@
#define pp_map_sim_weilp_k12 RLC_PREFIX(pp_map_sim_weilp_k12)
#define pp_map_oatep_k12 RLC_PREFIX(pp_map_oatep_k12)
#define pp_map_sim_oatep_k12 RLC_PREFIX(pp_map_sim_oatep_k12)
+#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_k54 RLC_PREFIX(pp_map_k54)
@@ -2523,6 +2604,22 @@
#undef cp_ecss_gen
#undef cp_ecss_sig
#undef cp_ecss_ver
+#undef cp_pdpub_gen
+#undef cp_pdpub_ask
+#undef cp_pdpub_ans
+#undef cp_pdpub_ver
+#undef cp_pdprv_gen
+#undef cp_pdprv_ask
+#undef cp_pdprv_ans
+#undef cp_pdprv_ver
+#undef cp_lvpub_gen
+#undef cp_lvpub_ask
+#undef cp_lvpub_ans
+#undef cp_lvpub_ver
+#undef cp_lvprv_gen
+#undef cp_lvprv_ask
+#undef cp_lvprv_ans
+#undef cp_lvprv_ver
#undef cp_sokaka_gen
#undef cp_sokaka_gen_prv
#undef cp_sokaka_key
@@ -2574,6 +2671,26 @@
#undef cp_vbnn_gen_prv
#undef cp_vbnn_sig
#undef cp_vbnn_ver
+#undef cp_pokdl_prv
+#undef cp_pokdl_ver
+#undef cp_pokor_prv
+#undef cp_pokor_ver
+#undef cp_sokdl_sig
+#undef cp_sokdl_ver
+#undef cp_sokor_sig
+#undef cp_sokor_ver
+#undef cp_ers_gen
+#undef cp_ers_gen_key
+#undef cp_ers_sig
+#undef cp_ers_ver
+#undef cp_ers_ext
+#undef cp_smlers_sig
+#undef cp_smlers_ver
+#undef cp_smlers_ext
+#undef cp_etrs_sig
+#undef cp_etrs_ver
+#undef cp_etrs_ext
+#undef cp_etrs_uni
#undef cp_cmlhs_init
#undef cp_cmlhs_gen
#undef cp_cmlhs_sig
@@ -2589,6 +2706,10 @@
#undef cp_mklhs_ver
#undef cp_mklhs_off
#undef cp_mklhs_onv
+#undef cp_lapsi_gen
+#undef cp_lapsi_ask
+#undef cp_lapsi_ans
+#undef cp_lapsi_int
#define cp_rsa_gen RLC_PREFIX(cp_rsa_gen)
#define cp_rsa_enc RLC_PREFIX(cp_rsa_enc)
@@ -2620,6 +2741,22 @@
#define cp_ecss_gen RLC_PREFIX(cp_ecss_gen)
#define cp_ecss_sig RLC_PREFIX(cp_ecss_sig)
#define cp_ecss_ver RLC_PREFIX(cp_ecss_ver)
+#define cp_pdpub_gen RLC_PREFIX(cp_pdpub_gen)
+#define cp_pdpub_ask RLC_PREFIX(cp_pdpub_ask)
+#define cp_pdpub_ans RLC_PREFIX(cp_pdpub_ans)
+#define cp_pdpub_ver RLC_PREFIX(cp_pdpub_ver)
+#define cp_pdprv_gen RLC_PREFIX(cp_pdprv_gen)
+#define cp_pdprv_ask RLC_PREFIX(cp_pdprv_ask)
+#define cp_pdprv_ans RLC_PREFIX(cp_pdprv_ans)
+#define cp_pdprv_ver RLC_PREFIX(cp_pdprv_ver)
+#define cp_lvpub_gen RLC_PREFIX(cp_lvpub_gen)
+#define cp_lvpub_ask RLC_PREFIX(cp_lvpub_ask)
+#define cp_lvpub_ans RLC_PREFIX(cp_lvpub_ans)
+#define cp_lvpub_ver RLC_PREFIX(cp_lvpub_ver)
+#define cp_lvprv_gen RLC_PREFIX(cp_lvprv_gen)
+#define cp_lvprv_ask RLC_PREFIX(cp_lvprv_ask)
+#define cp_lvprv_ans RLC_PREFIX(cp_lvprv_ans)
+#define cp_lvprv_ver RLC_PREFIX(cp_lvprv_ver)
#define cp_sokaka_gen RLC_PREFIX(cp_sokaka_gen)
#define cp_sokaka_gen_prv RLC_PREFIX(cp_sokaka_gen_prv)
#define cp_sokaka_key RLC_PREFIX(cp_sokaka_key)
@@ -2671,6 +2808,26 @@
#define cp_vbnn_gen_prv RLC_PREFIX(cp_vbnn_gen_prv)
#define cp_vbnn_sig RLC_PREFIX(cp_vbnn_sig)
#define cp_vbnn_ver RLC_PREFIX(cp_vbnn_ver)
+#define cp_pokdl_prv RLC_PREFIX(cp_pokdl_prv)
+#define cp_pokdl_ver RLC_PREFIX(cp_pokdl_ver)
+#define cp_pokor_prv RLC_PREFIX(cp_pokor_prv)
+#define cp_pokor_ver RLC_PREFIX(cp_pokor_ver)
+#define cp_sokdl_sig RLC_PREFIX(cp_sokdl_sig)
+#define cp_sokdl_ver RLC_PREFIX(cp_sokdl_ver)
+#define cp_sokor_sig RLC_PREFIX(cp_sokor_sig)
+#define cp_sokor_ver RLC_PREFIX(cp_sokor_ver)
+#define cp_ers_gen RLC_PREFIX(cp_ers_gen)
+#define cp_ers_gen_key RLC_PREFIX(cp_ers_gen_key)
+#define cp_ers_sig RLC_PREFIX(cp_ers_sig)
+#define cp_ers_ver RLC_PREFIX(cp_ers_ver)
+#define cp_ers_ext RLC_PREFIX(cp_ers_ext)
+#define cp_smlers_sig RLC_PREFIX(cp_smlers_sig)
+#define cp_smlers_ver RLC_PREFIX(cp_smlers_ver)
+#define cp_smlers_ext RLC_PREFIX(cp_smlers_ext)
+#define cp_etrs_sig RLC_PREFIX(cp_etrs_sig)
+#define cp_etrs_ver RLC_PREFIX(cp_etrs_ver)
+#define cp_etrs_ext RLC_PREFIX(cp_etrs_ext)
+#define cp_etrs_uni RLC_PREFIX(cp_etrs_uni)
#define cp_cmlhs_init RLC_PREFIX(cp_cmlhs_init)
#define cp_cmlhs_gen RLC_PREFIX(cp_cmlhs_gen)
#define cp_cmlhs_sig RLC_PREFIX(cp_cmlhs_sig)
@@ -2686,6 +2843,10 @@
#define cp_mklhs_ver RLC_PREFIX(cp_mklhs_ver)
#define cp_mklhs_off RLC_PREFIX(cp_mklhs_off)
#define cp_mklhs_onv RLC_PREFIX(cp_mklhs_onv)
+#define cp_lapsi_gen RLC_PREFIX(cp_lapsi_gen)
+#define cp_lapsi_ask RLC_PREFIX(cp_lapsi_ask)
+#define cp_lapsi_ans RLC_PREFIX(cp_lapsi_ans)
+#define cp_lapsi_int RLC_PREFIX(cp_lapsi_int)
#undef md_map_sh224
#undef md_map_sh256
diff --git a/contrib/relic/include/relic_md.h b/contrib/relic/include/relic_md.h
index 1a16b8423..a624b66cc 100644
--- a/contrib/relic/include/relic_md.h
+++ b/contrib/relic/include/relic_md.h
@@ -96,9 +96,9 @@ enum {
#define md_map(H, M, L) md_map_sh384(H, M, L)
#elif MD_MAP == SH512
#define md_map(H, M, L) md_map_sh512(H, M, L)
-#elif MD_MAP == BLAKE2S_160
+#elif MD_MAP == B2S160
#define md_map(H, M, L) md_map_b2s160(H, M, L)
-#elif MD_MAP == BLAKE2S_256
+#elif MD_MAP == B2S256
#define md_map(H, M, L) md_map_b2s256(H, M, L)
#endif
diff --git a/contrib/relic/include/relic_pc.h b/contrib/relic/include/relic_pc.h
index aa7198964..5c55b1055 100644
--- a/contrib/relic/include/relic_pc.h
+++ b/contrib/relic/include/relic_pc.h
@@ -54,12 +54,26 @@
*/
/** @{ */
#if FP_PRIME < 1536
+
#define RLC_G1_LOWER ep_
#define RLC_G1_UPPER EP
+
+#if FP_PRIME == 509
+#define RLC_G2_LOWER ep4_
+#else
#define RLC_G2_LOWER ep2_
+#endif
+
#define RLC_G2_UPPER EP
+
+#if FP_PRIME == 509
+#define RLC_GT_LOWER fp24_
+#else
#define RLC_GT_LOWER fp12_
+#endif
+
#define RLC_PC_LOWER pp_
+
#else
#define RLC_G1_LOWER ep_
#define RLC_G1_UPPER EP
@@ -246,7 +260,23 @@ typedef RLC_CAT(RLC_GT_LOWER, t) gt_t;
#define pc_param_level() RLC_CAT(RLC_G1_LOWER, param_level)()
/**
- * Tests if a G_1 element is the unity.
+ * Tests if a G_1 element is on the curve.
+ *
+ * @param[in] P - the element to test.
+ * @return 1 if the element it the unity, 0 otherwise.
+ */
+#define g1_on_curve(P) RLC_CAT(RLC_G1_LOWER, on_curve)(P)
+
+/**
+ * Tests if a G_2 element is on the curve.
+ *
+ * @param[in] P - the element to test.
+ * @return 1 if the element it the unity, 0 otherwise.
+ */
+#define g2_on_curve(P) RLC_CAT(RLC_G2_LOWER, on_curve)(P)
+
+/**
+ * Tests if a G_1 element is the point at infinity.
*
* @param[in] P - the element to test.
* @return 1 if the element it the unity, 0 otherwise.
@@ -254,7 +284,7 @@ typedef RLC_CAT(RLC_GT_LOWER, t) gt_t;
#define g1_is_infty(P) RLC_CAT(RLC_G1_LOWER, is_infty)(P)
/**
- * Tests if a G_2 element is the unity.
+ * Tests if a G_2 element is the point at infinity.
*
* @param[in] P - the element to test.
* @return 1 if the element it the unity, 0 otherwise.
@@ -262,7 +292,7 @@ typedef RLC_CAT(RLC_GT_LOWER, t) gt_t;
#define g2_is_infty(P) RLC_CAT(RLC_G2_LOWER, is_infty)(P)
/**
- * Tests if a G_T element is the unity.
+ * Tests if a G_T element is the identity.
*
* @param[in] A - the element to test.
* @return 1 if the element it the unity, 0 otherwise.
@@ -652,15 +682,6 @@ typedef RLC_CAT(RLC_GT_LOWER, t) gt_t;
*/
#define g2_mul_dig(R, P, K) RLC_CAT(RLC_G2_LOWER, mul_dig)(R, P, K)
-/**
- * Exponentiates an element from G_T by a small integer. Computes c = a^b.
- *
- * @param[out] R - the result.
- * @param[in] P - the element to multiply.
- * @param[in] K - the small integer.
- */
-#define gt_exp_dig(C, A, B) RLC_CAT(RLC_GT_LOWER, exp_dig)(C, A, B)
-
/**
* Builds a precomputation table for multiplying an element from G_1.
*
@@ -781,6 +802,16 @@ typedef RLC_CAT(RLC_GT_LOWER, t) gt_t;
*/
#define g2_mul_sim_gen(R, K, Q, L) RLC_CAT(RLC_G2_LOWER, mul_sim_gen)(R, K, Q, L)
+/**
+ * Exponetiates a G_2 element using the i-th power Frobenius.
+ * Computes C = [p^i]A.
+ *
+ * @param[out] C - the result.
+ * @param[in] A - the element to exponentiate.
+ * @param[in] I - the power of the Frobenius map.
+ */
+#define g2_frb(C, A, I) RLC_CAT(RLC_G2_LOWER, frb)(C, A, I)
+
/**
* Exponetiates a G_T element using the i-th power Frobenius.
* Computes C = A^(p^i).
@@ -818,9 +849,17 @@ typedef RLC_CAT(RLC_GT_LOWER, t) gt_t;
* @param[in] Q - the second element.
*/
#if FP_PRIME < 1536
+
+#if FP_PRIME == 509
+#define pc_map(R, P, Q); RLC_CAT(RLC_PC_LOWER, map_k24)(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
/**
@@ -833,7 +872,13 @@ typedef RLC_CAT(RLC_GT_LOWER, t) gt_t;
* @param[in] M - the number of pairing arguments.
*/
#if FP_PRIME < 1536
+
+#if FP_PRIME == 509
+#define pc_map_sim(R, P, Q, M); RLC_CAT(RLC_PC_LOWER, map_sim_k24)(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
@@ -845,7 +890,13 @@ typedef RLC_CAT(RLC_GT_LOWER, t) gt_t;
* @param[in] A - the field element to exponentiate.
*/
#if FP_PRIME < 1536
+
+#if FP_PRIME == 509
+#define pc_exp(C, A); RLC_CAT(RLC_PC_LOWER, exp_k24)(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
@@ -920,6 +971,15 @@ void g2_mul_gen(g2_t r, bn_t k);
*/
void gt_exp(gt_t c, gt_t a, bn_t b);
+/**
+ * Exponentiates an element from G_T by a small integer. Computes c = a^b.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the element to exponentiate.
+ * @param[in] b - the integer exponent.
+ */
+void gt_exp_dig(gt_t c, gt_t a, dig_t b);
+
/**
* Exponentiates two element from G_T by integers simultaneously. Computes
* e = a^b * c^d.
diff --git a/contrib/relic/include/relic_pp.h b/contrib/relic/include/relic_pp.h
index 5d4db85ab..4baee4c32 100644
--- a/contrib/relic/include/relic_pp.h
+++ b/contrib/relic/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 2 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.
+ */
+#if PP_EXT == BASIC
+#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)
+#endif
+
/**
* Adds two points and evaluates the corresponding line function at another
* point on an elliptic curve with embedding degree 2.
@@ -62,18 +78,18 @@
/**
* Adds two points and evaluates the corresponding line function at another
- * point on an elliptic curve with embedding degree 2 using projective
+ * point on an elliptic curve with embedding degree 8 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.
+ * @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_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_k8_projc(L, R, Q, P) pp_add_k8_projc_basic(L, R, Q, P)
+#elif PP_EXT == LAZYR
+#define pp_add_k8_projc(L, R, Q, P) pp_add_k8_projc_lazyr(L, R, Q, P)
#endif
/**
@@ -93,7 +109,7 @@
/**
* Adds two points and evaluates the corresponding line function at another
- * point on an elliptic curve with embedding degree 8 using projective
+ * point on an elliptic curve with embedding degree 12 using projective
* coordinates.
*
* @param[out] L - the result of the evaluation.
@@ -102,9 +118,9 @@
* @param[in] P - the affine point to evaluate the line function.
*/
#if PP_EXT == BASIC
-#define pp_add_k8_projc(L, R, Q, P) pp_add_k8_projc_basic(L, R, Q, P)
+#define pp_add_k12_projc(L, R, Q, P) pp_add_k12_projc_basic(L, R, Q, P)
#elif PP_EXT == LAZYR
-#define pp_add_k8_projc(L, R, Q, P) pp_add_k8_projc_lazyr(L, R, Q, P)
+#define pp_add_k12_projc(L, R, Q, P) pp_add_k12_projc_lazyr(L, R, Q, P)
#endif
/**
@@ -124,18 +140,17 @@
/**
* Adds two points and evaluates the corresponding line function at another
- * point on an elliptic curve with embedding degree 12 using projective
- * coordinates.
+ * point on an elliptic curve with embedding degree 24.
*
* @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_k12_projc(L, R, Q, P) pp_add_k12_projc_basic(L, R, Q, P)
-#elif PP_EXT == LAZYR
-#define pp_add_k12_projc(L, R, Q, P) pp_add_k12_projc_lazyr(L, R, Q, P)
+#if EP_ADD == BASIC
+#define pp_add_k24(L, R, Q, P) pp_add_k24_basic(L, R, Q, P)
+#else
+#define pp_add_k24(L, R, Q, P) pp_add_k24_projc(L, R, Q, P)
#endif
/**
@@ -168,6 +183,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 2 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_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)
+#endif
+
/**
* Doubles a point and evaluates the corresponding line function at another
* point on an elliptic curve with embedding degree 2.
@@ -185,22 +216,23 @@
/**
* Doubles a point and evaluates the corresponding line function at another
- * point on an elliptic curve with embedding degree 8.
+ * point on an elliptic curve with embedding degree 12 using projective
+ * coordinates.
*
* @param[out] L - the result of the evaluation.
- * @param[out] R - the resulting point.
+ * @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 EP_ADD == BASIC
-#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)
+#if PP_EXT == BASIC
+#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)
#endif
/**
* Doubles a point and evaluates the corresponding line function at another
- * point on an elliptic curve with embedding degree 12.
+ * point on an elliptic curve with embedding degree 8.
*
* @param[out] L - the result of the evaluation.
* @param[out] R - the resulting point.
@@ -208,9 +240,9 @@
* @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_k8(L, R, Q, P) pp_dbl_k8_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_k8(L, R, Q, P) pp_dbl_k8_projc(L, R, Q, P)
#endif
/**
@@ -224,41 +256,39 @@
* @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_k12_projc(L, R, Q, P) pp_dbl_k12_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_k12_projc(L, R, Q, P) pp_dbl_k12_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 2 using projective
- * coordinates.
+ * point on an elliptic curve with embedding degree 12.
*
* @param[out] L - the result of the evaluation.
- * @param[in, out] R - the resulting point.
+ * @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 PP_EXT == BASIC
-#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)
+#if EP_ADD == BASIC
+#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)
#endif
/**
* Doubles a point and evaluates the corresponding line function at another
- * point on an elliptic curve with embedding degree 12 using projective
- * coordinates.
+ * point on an elliptic curve with embedding degree 24.
*
* @param[out] L - the result of the evaluation.
- * @param[in, out] R - the resulting point.
+ * @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 PP_EXT == BASIC
-#define pp_dbl_k12_projc(L, R, Q, P) pp_dbl_k12_projc_basic(L, R, Q, P)
-#elif PP_EXT == LAZYR
-#define pp_dbl_k12_projc(L, R, Q, P) pp_dbl_k12_projc_lazyr(L, R, Q, P)
+#if EP_ADD == BASIC
+#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)
#endif
/**
@@ -487,6 +517,29 @@ void pp_add_k12_projc_lazyr(fp12_t l, ep2_t r, ep2_t q, ep_t p);
*/
void pp_add_lit_k12(fp12_t l, ep_t r, ep_t p, ep2_t q);
+/**
+ * Adds two points and evaluates the corresponding line function at another
+ * point on an elliptic curve with embedding degree 24 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_k24_basic(fp24_t l, ep4_t r, ep4_t q, ep_t p);
+
+/**
+ * Adds two points and evaluates the corresponding line function at another
+ * point on an elliptic curve with embedding degree 24 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_k24_projc(fp24_t l, ep4_t r, ep4_t q, ep_t p);
+
/**
* Adds two points and evaluates the corresponding line function at another
* point on an elliptic curve with embedding degree 48 using affine coordinates.
@@ -641,6 +694,30 @@ void pp_dbl_k12_projc_basic(fp12_t l, ep2_t r, ep2_t q, ep_t p);
*/
void pp_dbl_k12_projc_lazyr(fp12_t l, ep2_t r, ep2_t q, ep_t p);
+/**
+ * Doubles a point and evaluates the corresponding line function at another
+ * point on an elliptic curve with embedding degree 24 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_k24_basic(fp24_t l, ep4_t r, ep4_t q, ep_t p);
+
+/**
+ * Doubles a point and evaluates the corresponding line function at another
+ * point on an elliptic curve with embedding degree 24 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_k24_projc(fp24_t l, ep4_t r, ep4_t q, ep_t p);
+
/**
* Doubles a point and evaluates the corresponding line function at another
* point on an elliptic curve with embedding degree 48 using affine
@@ -728,6 +805,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 24. Computes c = a^(p^24 - 1)/r.
+ *
+ * @param[out] c - the result.
+ * @param[in] a - the extension field element to exponentiate.
+ */
+void pp_exp_k24(fp24_t c, fp24_t a);
+
/**
* Computes the final exponentiation for a pairing defined over curves of
* embedding degree 48. Computes c = a^(p^48 - 1)/r.
@@ -773,6 +859,15 @@ void pp_norm_k8(ep2_t c, ep2_t a);
*/
void pp_norm_k12(ep2_t c, ep2_t a);
+/**
+ * Normalizes the accumulator point used inside pairing computation defined
+ * over curves of embedding degree 24.
+ *
+ * @param[out] r - the resulting point.
+ * @param[in] p - the point to normalize.
+ */
+void pp_norm_k24(ep4_t c, ep4_t a);
+
/**
* Computes the Tate pairing of two points in a parameterized elliptic curve
* with embedding degree 12.
@@ -888,6 +983,27 @@ void pp_map_oatep_k12(fp12_t r, ep_t p, ep2_t q);
*/
void pp_map_sim_oatep_k12(fp12_t r, ep_t *p, ep2_t *q, int m);
+/**
+ * Computes the Optimal Ate pairing of two points in a parameterized elliptic
+ * curve with embedding degree 24.
+ *
+ * @param[out] r - the result.
+ * @param[in] q - the first elliptic curve point.
+ * @param[in] p - the second elliptic curve point.
+ */
+void pp_map_k24(fp24_t r, ep_t p, ep4_t q);
+
+/**
+ * Computes the optimal ate multi-pairing of in a parameterized elliptic
+ * curve with embedding degree 24.
+ *
+ * @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_k24(fp24_t r, ep_t *p, ep4_t *q, int m);
+
/**
* Computes the Optimal Ate pairing of two points in a parameterized elliptic
* curve with embedding degree 48.
diff --git a/contrib/relic/include/relic_rand.h b/contrib/relic/include/relic_rand.h
index 320507fb0..bf92ac376 100644
--- a/contrib/relic/include/relic_rand.h
+++ b/contrib/relic/include/relic_rand.h
@@ -47,7 +47,7 @@
*/
#if RAND == HASHD
-#if MD_MAP == SH224 || MD_MAP == SH256 || MD_MAP == BLAKE2S_160 || MD_MAP == BLAKE2S_256
+#if MD_MAP == SH224 || MD_MAP == SH256 || MD_MAP == B2S160 || MD_MAP == B2S256
#define RLC_RAND_SIZE (1 + 2*440/8)
#elif MD_MAP == SH384 || MD_MAP == SH512
#define RLC_RAND_SIZE (1 + 2*888/8)
@@ -104,6 +104,16 @@ void rand_seed(void (*callback)(uint8_t *, int, void *), void *arg);
#endif
+/**
+ * Performs a basic self-test in the pseudo-random number generator output, and
+ * raises an exception in case a string of identifical bytes is found.
+ *
+ * @param[out] buf - the buffer to check.
+ * @param[in] size - the number of bytes to check.
+ * @throw ERR_NO_RAND - if the pseudo-random number generator is stuck.
+ */
+int rand_check(uint8_t *buf, int size);
+
/**
* Gathers pseudo-random bytes from the pseudo-random number generator.
*
diff --git a/contrib/relic/include/relic_types.h b/contrib/relic/include/relic_types.h
index 5e38a69e8..92316bfec 100644
--- a/contrib/relic/include/relic_types.h
+++ b/contrib/relic/include/relic_types.h
@@ -40,6 +40,10 @@
#include
#endif
+#if defined(_MSC_VER) && WSIZE == 64
+#include
+#endif
+
/*============================================================================*/
/* Constant definitions */
/*============================================================================*/
@@ -109,12 +113,48 @@ typedef uint32_t dbl_t;
#elif WSIZE == 32
typedef uint64_t dbl_t;
#elif WSIZE == 64
-#if defined(__GNUC__) && !defined(__INTEL_COMPILER)
+#ifdef _MSC_VER
+/** MSVS does not support 128-bit type. */
+#define RLC_CONF_NODBL
+#else
typedef __uint128_t dbl_t;
-#elif ARITH == EASY
-#error "Easy backend in 64-bit mode supported only in GCC compiler."
+#endif
+#endif
+
+/**
+ * Multiplies two digits to give a double precision result.
+ *
+ * @param[out] H - the higher half of the result.
+ * @param[out] L - the lower half of the result.
+ * @param[in] A - the first digit to multiply.
+ * @param[in] B - the second digit to multiply.
+ */
+#ifdef RLC_CONF_NODBL
+#define RLC_MUL_DIG(H, L, A, B) L = _umul128(A, B, &(H))
#else
+#define RLC_MUL_DIG(H, L, A, B) \
+ H = ((dbl_t)(A) * (dbl_t)(B)) >> RLC_DIG; \
+ L = (A) * (B); \
+
#endif
+
+/**
+ * Divides a double-digit by a digit, setting quotient and remainder.
+ *
+ * @param[out] Q - the quotient.
+ * @param[out] R - the remainder.
+ * @param[in] H - the higher half of the dividend.
+ * @param[in] L - the lower half of the dividend.
+ * @param[in] D - the divisor.
+ */
+#ifdef RLC_CONF_NODBL
+#define RLC_DIV_DIG(Q, R, H, L, D) Q = _udiv128(H, L, D, &(R))
+#else
+
+#define RLC_DIV_DIG(Q, R, H, L, D) \
+ Q = (((dbl_t)(H) << RLC_DIG) | (L)) / (D); \
+ R = (((dbl_t)(H) << RLC_DIG) | (L)) - (dbl_t)(Q) * (dbl_t)(D); \
+
#endif
/*
diff --git a/contrib/relic/include/relic_util.h b/contrib/relic/include/relic_util.h
index d3522cc13..9fc54f703 100644
--- a/contrib/relic/include/relic_util.h
+++ b/contrib/relic/include/relic_util.h
@@ -115,6 +115,13 @@
*/
#define RLC_HIGH(D) (D >> (RLC_DIG >> 1))
+/**
+ * Returns the sign bit of a digit.
+ *
+ * @param[in] D - the digit.
+ */
+#define RLC_SIGN(D) (((dig_t)D) >> (RLC_DIG - 1))
+
/**
* Selects between two values based on the value of a given flag.
*
@@ -162,6 +169,68 @@
#define __OPT(_1, _2, N, ...) N
/** @} */
+/**
+ * Generic macro to initialize an object to NULL.
+ *
+ * @param[out] A - the object to initialize.
+ */
+#if ALLOC == AUTO
+#define RLC_NULL(A) /* empty */
+#else
+#define RLC_NULL(A) A = NULL;
+#endif
+
+
+/**
+ * Accumulates a double precision digit in a triple register variable.
+ *
+ * @param[in,out] R2 - most significant word of the triple register.
+ * @param[in,out] R1 - middle word of the triple register.
+ * @param[in,out] R0 - lowest significant word of the triple register.
+ * @param[in] A - the first digit to multiply.
+ * @param[in] B - the second digit to multiply.
+ */
+#define RLC_COMBA_STEP_MUL(R2, R1, R0, A, B) \
+ dig_t _r, _r0, _r1; \
+ RLC_MUL_DIG(_r1, _r0, A, B); \
+ RLC_COMBA_ADD(_r, R2, R1, R0, _r0); \
+ (R1) += _r1; \
+ (R2) += (R1) < _r1; \
+
+/**
+ * Computes the step of a Comba squaring.
+ *
+ * @param[in,out] R2 - most significant word of the triple register.
+ * @param[in,out] R1 - middle word of the triple register.
+ * @param[in,out] R0 - lowest significant word of the triple register.
+ * @param[in] A - the first digit to multiply.
+ * @param[in] B - the second digit to multiply.
+ */
+#define RLC_COMBA_STEP_SQR(R2, R1, R0, A, B) \
+ dig_t _r, _r0, _r1; \
+ RLC_MUL_DIG(_r1, _r0, A, B); \
+ dig_t _s0 = _r0 + _r0; \
+ dig_t _s1 = _r1 + _r1 + (_s0 < _r0); \
+ RLC_COMBA_ADD(_r, R2, R1, R0, _s0); \
+ (R1) += _s1; \
+ (R2) += (R1) < _s1; \
+ (R2) += (_s1 < _r1); \
+
+/**
+ * Accumulates a single precision digit in a triple register variable.
+ *
+ * @param[in,out] T - the temporary variable.
+ * @param[in,out] R2 - most significant word of the triple register.
+ * @param[in,out] R1 - middle word of the triple register.
+ * @param[in,out] R0 - lowest significant word of the triple register.
+ * @param[in] A - the first digit to accumulate.
+ */
+#define RLC_COMBA_ADD(T, R2, R1, R0, A) \
+ (T) = (R1); \
+ (R0) += (A); \
+ (R1) += (R0) < (A); \
+ (R2) += (R1) < (T); \
+
/**
* Selects a real or dummy printing function depending on library flags.
*
diff --git a/contrib/relic/preset/ardue-ecc-128k.sh b/contrib/relic/preset/ardue-ecc-128k.sh
new file mode 100755
index 000000000..a7f4616ce
--- /dev/null
+++ b/contrib/relic/preset/ardue-ecc-128k.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+ARDUINO=${HOME}/.arduino15/packages/arduino/
+CC="${ARDUINO}/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-gcc" CXX="${ARDUINO}/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-g++ -nostdlib" LDFLAGS="-mthumb -Wl,--gc-sections" CFLAGS="-nostdlib -std=c99 -Wl,--no-export-dynamic -O2 -ggdb -DF_CPU=84000000L -mcpu=cortex-m3 -mthumb -ffunction-sections -fdata-sections" cmake -DCMAKE_SYSTEM_NAME="Generic" -DARCH=ARM -DWSIZE=32 -DOPSYS=DUINO -DSEED=LIBC -DSHLIB=OFF -DSTBIN=ON -DTIMER=HREAL -DWITH="DV;BN;FP;EP;EC;CP;MD" -DBENCH=20 -DTESTS=20 -DCHECK=off -DVERBS=off -DSTRIP=on -DQUIET=off -DARITH=easy -DBN_METHD="COMBA;COMBA;BASIC;BASIC;STEIN;BASIC" -DBN_PRECI=3072 -DBN_MAGNI=DOUBLE -DFP_PRIME=256 -DFP_METHD="INTEG;COMBA;COMBA;QUICK;EXGCD;LOWER;SLIDE" -DEP_ENDOM=on -DEP_PLAIN=off -DEP_SUPER=off -DEC_ENDOM=on -DEC_METHD="PRIME" -DMD_METHD=SH256 $1
diff --git a/contrib/relic/preset/fiat-pbc-bls381.sh b/contrib/relic/preset/fiat-pbc-bls381.sh
index 1b8b8bc1c..51143840f 100755
--- a/contrib/relic/preset/fiat-pbc-bls381.sh
+++ b/contrib/relic/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;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
+#!/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
diff --git a/contrib/relic/preset/gmp-ecc-128.sh b/contrib/relic/preset/gmp-ecc-128.sh
index 971c66e21..d2d1516f0 100755
--- a/contrib/relic/preset/gmp-ecc-128.sh
+++ b/contrib/relic/preset/gmp-ecc-128.sh
@@ -1,2 +1,2 @@
#!/bin/sh
-cmake -DCHECK=off -DARITH=gmp -DFP_PRIME=256 -DFP_QNRES=off -DEC_METHD="PRIME" -DFP_METHD="INTEG;COMBA;COMBA;MONTY;MONTY;SLIDE" -DCFLAGS="-O2 -funroll-loops -fomit-frame-pointer" $1
+cmake -DCHECK=off -DARITH=gmp -DFP_PRIME=255 -DFP_QNRES=off -DEC_METHD="EDDIE" -DFP_METHD="INTEG;COMBA;COMBA;MONTY;MONTY;LOWER;SLIDE" -DCFLAGS="-O3 -funroll-loops -fomit-frame-pointer -march=native -mtune=native" $1
diff --git a/contrib/relic/preset/gmp-pbc-bls381.sh b/contrib/relic/preset/gmp-pbc-bls381.sh
index 391b8a367..251793fa0 100755
--- a/contrib/relic/preset/gmp-pbc-bls381.sh
+++ b/contrib/relic/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;SLIDE" -DFPX_METHD="INTEG;INTEG;LAZYR" -DPP_METHD="LAZYR;OATEP" -DCFLAGS="-O2 -funroll-loops -fomit-frame-pointer" -DWITH="DV;MD;BC;BN;FP;FPX;EP;EPC;EC;PP;PC;CP" $1
+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" -DWITH="DV;MD;BC;BN;FP;FPX;EP;EPC;EC;PP;PC;CP" $1
diff --git a/contrib/relic/preset/gmp-pbc-bn254.sh b/contrib/relic/preset/gmp-pbc-bn254.sh
index c0786d94d..bcd1a144d 100755
--- a/contrib/relic/preset/gmp-pbc-bn254.sh
+++ b/contrib/relic/preset/gmp-pbc-bn254.sh
@@ -1,2 +1,2 @@
#!/bin/sh
-cmake -DARCH=X86 -DWSIZE=32 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=off -DARITH=gmp -DFP_PRIME=254 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;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 -DARCH=X86 -DWSIZE=32 -DRAND=UDEV -DSHLIB=OFF -DSTBIN=ON -DTIMER=CYCLE -DCHECK=off -DVERBS=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
diff --git a/contrib/relic/preset/gmp-pbc-ss1536.sh b/contrib/relic/preset/gmp-pbc-ss1536.sh
index db81fab76..e08dbb044 100755
--- a/contrib/relic/preset/gmp-pbc-ss1536.sh
+++ b/contrib/relic/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;SLIDE" -DFPX_METHD="INTEG;INTEG;LAZYR" -DPP_METHD="LAZYR;OATEP" -DCFLAGS="-O2 -funroll-loops -fomit-frame-pointer" $1
+#!/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
diff --git a/contrib/relic/preset/msp-ecc-128.sh b/contrib/relic/preset/msp-ecc-128.sh
index c5acfc9e1..1eea7028a 100755
--- a/contrib/relic/preset/msp-ecc-128.sh
+++ b/contrib/relic/preset/msp-ecc-128.sh
@@ -1,2 +1,2 @@
#!/bin/sh
-CC="msp430-gcc -mmcu=msp430f1611" CXX="c++" cmake -DARITH=msp-asm -DCMAKE_SYSTEM_NAME=Generic -DALIGN=2 -DARCH=MSP -DBENCH=1 "-DBN_METHD=BASIC;MULTP;MONTY;BASIC;BASIC;BASIC" -DCHECK=OFF -DCOLOR=OFF "-DCFLAGS:STRING=-O2 -g -mmcu=msp430f1611 -ffunction-sections -fdata-sections -fno-inline -mdisable-watchdog" -DDOCUM=OFF -DEP_DEPTH=3 -DEP_PLAIN=ON -DEP_ENDOM=OFF "-DFP_METHD=BASIC;COMBA;COMBA;QUICK;LOWER;BASIC" -DFP_PMERS=ON "-DLDFLAGS=-Wl,-mmcu=msp430f1611 -Wl,--gc-sections" -DSEED= -DSHLIB=OFF -DSTRIP=ON -DTESTS=1 -DTIMER=CYCLE -DVERBS=OFF -DWSIZE=16 -DFP_PRIME=256 -DBN_PRECI=256 -DMD_METHD=SH256 "-DWITH=FP;EP;EC;DV;CP;MD;BN" -DEC_ENDOM=OFF -DEC_METHD=PRIME -DRAND=HASHD $1
+CC="msp430-gcc -mmcu=msp430f1611" CXX="c++" cmake -DARITH=msp-asm -DCMAKE_SYSTEM_NAME=Generic -DALIGN=2 -DARCH=MSP -DBENCH=1 "-DBN_METHD=BASIC;MULTP;MONTY;BASIC;BASIC;BASIC" -DCHECK=OFF -DCOLOR=OFF "-DCFLAGS:STRING=-O2 -g -mmcu=msp430f1611 -ffunction-sections -fdata-sections -fno-inline -mdisable-watchdog" -DDOCUM=OFF -DEP_DEPTH=3 -DEP_PLAIN=ON -DEP_ENDOM=OFF "-DFP_METHD=BASIC;COMBA;COMBA;QUICK;LOWER;BASIC;BASIC" -DFP_PMERS=ON "-DLDFLAGS=-Wl,-mmcu=msp430f1611 -Wl,--gc-sections" -DSEED= -DSHLIB=OFF -DSTRIP=ON -DTESTS=1 -DTIMER=CYCLE -DVERBS=OFF -DWSIZE=16 -DFP_PRIME=256 -DBN_PRECI=256 -DMD_METHD=SH256 "-DWITH=FP;EP;EC;DV;CP;MD;BN" -DEC_ENDOM=OFF -DEC_METHD=PRIME -DRAND=HASHD $1
diff --git a/contrib/relic/preset/msp-ecc-128k.sh b/contrib/relic/preset/msp-ecc-128k.sh
index 832a59c56..3a5d6a8b8 100755
--- a/contrib/relic/preset/msp-ecc-128k.sh
+++ b/contrib/relic/preset/msp-ecc-128k.sh
@@ -1,2 +1,2 @@
#!/bin/sh
-CC="msp430-gcc -mmcu=msp430f1611" CXX="c++" cmake -DARITH=msp-asm -DCMAKE_SYSTEM_NAME=Generic -DALIGN=2 -DARCH=MSP -DBENCH=1 "-DBN_METHD=BASIC;MULTP;MONTY;BASIC;BASIC;BASIC" -DCHECK=OFF -DCOLOR=OFF "-DCFLAGS:STRING=-O2 -g -mmcu=msp430f1611 -ffunction-sections -fdata-sections -fno-inline -mdisable-watchdog" -DDOCUM=OFF -DEB_DEPTH=3 -DEB_PLAIN=OFF -DEP_DEPTH=3 -DEP_PLAIN=OFF "-DFB_METHD=LODAH;RLC_TABLE;QUICK;QUICK;BASIC;BASIC;EXGCD;BASIC;BASIC" -DFB_PRECO=OFF "-DFP_METHD=BASIC;COMBA;COMBA;QUICK;LOWER;BASIC" -DFP_PMERS=ON "-DLDFLAGS=-Wl,--gc-sections" -DSEED= -DSHLIB=OFF -DSTRIP=ON -DTESTS=1 -DTIMER=CYCLE -DVERBS=OFF -DWSIZE=16 -DFP_PRIME=256 -DFB_POLYN=283 -DBN_PRECI=284 -DMD_METHD=SH256 "-DWITH=FP;FB;EP;EB;EC;DV;CP;MD;BN" -DEC_METHD=PRIME -DRAND=HASHD $1
+CC="msp430-gcc -mmcu=msp430f1611" CXX="c++" cmake -DARITH=msp-asm -DCMAKE_SYSTEM_NAME=Generic -DALIGN=2 -DARCH=MSP -DBENCH=1 "-DBN_METHD=BASIC;MULTP;MONTY;BASIC;BASIC;BASIC" -DCHECK=OFF -DCOLOR=OFF "-DCFLAGS:STRING=-O2 -g -mmcu=msp430f1611 -ffunction-sections -fdata-sections -fno-inline -mdisable-watchdog" -DDOCUM=OFF -DEB_DEPTH=3 -DEB_PLAIN=OFF -DEP_DEPTH=3 -DEP_PLAIN=OFF "-DFB_METHD=LODAH;RLC_TABLE;QUICK;QUICK;BASIC;BASIC;EXGCD;BASIC;BASIC" -DFB_PRECO=OFF "-DFP_METHD=BASIC;COMBA;COMBA;QUICK;LOWER;BASIC;BASIC" -DFP_PMERS=ON "-DLDFLAGS=-Wl,--gc-sections" -DSEED= -DSHLIB=OFF -DSTRIP=ON -DTESTS=1 -DTIMER=CYCLE -DVERBS=OFF -DWSIZE=16 -DFP_PRIME=256 -DFB_POLYN=283 -DBN_PRECI=284 -DMD_METHD=SH256 "-DWITH=FP;FB;EP;EB;EC;DV;CP;MD;BN" -DEC_METHD=PRIME -DRAND=HASHD $1
diff --git a/contrib/relic/preset/msp-ecc-80.sh b/contrib/relic/preset/msp-ecc-80.sh
index caccf1ad5..6072c2534 100755
--- a/contrib/relic/preset/msp-ecc-80.sh
+++ b/contrib/relic/preset/msp-ecc-80.sh
@@ -1,2 +1,2 @@
#!/bin/sh
-CC="msp430-gcc -mmcu=msp430f1611" CXX="c++" cmake -DARITH=msp-asm -DCMAKE_SYSTEM_NAME=Generic -DALIGN=2 -DARCH=MSP -DBENCH=1 "-DBN_METHD=BASIC;MULTP;MONTY;BASIC;BASIC;BASIC" -DCHECK=OFF -DCOLOR=OFF "-DCFLAGS:STRING=-O2 -g -mmcu=msp430f1611 -ffunction-sections -fdata-sections -fno-inline -mdisable-watchdog" -DDOCUM=OFF -DEP_DEPTH=3 -DEP_PLAIN=ON -DEP_ENDOM=OFF "-DFP_METHD=BASIC;COMBA;COMBA;QUICK;LOWER;BASIC" -DFP_PMERS=ON "-DLDFLAGS=-Wl,--gc-sections" -DSEED= -DSHLIB=OFF -DSTRIP=ON -DTESTS=1 -DTIMER=CYCLE -DVERBS=OFF -DWSIZE=16 -DFP_PRIME=160 -DBN_PRECI=160 -DMD_METHD=SH256 "-DWITH=FP;EP;EC;DV;CP;MD;BN" -DEC_ENDOM=OFF -DEC_METHD=PRIME -DRAND=HASHD $1
+CC="msp430-gcc -mmcu=msp430f1611" CXX="c++" cmake -DARITH=msp-asm -DCMAKE_SYSTEM_NAME=Generic -DALIGN=2 -DARCH=MSP -DBENCH=1 "-DBN_METHD=BASIC;MULTP;MONTY;BASIC;BASIC;BASIC" -DCHECK=OFF -DCOLOR=OFF "-DCFLAGS:STRING=-O2 -g -mmcu=msp430f1611 -ffunction-sections -fdata-sections -fno-inline -mdisable-watchdog" -DDOCUM=OFF -DEP_DEPTH=3 -DEP_PLAIN=ON -DEP_ENDOM=OFF "-DFP_METHD=BASIC;COMBA;COMBA;QUICK;LOWER;BASIC;BASIC" -DFP_PMERS=ON "-DLDFLAGS=-Wl,--gc-sections" -DSEED= -DSHLIB=OFF -DSTRIP=ON -DTESTS=1 -DTIMER=CYCLE -DVERBS=OFF -DWSIZE=16 -DFP_PRIME=160 -DBN_PRECI=160 -DMD_METHD=SH256 "-DWITH=FP;EP;EC;DV;CP;MD;BN" -DEC_ENDOM=OFF -DEC_METHD=PRIME -DRAND=HASHD $1
diff --git a/contrib/relic/preset/msp-ecc-80k.sh b/contrib/relic/preset/msp-ecc-80k.sh
index fdaf8ab58..42126a7d4 100755
--- a/contrib/relic/preset/msp-ecc-80k.sh
+++ b/contrib/relic/preset/msp-ecc-80k.sh
@@ -1,2 +1,2 @@
#!/bin/sh
-CC="msp430-gcc -mmcu=msp430f1611" CXX="c++" cmake -DARITH=msp-asm -DCMAKE_SYSTEM_NAME=Generic -DALIGN=2 -DARCH=MSP -DBENCH=1 "-DBN_METHD=BASIC;MULTP;MONTY;BASIC;BASIC;BASIC" -DCHECK=OFF -DCOLOR=OFF "-DCFLAGS:STRING=-O2 -g -mmcu=msp430f1611 -ffunction-sections -fdata-sections -fno-inline -mdisable-watchdog" -DDOCUM=OFF -DEB_DEPTH=3 -DEB_PLAIN=OFF -DEP_DEPTH=3 -DEP_PLAIN=OFF "-DFB_METHD=LODAH;RLC_TABLE;QUICK;QUICK;BASIC;BASIC;EXGCD;BASIC;BASIC" -DFB_PRECO=OFF "-DFP_METHD=BASIC;COMBA;COMBA;QUICK;LOWER;BASIC" -DFP_PMERS=ON "-DLDFLAGS=-Wl,--gc-sections" -DSEED= -DSHLIB=OFF -DSTRIP=ON -DTESTS=1 -DTIMER=CYCLE -DVERBS=OFF -DWSIZE=16 -DFP_PRIME=160 -DFB_POLYN=163 -DBN_PRECI=164 -DMD_METHD=SH256 "-DWITH=FP;FB;EP;EB;EC;DV;CP;MD;BN" -DEC_METHD=PRIME -DRAND=HASHD $1
+CC="msp430-gcc -mmcu=msp430f1611" CXX="c++" cmake -DARITH=msp-asm -DCMAKE_SYSTEM_NAME=Generic -DALIGN=2 -DARCH=MSP -DBENCH=1 "-DBN_METHD=BASIC;MULTP;MONTY;BASIC;BASIC;BASIC" -DCHECK=OFF -DCOLOR=OFF "-DCFLAGS:STRING=-O2 -g -mmcu=msp430f1611 -ffunction-sections -fdata-sections -fno-inline -mdisable-watchdog" -DDOCUM=OFF -DEB_DEPTH=3 -DEB_PLAIN=OFF -DEP_DEPTH=3 -DEP_PLAIN=OFF "-DFB_METHD=LODAH;RLC_TABLE;QUICK;QUICK;BASIC;BASIC;EXGCD;BASIC;BASIC" -DFB_PRECO=OFF "-DFP_METHD=BASIC;COMBA;COMBA;QUICK;LOWER;BASIC;BASIC" -DFP_PMERS=ON "-DLDFLAGS=-Wl,--gc-sections" -DSEED= -DSHLIB=OFF -DSTRIP=ON -DTESTS=1 -DTIMER=CYCLE -DVERBS=OFF -DWSIZE=16 -DFP_PRIME=160 -DFB_POLYN=163 -DBN_PRECI=164 -DMD_METHD=SH256 "-DWITH=FP;FB;EP;EB;EC;DV;CP;MD;BN" -DEC_METHD=PRIME -DRAND=HASHD $1
diff --git a/contrib/relic/preset/x64-ecc-128.sh b/contrib/relic/preset/x64-ecc-128.sh
new file mode 100755
index 000000000..f96c70370
--- /dev/null
+++ b/contrib/relic/preset/x64-ecc-128.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+cmake -DCHECK=off -DARITH=x64-asm-4l -DFP_PRIME=255 -DFP_QNRES=off -DEC_METHD="EDDIE" -DFP_METHD="INTEG;INTEG;INTEG;MONTY;LOWER;LOWER;SLIDE" -DCFLAGS="-O3 -funroll-loops -fomit-frame-pointer -march=native -mtune=native" $1
diff --git a/contrib/relic/preset/x64-pbc-bls12-381.sh b/contrib/relic/preset/x64-pbc-bls12-381.sh
index 93183420d..757e67612 100755
--- a/contrib/relic/preset/x64-pbc-bls12-381.sh
+++ b/contrib/relic/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-382 -DFP_PRIME=381 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;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" -DWITH="DV;MD;BC;BN;FP;FPX;EP;EPX;EC;PP;PC;CP" $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;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" -DWITH="DV;MD;BC;BN;FP;FPX;EP;EPX;EC;PP;PC;CP" $1
diff --git a/contrib/relic/preset/x64-pbc-bls12-446.sh b/contrib/relic/preset/x64-pbc-bls12-446.sh
index e820b9b67..99fbf3d7b 100755
--- a/contrib/relic/preset/x64-pbc-bls12-446.sh
+++ b/contrib/relic/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-446 -DFP_PRIME=446 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;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-446 -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
diff --git a/contrib/relic/preset/x64-pbc-bls12-455.sh b/contrib/relic/preset/x64-pbc-bls12-455.sh
index 1f3474bd7..63db8de49 100755
--- a/contrib/relic/preset/x64-pbc-bls12-455.sh
+++ b/contrib/relic/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-455 -DFP_PRIME=455 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;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-455 -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
diff --git a/contrib/relic/preset/x64-pbc-bls12-638.sh b/contrib/relic/preset/x64-pbc-bls12-638.sh
index 20c278809..501149b0d 100755
--- a/contrib/relic/preset/x64-pbc-bls12-638.sh
+++ b/contrib/relic/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-638 -DFP_PRIME=638 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;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-638 -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
diff --git a/contrib/relic/preset/x64-pbc-bls24-509.sh b/contrib/relic/preset/x64-pbc-bls24-509.sh
new file mode 100755
index 000000000..51eafeae6
--- /dev/null
+++ b/contrib/relic/preset/x64-pbc-bls24-509.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-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
diff --git a/contrib/relic/preset/x64-pbc-bls48-575.sh b/contrib/relic/preset/x64-pbc-bls48-575.sh
index b6ae8cc8b..83c171bcd 100755
--- a/contrib/relic/preset/x64-pbc-bls48-575.sh
+++ b/contrib/relic/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-nine -DFP_PRIME=575 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;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 -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
diff --git a/contrib/relic/preset/x64-pbc-bn254.sh b/contrib/relic/preset/x64-pbc-bn254.sh
index cf5737eb4..b3a0924cd 100755
--- a/contrib/relic/preset/x64-pbc-bn254.sh
+++ b/contrib/relic/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-254 -DFP_PRIME=254 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;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;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
diff --git a/contrib/relic/preset/x64-pbc-bn382.sh b/contrib/relic/preset/x64-pbc-bn382.sh
index 6c76642c3..bb3094695 100755
--- a/contrib/relic/preset/x64-pbc-bn382.sh
+++ b/contrib/relic/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-382 -DFP_PRIME=382 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;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;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
diff --git a/contrib/relic/preset/x64-pbc-bn446.sh b/contrib/relic/preset/x64-pbc-bn446.sh
index 0d6cce619..4ec7373ba 100755
--- a/contrib/relic/preset/x64-pbc-bn446.sh
+++ b/contrib/relic/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-446 -DFP_PRIME=446 -DFP_METHD="INTEG;INTEG;INTEG;MONTY;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-446 -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
diff --git a/contrib/relic/src/CMakeLists.txt b/contrib/relic/src/CMakeLists.txt
index b98748641..c9f726cb6 100644
--- a/contrib/relic/src/CMakeLists.txt
+++ b/contrib/relic/src/CMakeLists.txt
@@ -115,29 +115,38 @@ if (WITH_CP)
list(APPEND RELIC_SRCS "cp/relic_cp_bdpe.c")
list(APPEND RELIC_SRCS "cp/relic_cp_ghpe.c")
list(APPEND RELIC_SRCS "cp/relic_cp_phpe.c")
- endif(WITH_BN)
- if (WITH_EB OR WITH_EP OR WITH_ED)
+ endif()
+ if (WITH_EB OR WITH_EP OR WITH_ED OR WITH_EC)
list(APPEND RELIC_SRCS "cp/relic_cp_ecdh.c")
list(APPEND RELIC_SRCS "cp/relic_cp_ecmqv.c")
list(APPEND RELIC_SRCS "cp/relic_cp_ecies.c")
list(APPEND RELIC_SRCS "cp/relic_cp_ecdsa.c")
list(APPEND RELIC_SRCS "cp/relic_cp_ecss.c")
list(APPEND RELIC_SRCS "cp/relic_cp_vbnn.c")
- endif(WITH_EB OR WITH_EP OR WITH_ED)
- if (WITH_PP)
+ list(APPEND RELIC_SRCS "cp/relic_cp_pok.c")
+ list(APPEND RELIC_SRCS "cp/relic_cp_sok.c")
+ list(APPEND RELIC_SRCS "cp/relic_cp_ers.c")
+ list(APPEND RELIC_SRCS "cp/relic_cp_smlers.c")
+ list(APPEND RELIC_SRCS "cp/relic_cp_etrs.c")
+ endif()
+ if (WITH_PP OR WITH_PC)
+ list(APPEND RELIC_SRCS "cp/relic_cp_pcdel.c")
list(APPEND RELIC_SRCS "cp/relic_cp_sokaka.c")
list(APPEND RELIC_SRCS "cp/relic_cp_bgn.c")
list(APPEND RELIC_SRCS "cp/relic_cp_ibe.c")
list(APPEND RELIC_SRCS "cp/relic_cp_bls.c")
list(APPEND RELIC_SRCS "cp/relic_cp_cls.c")
list(APPEND RELIC_SRCS "cp/relic_cp_pss.c")
- list(APPEND RELIC_SRCS "cp/relic_cp_mpss.c")
list(APPEND RELIC_SRCS "cp/relic_cp_bbs.c")
list(APPEND RELIC_SRCS "cp/relic_cp_zss.c")
list(APPEND RELIC_SRCS "cp/relic_cp_cmlhs.c")
list(APPEND RELIC_SRCS "cp/relic_cp_mklhs.c")
- endif(WITH_PP)
-endif(WITH_CP)
+ list(APPEND RELIC_SRCS "cp/relic_cp_lapsi.c")
+ endif()
+ if (WITH_MPC)
+ list(APPEND RELIC_SRCS "cp/relic_cp_mpss.c")
+ endif()
+endif()
if (WITH_BC)
list(APPEND RELIC_SRCS ${BC_SRCS})
diff --git a/contrib/relic/src/bn/relic_bn_inv.c b/contrib/relic/src/bn/relic_bn_inv.c
index 947f7c3e2..1cae05b60 100644
--- a/contrib/relic/src/bn/relic_bn_inv.c
+++ b/contrib/relic/src/bn/relic_bn_inv.c
@@ -63,3 +63,50 @@ void bn_mod_inv(bn_t c, const bn_t a, const bn_t b) {
bn_free(u);
}
}
+
+void bn_mod_inv_sim(bn_t *c, const bn_t *a, const bn_t b, int n) {
+ int i;
+ bn_t u, *t = RLC_ALLOCA(bn_t, n);
+
+ bn_null(u);
+
+ RLC_TRY {
+ if (t == NULL) {
+ RLC_THROW(ERR_NO_MEMORY);
+ }
+ for (i = 0; i < n; i++) {
+ bn_null(t[i]);
+ bn_new(t[i]);
+ }
+ bn_new(u);
+
+ bn_copy(c[0], a[0]);
+ bn_copy(t[0], a[0]);
+
+ for (i = 1; i < n; i++) {
+ bn_copy(t[i], a[i]);
+ bn_mul(c[i], c[i - 1], a[i]);
+ bn_mod(c[i], c[i], b);
+ }
+
+ bn_mod_inv(u, c[n - 1], b);
+
+ for (i = n - 1; i > 0; i--) {
+ bn_mul(c[i], u, c[i - 1]);
+ bn_mod(c[i], c[i], b);
+ bn_mul(u, u, t[i]);
+ bn_mod(u, u, b);
+ }
+ bn_copy(c[0], u);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ for (i = 0; i < n; i++) {
+ bn_free(t[i]);
+ }
+ bn_free(u);
+ RLC_FREE(t);
+ }
+}
diff --git a/contrib/relic/src/bn/relic_bn_mem.c b/contrib/relic/src/bn/relic_bn_mem.c
index a74eab930..f378432ad 100644
--- a/contrib/relic/src/bn/relic_bn_mem.c
+++ b/contrib/relic/src/bn/relic_bn_mem.c
@@ -41,7 +41,7 @@
/* Public definitions */
/*============================================================================*/
-void bn_init(bn_t a, int digits) {
+void bn_make(bn_t a, int digits) {
if (digits < 0) {
RLC_THROW(ERR_NO_VALID);
}
@@ -85,7 +85,8 @@ void bn_init(bn_t a, int digits) {
}
#endif
if (a != NULL) {
- a->used = 0;
+ a->used = 1;
+ a->dp[0] = 0;
a->alloc = digits;
a->sign = RLC_POS;
}
diff --git a/contrib/relic/src/bn/relic_bn_mod.c b/contrib/relic/src/bn/relic_bn_mod.c
index 387691ecd..e0d0e6cd1 100644
--- a/contrib/relic/src/bn/relic_bn_mod.c
+++ b/contrib/relic/src/bn/relic_bn_mod.c
@@ -169,7 +169,7 @@ void bn_mod_pre_monty(bn_t u, const bn_t m) {
#if WSIZE > 16
x *= (dig_t)2 - b * x; /* here x*a==1 mod 2**32 */
#endif
-#if WSIZE == 64
+#if WSIZE > 32
x *= (dig_t)2 - b * x; /* here x*a==1 mod 2**64 */
#endif
/* u = -1/m0 (mod 2^RLC_DIG) */
diff --git a/contrib/relic/src/bn/relic_bn_mxp.c b/contrib/relic/src/bn/relic_bn_mxp.c
index d0c4ac843..5e892b934 100644
--- a/contrib/relic/src/bn/relic_bn_mxp.c
+++ b/contrib/relic/src/bn/relic_bn_mxp.c
@@ -299,20 +299,11 @@ void bn_mxp_monty(bn_t c, const bn_t a, const bn_t b, const bn_t m) {
bn_copy(u, tab[0]);
#endif
- /* Silly branchless code, since called functions not constant-time. */
- bn_mod_inv(tab[0], u, m);
- dv_swap_cond(u->dp, tab[0]->dp, RLC_BN_DIGS, bn_sign(b) == RLC_NEG);
if (bn_sign(b) == RLC_NEG) {
- u->sign = tab[0]->sign;
- if (bn_cmp_dig(tab[1], 1) != RLC_EQ) {
- bn_zero(c);
- RLC_THROW(ERR_NO_VALID);
- }
+ bn_mod_inv(c, u, m);
+ } else {
+ bn_copy(c, u);
}
- bn_add(tab[1], u, m);
- dv_swap_cond(u->dp, tab[1]->dp, RLC_BN_DIGS, bn_sign(b) == RLC_NEG && bn_sign(u) == RLC_NEG);
- u->sign = RLC_POS;
- bn_copy(c, u);
}
RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
diff --git a/contrib/relic/src/bn/relic_bn_prime.c b/contrib/relic/src/bn/relic_bn_prime.c
index c89afa10c..eab7ff9e0 100644
--- a/contrib/relic/src/bn/relic_bn_prime.c
+++ b/contrib/relic/src/bn/relic_bn_prime.c
@@ -378,11 +378,13 @@ int bn_is_prime_solov(const bn_t a) {
break;
}
- /* t2 = (t0|a). */
- bn_smb_jac(t2, t0, a);
- if (bn_sign(t2) == RLC_NEG) {
- bn_add(t2, t2, a);
+ /* Lend result here, but restore afterwards, for t2 = (t0|a). */
+ result = bn_smb_jac(t0, a);
+ bn_set_dig(t2, (result < 0 ? -result : result));
+ if (result < 0) {
+ bn_neg(t2, t2);
}
+ result = 1;
/* If t1 != t2 (mod a) return 0. */
bn_mod(t1, t1, a);
bn_mod(t2, t2, a);
diff --git a/contrib/relic/src/bn/relic_bn_rec.c b/contrib/relic/src/bn/relic_bn_rec.c
index 1c9bcd2bd..a67db496f 100644
--- a/contrib/relic/src/bn/relic_bn_rec.c
+++ b/contrib/relic/src/bn/relic_bn_rec.c
@@ -102,6 +102,8 @@ void bn_rec_win(uint8_t *win, int *len, const bn_t k, int w) {
return;
}
+ memset(win, 0, *len);
+
j = 0;
for (i = 0; i < l - w; i += w) {
win[j++] = get_bits(k, i, i + w - 1);
@@ -121,6 +123,8 @@ void bn_rec_slw(uint8_t *win, int *len, const bn_t k, int w) {
return;
}
+ memset(win, 0, *len);
+
i = l - 1;
j = 0;
while (i >= 0) {
@@ -160,6 +164,8 @@ void bn_rec_naf(int8_t *naf, int *len, const bn_t k, int w) {
mask = RLC_MASK(w);
l = (1 << w);
+ memset(naf, 0, *len);
+
i = 0;
if (w == 2) {
while (!bn_is_zero(t)) {
@@ -438,6 +444,8 @@ void bn_rec_tnaf(int8_t *tnaf, int *len, const bn_t k, int8_t u, int m, int w) {
bn_new(r1);
bn_new(tmp);
+ memset(tnaf, 0, *len);
+
bn_rec_tnaf_get(&t_w, beta, gama, u, w);
bn_abs(tmp, k);
bn_rec_tnaf_mod(r0, r1, tmp, u, m);
@@ -565,6 +573,8 @@ void bn_rec_rtnaf(int8_t *tnaf, int *len, const bn_t k, int8_t u, int m, int w)
bn_new(r1);
bn_new(tmp);
+ memset(tnaf, 0, *len);
+
bn_rec_tnaf_get(&t_w, beta, gama, u, w);
bn_abs(tmp, k);
bn_rec_tnaf_mod(r0, r1, tmp, u, m);
@@ -704,6 +714,8 @@ void bn_rec_reg(int8_t *naf, int *len, const bn_t k, int n, int w) {
bn_new(t);
bn_abs(t, k);
+ memset(naf, 0, *len);
+
i = 0;
if (w == 2) {
for (i = 0; i < l; i++) {
@@ -740,15 +752,15 @@ void bn_rec_jsf(int8_t *jsf, int *len, const bn_t k, const bn_t l) {
int8_t u0, u1, d0, d1;
int i, j, offset;
- bn_null(n0);
- bn_null(n1);
-
if (*len < (2 * bn_bits(k) + 1)) {
*len = 0;
RLC_THROW(ERR_NO_BUFFER);
return;
}
+ bn_null(n0);
+ bn_null(n1);
+
RLC_TRY {
bn_new(n0);
bn_new(n1);
@@ -760,6 +772,8 @@ void bn_rec_jsf(int8_t *jsf, int *len, const bn_t k, const bn_t l) {
j = bn_bits(l);
offset = RLC_MAX(i, j) + 1;
+ memset(jsf, 0, *len);
+
i = 0;
d0 = d1 = 0;
while (!(bn_is_zero(n0) && d0 == 0) || !(bn_is_zero(n1) && d1 == 0)) {
@@ -857,3 +871,154 @@ void bn_rec_glv(bn_t k0, bn_t k1, const bn_t k, const bn_t n, const bn_t *v1,
bn_free(t);
}
}
+
+void bn_rec_frb(bn_t *ki, int sub, const bn_t k, const bn_t x, const bn_t n,
+ int bls) {
+ int i, l, sk, sx;
+ bn_t u[4], v[4];
+
+ RLC_TRY {
+ for (i = 0; i < 4; i++) {
+ bn_null(u[i]);
+ bn_null(v[i]);
+ bn_new(u[i]);
+ bn_new(v[i]);
+ }
+
+ if (bls) {
+ bn_abs(v[0], k);
+ bn_abs(u[0], x);
+
+ sk = bn_sign(k);
+ sx = bn_sign(x);
+
+ for (i = 0; i < sub; i++) {
+ bn_mod(ki[i], v[0], u[0]);
+ bn_div(v[0], v[0], u[0]);
+ if ((sx == RLC_NEG) && (i % 2 != 0)) {
+ bn_neg(ki[i], ki[i]);
+ }
+ if (sk == RLC_NEG) {
+ bn_neg(ki[i], ki[i]);
+ }
+ }
+ } else {
+ bn_copy(v[1], x);
+ bn_copy(v[2], x);
+ bn_copy(v[3], x);
+
+ /* t = 2x^2. */
+ bn_sqr(u[3], x);
+ bn_dbl(u[3], u[3]);
+
+ /* 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], u[3]);
+
+ /* v3 = -(2x^2 + x). */
+ bn_add(v[3], v[3], u[3]);
+ bn_neg(v[3], v[3]);
+
+ /* v1 = 12x^3 + 8x^2 + x, v2 = 6x^3 + 4x^2 + x. */
+ bn_dbl(u[3], u[3]);
+ bn_add(v[2], v[2], u[3]);
+ bn_dbl(u[3], u[3]);
+ bn_add(v[1], v[1], u[3]);
+ bn_rsh(u[3], u[3], 2);
+ bn_mul(u[3], u[3], x);
+ bn_mul_dig(u[3], u[3], 3);
+ bn_add(v[2], v[2], u[3]);
+ bn_dbl(u[3], u[3]);
+ bn_add(v[1], v[1], u[3]);
+
+ for (i = 0; i < 4; i++) {
+ bn_mul(v[i], v[i], k);
+ bn_div(v[i], v[i], n);
+ if (bn_sign(v[i]) == RLC_NEG) {
+ bn_add_dig(v[i], v[i], 1);
+ }
+ }
+
+ /* u0 = x + 1, u1 = 2x + 1, u2 = 2x, u3 = x - 1. */
+ bn_dbl(u[2], x);
+ bn_add_dig(u[1], u[2], 1);
+ bn_sub_dig(u[3], x, 1);
+ bn_add_dig(u[0], x, 1);
+ bn_copy(ki[0], k);
+ bn_zero(ki[1]);
+ bn_zero(ki[2]);
+ bn_zero(ki[3]);
+ for (i = 0; i < 4; i++) {
+ bn_mul(u[i], u[i], v[i]);
+ bn_mod(u[i], u[i], n);
+ bn_add(ki[0], ki[0], n);
+ bn_sub(ki[0], ki[0], u[i]);
+ bn_mod(ki[0], ki[0], n);
+ }
+
+ /* u0 = x, u1 = -x, u2 = 2x + 1, u3 = 4x + 2. */
+ bn_copy(u[0], x);
+ bn_neg(u[1], x);
+ bn_dbl(u[2], x);
+ bn_add_dig(u[2], u[2], 1);
+ bn_dbl(u[3], u[2]);
+ for (i = 0; i < 4; i++) {
+ bn_mul(u[i], u[i], v[i]);
+ bn_mod(u[i], u[i], n);
+ bn_add(ki[1], ki[1], n);
+ bn_sub(ki[1], ki[1], u[i]);
+ bn_mod(ki[1], ki[1], n);
+ }
+
+ /* u0 = x, u1 = -(x + 1), u2 = 2x + 1, u3 = -(2x - 1). */
+ bn_copy(u[0], x);
+ bn_add_dig(u[1], x, 1);
+ bn_neg(u[1], u[1]);
+ bn_dbl(u[2], x);
+ bn_add_dig(u[2], u[2], 1);
+ bn_sub_dig(u[3], u[2], 2);
+ bn_neg(u[3], u[3]);
+ for (i = 0; i < 4; i++) {
+ bn_mul(u[i], u[i], v[i]);
+ bn_mod(u[i], u[i], n);
+ bn_add(ki[2], ki[2], n);
+ bn_sub(ki[2], ki[2], u[i]);
+ bn_mod(ki[2], ki[2], n);
+ }
+
+ /* u0 = -2x, u1 = -x, u2 = 2x + 1, u3 = x - 1. */
+ bn_dbl(u[0], x);
+ bn_neg(u[0], u[0]);
+ bn_dbl(u[2], x);
+ bn_add_dig(u[2], u[2], 1);
+ bn_sub_dig(u[3], x, 1);
+ bn_neg(u[1], x);
+ for (i = 0; i < 4; i++) {
+ bn_mul(u[i], u[i], v[i]);
+ bn_mod(u[i], u[i], n);
+ bn_add(ki[3], ki[3], n);
+ bn_sub(ki[3], ki[3], u[i]);
+ bn_mod(ki[3], ki[3], n);
+ }
+
+ for (i = 0; i < 4; i++) {
+ l = bn_bits(ki[i]);
+ bn_sub(ki[i], n, ki[i]);
+ if (bn_bits(ki[i]) > l) {
+ bn_sub(ki[i], ki[i], n);
+ ki[i]->sign = RLC_POS;
+ } else {
+ ki[i]->sign = RLC_NEG;
+ }
+ }
+ }
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ } RLC_FINALLY {
+ for (i = 0; i < 4; i++) {
+ bn_free(u[i]);
+ bn_free(v[i]);
+ }
+ }
+}
diff --git a/contrib/relic/src/bn/relic_bn_smb.c b/contrib/relic/src/bn/relic_bn_smb.c
index 1fc977694..6c297608a 100644
--- a/contrib/relic/src/bn/relic_bn_smb.c
+++ b/contrib/relic/src/bn/relic_bn_smb.c
@@ -35,19 +35,19 @@
/* Public definitions */
/*============================================================================*/
-void bn_smb_leg(bn_t c, const bn_t a, const bn_t b) {
+int bn_smb_leg(const bn_t a, const bn_t b) {
bn_t t;
+ int res;
bn_null(t);
if (bn_sign(b) == RLC_NEG) {
RLC_THROW(ERR_NO_VALID);
- return;
+ return 0;
}
if (bn_cmp(a, b) == RLC_EQ) {
- bn_zero(c);
- return;
+ return 0;
}
RLC_TRY {
@@ -56,11 +56,14 @@ void bn_smb_leg(bn_t c, const bn_t a, const bn_t b) {
/* t = (b - 1)/2. */
bn_sub_dig(t, b, 1);
bn_rsh(t, t, 1);
- bn_mxp(c, a, t, b);
- bn_sub_dig(t, b, 1);
- if (bn_cmp(c, t) == RLC_EQ) {
- bn_set_dig(c, 1);
- bn_neg(c, c);
+ bn_mxp(t, a, t, b);
+ res = 0;
+ if (bn_cmp_dig(t, 1) == RLC_EQ) {
+ res = 1;
+ }
+ bn_sub(t, b, t);
+ if (bn_cmp_dig(t, 1) == RLC_EQ) {
+ res = -1;
}
}
RLC_CATCH_ANY {
@@ -69,11 +72,13 @@ void bn_smb_leg(bn_t c, const bn_t a, const bn_t b) {
RLC_FINALLY {
bn_free(t);
}
+
+ return res;
}
-void bn_smb_jac(bn_t c, const bn_t a, const bn_t b) {
+int bn_smb_jac(const bn_t a, const bn_t b) {
bn_t t0, t1, r;
- int t, h;
+ int t, h, res;
bn_null(t0);
bn_null(t1);
@@ -82,7 +87,7 @@ void bn_smb_jac(bn_t c, const bn_t a, const bn_t b) {
/* Argument b must be odd. */
if (bn_is_even(b) || bn_sign(b) == RLC_NEG) {
RLC_THROW(ERR_NO_VALID);
- return;
+ return 0;
}
RLC_TRY {
@@ -104,13 +109,13 @@ void bn_smb_jac(bn_t c, const bn_t a, const bn_t b) {
/* If a = 0 then if n = 1 return t else return 0. */
if (bn_is_zero(t0)) {
if (bn_cmp_dig(t1, 1) == RLC_EQ) {
- bn_set_dig(c, 1);
+ res = 1;
if (t == -1) {
- bn_neg(c, c);
+ res = -1;
}
break;
} else {
- bn_zero(c);
+ res = 0;
break;
}
}
@@ -147,4 +152,6 @@ void bn_smb_jac(bn_t c, const bn_t a, const bn_t b) {
bn_free(t1);
bn_free(r);
}
+
+ return res;
}
diff --git a/contrib/relic/src/bn/relic_bn_util.c b/contrib/relic/src/bn/relic_bn_util.c
index d438b94ac..21ce00ede 100644
--- a/contrib/relic/src/bn/relic_bn_util.c
+++ b/contrib/relic/src/bn/relic_bn_util.c
@@ -56,6 +56,7 @@ void bn_copy(bn_t c, const bn_t a) {
c->used = a->used;
c->sign = a->sign;
+ bn_trim(c);
}
void bn_abs(bn_t c, const bn_t a) {
diff --git a/contrib/relic/src/cp/relic_cp_bbs.c b/contrib/relic/src/cp/relic_cp_bbs.c
index 15cec8ffc..1236f7875 100644
--- a/contrib/relic/src/cp/relic_cp_bbs.c
+++ b/contrib/relic/src/cp/relic_cp_bbs.c
@@ -30,8 +30,6 @@
*/
#include "relic.h"
-#include "relic_test.h"
-#include "relic_bench.h"
/*============================================================================*/
/* Public definitions */
diff --git a/contrib/relic/src/cp/relic_cp_bdpe.c b/contrib/relic/src/cp/relic_cp_bdpe.c
index 7dc575c39..2d60cd3c6 100644
--- a/contrib/relic/src/cp/relic_cp_bdpe.c
+++ b/contrib/relic/src/cp/relic_cp_bdpe.c
@@ -29,15 +29,7 @@
* @ingroup cp
*/
-#include
-
-#include "relic_core.h"
-#include "relic_conf.h"
-#include "relic_rand.h"
-#include "relic_bn.h"
-#include "relic_util.h"
-#include "relic_cp.h"
-#include "relic_md.h"
+#include "relic.h"
/*============================================================================*/
/* Public definitions */
diff --git a/contrib/relic/src/cp/relic_cp_bgn.c b/contrib/relic/src/cp/relic_cp_bgn.c
index 7882c2d58..a7c38193f 100644
--- a/contrib/relic/src/cp/relic_cp_bgn.c
+++ b/contrib/relic/src/cp/relic_cp_bgn.c
@@ -33,13 +33,7 @@
#include
-#include "relic_core.h"
-#include "relic_conf.h"
-#include "relic_rand.h"
-#include "relic_bn.h"
-#include "relic_util.h"
-#include "relic_cp.h"
-#include "relic_md.h"
+#include "relic.h"
/*============================================================================*/
/* Public definitions */
diff --git a/contrib/relic/src/cp/relic_cp_cmlhs.c b/contrib/relic/src/cp/relic_cp_cmlhs.c
index 07638de6e..ecdc96baf 100644
--- a/contrib/relic/src/cp/relic_cp_cmlhs.c
+++ b/contrib/relic/src/cp/relic_cp_cmlhs.c
@@ -96,7 +96,7 @@ int cp_cmlhs_sig(g1_t sig, g2_t z, g1_t a, g1_t c, g1_t r, g2_t s, bn_t msg,
g1_t t;
uint8_t mac[RLC_MD_LEN];
int len, dlen = strlen(data), result = RLC_OK;
- uint8_t *buf = RLC_ALLOCA(uint8_t, 1 + 4 * RLC_FP_BYTES + dlen);
+ uint8_t *buf = RLC_ALLOCA(uint8_t, 1 + 8 * RLC_PC_BYTES + dlen);
bn_null(k);
bn_null(m);
@@ -151,12 +151,7 @@ int cp_cmlhs_sig(g1_t sig, g2_t z, g1_t a, g1_t c, g1_t r, g2_t s, bn_t msg,
g1_add(c, c, t);
g1_norm(c, c);
- if (pc_map_is_type1()) {
- len = 2 * RLC_FP_BYTES + 1;
- } else {
- len = 4 * RLC_FP_BYTES + 1;
- }
-
+ len = g2_size_bin(z, 0);
g2_write_bin(buf, len, z, 0);
memcpy(buf + len, data, dlen);
cp_bls_sig(sig, buf, len + dlen, sk);
@@ -200,7 +195,7 @@ int cp_cmlhs_ver(g1_t r, g2_t s, g1_t sig[], g2_t z[], g1_t a[], g1_t c[],
gt_t e, u, v;
bn_t k, n;
int len, dlen = strlen(data), result = 1;
- uint8_t *buf = RLC_ALLOCA(uint8_t, 1 + 4 * RLC_FP_BYTES + dlen);
+ uint8_t *buf = RLC_ALLOCA(uint8_t, 1 + 8 * RLC_PC_BYTES + dlen);
g1_null(g1);
g2_null(g2);
@@ -311,7 +306,7 @@ int cp_cmlhs_onv(g1_t r, g2_t s, g1_t sig[], g2_t z[], g1_t a[], g1_t c[],
gt_t e, u, v;
bn_t k, n;
int len, dlen = strlen(data), result = 1;
- uint8_t *buf = RLC_ALLOCA(uint8_t, 1 + 4 * RLC_FP_BYTES + dlen);
+ uint8_t *buf = RLC_ALLOCA(uint8_t, 1 + 8 * RLC_FP_BYTES + dlen);
g1_null(g1);
g2_null(g2);
diff --git a/contrib/relic/src/cp/relic_cp_ecdh.c b/contrib/relic/src/cp/relic_cp_ecdh.c
index 31980f577..7479fa955 100755
--- a/contrib/relic/src/cp/relic_cp_ecdh.c
+++ b/contrib/relic/src/cp/relic_cp_ecdh.c
@@ -30,8 +30,6 @@
*/
#include "relic.h"
-#include "relic_test.h"
-#include "relic_bench.h"
/*============================================================================*/
/* Public definitions */
diff --git a/contrib/relic/src/cp/relic_cp_ecdsa.c b/contrib/relic/src/cp/relic_cp_ecdsa.c
index 97fda3cb5..c42db5182 100644
--- a/contrib/relic/src/cp/relic_cp_ecdsa.c
+++ b/contrib/relic/src/cp/relic_cp_ecdsa.c
@@ -30,7 +30,6 @@
*/
#include "relic.h"
-#include "relic_test.h"
/*============================================================================*/
/* Public definitions */
diff --git a/contrib/relic/src/cp/relic_cp_ecies.c b/contrib/relic/src/cp/relic_cp_ecies.c
index 280983161..74b756997 100644
--- a/contrib/relic/src/cp/relic_cp_ecies.c
+++ b/contrib/relic/src/cp/relic_cp_ecies.c
@@ -29,14 +29,7 @@
* @ingroup cp
*/
-#include
-
-#include "relic_core.h"
-#include "relic_bn.h"
-#include "relic_util.h"
-#include "relic_cp.h"
-#include "relic_md.h"
-#include "relic_bc.h"
+#include "relic.h"
/*============================================================================*/
/* Public definitions */
@@ -69,7 +62,7 @@ int cp_ecies_enc(ec_t r, uint8_t *out, int *out_len, uint8_t *in, int in_len,
ec_t q) {
bn_t k, n, x;
ec_t p;
- int l, result = RLC_OK, size = RLC_CEIL(ec_param_level(), 8);
+ int l, result = RLC_OK, size = RLC_CEIL(RLC_MAX(128, ec_param_level()), 8);
uint8_t _x[RLC_FC_BYTES + 1], iv[RLC_BC_LEN] = { 0 };
uint8_t key[2 * 8 * (RLC_FC_BYTES + 1)];
@@ -124,7 +117,7 @@ int cp_ecies_dec(uint8_t *out, int *out_len, ec_t r, uint8_t *in, int in_len,
ec_t p;
bn_t x;
- int l, result = RLC_OK, size = RLC_CEIL(ec_param_level(), 8);
+ int l, result = RLC_OK, size = RLC_CEIL(RLC_MAX(128, ec_param_level()), 8);
uint8_t _x[RLC_FC_BYTES + 1], h[RLC_MD_LEN], iv[RLC_BC_LEN] = { 0 };
uint8_t key[2 * 8 * (RLC_FC_BYTES + 1)];
diff --git a/contrib/relic/src/cp/relic_cp_ecmqv.c b/contrib/relic/src/cp/relic_cp_ecmqv.c
index fd3596ed6..5d40116fb 100644
--- a/contrib/relic/src/cp/relic_cp_ecmqv.c
+++ b/contrib/relic/src/cp/relic_cp_ecmqv.c
@@ -30,8 +30,6 @@
*/
#include "relic.h"
-#include "relic_test.h"
-#include "relic_bench.h"
/*============================================================================*/
/* Public definitions */
diff --git a/contrib/relic/src/cp/relic_cp_ecss.c b/contrib/relic/src/cp/relic_cp_ecss.c
index d943b8960..0ff291033 100644
--- a/contrib/relic/src/cp/relic_cp_ecss.c
+++ b/contrib/relic/src/cp/relic_cp_ecss.c
@@ -30,7 +30,6 @@
*/
#include "relic.h"
-#include "relic_test.h"
/*============================================================================*/
/* Public definitions */
diff --git a/contrib/relic/src/cp/relic_cp_elgamal.c b/contrib/relic/src/cp/relic_cp_elgamal.c
deleted file mode 100644
index 7c1c80fa9..000000000
--- a/contrib/relic/src/cp/relic_cp_elgamal.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * RELIC is an Efficient LIbrary for Cryptography
- * Copyright (c) 2020 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 ElGamal cryptosystem.
- *
- * @ingroup cp
- */
-
-#include
-
-#include "relic_core.h"
-#include "relic_conf.h"
-#include "relic_error.h"
-#include "relic_rand.h"
-#include "relic_bn.h"
-#include "relic_util.h"
-#include "relic_cp.h"
-#include "relic_md.h"
-
-/*============================================================================*/
-/* Public definitions */
-/*============================================================================*/
-
-int cp_elgamal_gen(elgamal_t pub, elgamal_t prv, int bits) {
- int result = STS_OK;
-
- RLC_TRY {
- /* Generate prime p. */
- bn_gen_prime(prv->q, bits);
- bn_copy(pub->q, prv->q);
- bn_rand(prv->x, 0, bits);
- bn_rand(prv->g, 0, bits);
- bn_mod_basic(prv->g, prv->g, prv->q);
- bn_copy(pub->g, prv->g);
- bn_mxp(pub->P, prv->g, prv->x, prv->q);
- bn_copy(prv->P, pub->P);
- }
- RLC_CATCH_ANY {
- result = STS_ERR;
- }
- RLC_FINALLY {
- }
-
- return result;
-}
-
-int cp_elgamal_enc(unsigned char *out, int *out_len, unsigned char *in,
- int in_len, elgamal_t pub) {
- bn_t m, b;
- elgamal_cipher_t c;
- int size, result = STS_OK;
-
- bn_null(m);
- bn_null(c->c1);
- bn_null(c->c2);
- bn_null(b);
-
- bn_size_bin(&size, pub->q);
-
- RLC_TRY {
- bn_new(m);
- bn_new(c->c1);
- bn_new(c->c2);
- bn_new(b);
-
- bn_zero(m);
- bn_zero(c->c1);
- bn_zero(c->c2);
- bn_zero(b);
-
- bn_read_bin(m, in, in_len);
- bn_add(c->c1, c->c1, m);
-
- bn_rand(b, 0, size);
- bn_mxp(c->c1, pub->g, b, pub->q);
- bn_mxp(c->c2, pub->P, b, pub->q);
- bn_mul(c->c2, m, c->c2);
- bn_mod_basic(c->c2, c->c2, pub->q);
-
- if (size <= *out_len) {
- *out_len = size;
- memset(out, 0, *out_len);
- bn_write_bin(out, size, c->c1);
- bn_write_bin(out+size, size, c->c2);
- } else {
- result = STS_ERR;
- }
- }
- RLC_CATCH_ANY {
- result = STS_ERR;
- }
- RLC_FINALLY {
- bn_free(m);
- bn_free(c->c1);
- bn_free(c->c2);
- bn_free(b);
-
- }
-
- return result;
-}
-
-int cp_elgamal_dec(unsigned char *out, int *out_len, unsigned char *in,
- int in_len, elgamal_t prv) {
- bn_t m, c1, c2, r;
- int size, result = STS_OK;
-
-
- if (in_len < 0 || in_len != size) {
- return STS_ERR;
- }
-
- bn_null(m);
- bn_null(c1);
- bn_null(c2);
- bn_null(r);
-
- RLC_TRY {
- bn_new(m);
- bn_new(c1);
- bn_new(c2);
- bn_new(r);
-
- bn_read_bin(c1, in, size);
- bn_read_bin(c2, in+size, size);
- bn_mxp(c1, c1, prv->x, prv->q);
- bn_gcd_ext(r, c1, NULL, c1, prv->q); //TODO verificar se r = 1
- bn_mul(m, c1, c2);
- bn_mod_basic(m, m, prv->q);
-
- if (m->sign == BN_NEG) {
- bn_add(m, m, prv->q);
- }
-
- bn_size_bin(&size, m);
-
- if (bn_cmp(m, prv->q) != CMP_LT) {
- result = STS_ERR;
- }
-
- if (size <= *out_len) {
- memset(out, 0, size);
- bn_write_bin(out, size, m);
- *out_len = size;
- }
- else {
- result = STS_ERR;
- }
- }
- RLC_CATCH_ANY {
- result = STS_ERR;
- }
- RLC_FINALLY {
- bn_free(m);
- bn_free(c1);
- bn_free(c2);
- bn_free(r);
- }
-
- return result;
-}
diff --git a/contrib/relic/src/cp/relic_cp_ers.c b/contrib/relic/src/cp/relic_cp_ers.c
new file mode 100644
index 000000000..ecb5e805e
--- /dev/null
+++ b/contrib/relic/src/cp/relic_cp_ers.c
@@ -0,0 +1,195 @@
+/*
+ * RELIC is an Efficient LIbrary for Cryptography
+ * Copyright (c) 2021 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 extendable ring signatures.
+ *
+ * @ingroup cp
+ */
+
+#include "relic.h"
+
+/*============================================================================*/
+/* Public definitions */
+/*============================================================================*/
+
+int cp_ers_gen(ec_t pp) {
+ ec_rand(pp);
+ return RLC_OK;
+}
+
+int cp_ers_gen_key(bn_t sk, ec_t pk) {
+ bn_t n;
+ int result = RLC_OK;
+
+ bn_null(n);
+
+ RLC_TRY {
+ bn_new(n);
+
+ ec_curve_get_ord(n);
+ bn_rand_mod(sk, n);
+ ec_mul_gen(pk, sk);
+ }
+ RLC_CATCH_ANY {
+ result = RLC_ERR;
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ }
+ return result;
+}
+
+int cp_ers_sig(bn_t td, ers_t p, uint8_t *msg, int len, bn_t sk, ec_t pk,
+ ec_t pp) {
+ bn_t n;
+ ec_t t, y[2];
+ int result = RLC_OK;
+
+ bn_null(n);
+ ec_null(t);
+ ec_null(y[0]);
+ ec_null(y[1]);
+
+ RLC_TRY {
+ bn_new(n);
+ ec_new(t);
+ ec_new(y[0]);
+ ec_new(y[1]);
+
+ ec_curve_get_ord(n);
+ bn_rand_mod(td, n);
+ ec_mul_gen(t, td);
+ ec_sub(t, pp, t);
+ ec_norm(p->h, t);
+
+ ec_copy(p->pk, pk);
+ ec_copy(y[0], p->h);
+ ec_copy(y[1], p->pk);
+ cp_sokor_sig(p->c, p->r, msg, len, y, NULL, sk, 0);
+ }
+ RLC_CATCH_ANY {
+ result = RLC_ERR;
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ ec_free(t);
+ ec_free(y[0]);
+ ec_free(y[1]);
+ }
+ return result;
+}
+
+int cp_ers_ver(bn_t td, ers_t *s, int size, uint8_t *msg, int len, ec_t pp) {
+ bn_t n;
+ ec_t t, y[2];
+ int flag = 0, result = 0;
+
+ bn_null(n);
+ ec_null(t);
+ ec_null(y[0]);
+ ec_null(y[1]);
+
+ RLC_TRY {
+ bn_new(n);
+ ec_new(t);
+ ec_new(y[0]);
+ ec_new(y[1]);
+
+ ec_curve_get_ord(n);
+ ec_mul_gen(t, td);
+
+ for (int i = 0; i < size; i++) {
+ ec_add(t, t, s[i]->h);
+ }
+ if (ec_cmp(pp, t) == RLC_EQ) {
+ flag = 1;
+ for (int i = 0; i < size; i++) {
+ ec_copy(y[0], s[i]->h);
+ ec_copy(y[1], s[i]->pk);
+ flag &= cp_sokor_ver(s[i]->c, s[i]->r, msg, len, y, NULL);
+ }
+ }
+ result = flag;
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ ec_free(t);
+ ec_free(y[0]);
+ ec_free(y[1]);
+ }
+ return result;
+}
+
+int cp_ers_ext(bn_t td, ers_t *p, int *size, uint8_t *msg, int len, ec_t pk,
+ ec_t pp) {
+ bn_t n, r;
+ ec_t y[2];
+ int result = RLC_OK;
+
+ bn_null(n);
+ bn_null(r);
+ ec_null(y[0]);
+ ec_null(y[1]);
+
+ for (int i = 0; i < *size; i++) {
+ if (ec_cmp(pk, p[i]->pk) == RLC_EQ) {
+ return RLC_ERR;
+ }
+ }
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(r);
+ ec_new(y[0]);
+ ec_new(y[1]);
+
+ ec_curve_get_ord(n);
+ bn_rand_mod(r, n);
+ bn_sub(td, td, r);
+ bn_mod(td, td, n);
+ ec_mul_gen(p[*size]->h, r);
+
+ ec_copy(p[*size]->pk, pk);
+ ec_copy(y[0], p[*size]->h);
+ ec_copy(y[1], p[*size]->pk);
+ cp_sokor_sig(p[*size]->c, p[*size]->r, msg, len, y, NULL, r, 1);
+ (*size)++;
+ result = RLC_OK;
+ }
+ RLC_CATCH_ANY {
+ result = RLC_ERR;
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ bn_free(r);
+ ec_free(y[0]);
+ ec_free(y[1]);
+ }
+ return result;
+}
diff --git a/contrib/relic/src/cp/relic_cp_etrs.c b/contrib/relic/src/cp/relic_cp_etrs.c
new file mode 100644
index 000000000..d55dee871
--- /dev/null
+++ b/contrib/relic/src/cp/relic_cp_etrs.c
@@ -0,0 +1,401 @@
+/*
+ * RELIC is an Efficient LIbrary for Cryptography
+ * Copyright (c) 2021 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 extendable ring signatures.
+ *
+ * @ingroup cp
+ */
+
+#include "relic.h"
+
+/*============================================================================*/
+/* Public definitions */
+/*============================================================================*/
+
+int cp_etrs_sig(bn_t *td, bn_t *y, int max, etrs_t p, uint8_t *msg, int len,
+ bn_t sk, ec_t pk, ec_t pp) {
+ bn_t n, l, u, v, z;
+ ec_t t, w[2];
+ bn_t *_v = RLC_ALLOCA(bn_t, max);
+ int result = RLC_OK;
+
+ bn_null(n);
+ bn_null(l);
+ bn_null(u);
+ bn_null(v);
+ bn_null(z);
+ ec_null(t);
+ ec_null(w[0]);
+ ec_null(w[1]);
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(l);
+ bn_new(u);
+ bn_new(v);
+ bn_new(z);
+ ec_new(t);
+ ec_new(w[0]);
+ ec_new(w[1]);
+
+ ec_curve_get_ord(n);
+ if (_v == NULL) {
+ RLC_THROW(ERR_NO_MEMORY);
+ }
+ for(int i = 0; i < max; i++) {
+ bn_new(_v[i]);
+ bn_rand_mod(y[i], n);
+ bn_rand_mod(td[i], n);
+ }
+ bn_rand_mod(p->y, n);
+
+ bn_set_dig(l, 1);
+ for(int j = 0; j < max; j++) {
+ bn_copy(_v[j], y[j]);
+ }
+ bn_mod_inv_sim(_v, _v, n, max);
+ for(int j = 0; j < max; j++) {
+ bn_sub(u, y[j], p->y);
+ bn_mul(u, u, _v[j]);
+ bn_mod(u, u, n);
+ bn_mul(l, l, u);
+ bn_mod(l, l, n);
+ }
+ ec_mul(p->h, pp, l);
+ for(int i = 0; i < max; i++) {
+ ec_mul_gen(t, td[i]);
+ bn_mod_inv(v, y[i], n);
+ bn_mul(u, v, p->y);
+ bn_mod(l, u, n);
+ for(int j = 0; j < max; j++) {
+ bn_set_dig(_v[j], 1);
+ if (j != i) {
+ bn_sub(_v[j], y[j], y[i]);
+ bn_mod(_v[j], _v[j], n);
+ }
+ }
+ bn_mod_inv_sim(_v, _v, n, max);
+ for(int j = 0; j < max; j++) {
+ if (j != i) {
+ bn_sub(u, y[j], p->y);
+ bn_mul(u, u, _v[j]);
+ bn_mod(u, u, n);
+ bn_mul(l, l, u);
+ bn_mod(l, l, n);
+ }
+ }
+ ec_mul(t, t, l);
+ ec_add(p->h, p->h, t);
+ }
+ ec_norm(p->h, p->h);
+
+ ec_copy(p->pk, pk);
+ ec_copy(w[0], p->h);
+ ec_copy(w[1], p->pk);
+ cp_sokor_sig(p->c, p->r, msg, len, w, NULL, sk, 0);
+ }
+ RLC_CATCH_ANY {
+ result = RLC_ERR;
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ bn_free(l);
+ bn_free(u);
+ bn_free(v);
+ bn_free(z);
+ ec_free(t);
+ ec_free(w[0]);
+ ec_free(w[1]);
+ for (int i = 0; i < max; i++) {
+ bn_free(_v[i]);
+ }
+ RLC_FREE(_v);
+ }
+ return result;
+}
+
+int cp_etrs_ver(int thres, bn_t *td, bn_t *y, int max, etrs_t *s, int size,
+ uint8_t *msg, int len, ec_t pp) {
+ int i, flag = 0, result = 0;
+ bn_t l, n, u, v;
+ ec_t t, w[2];
+
+ int d = max + size - thres;
+ bn_t *_v = RLC_ALLOCA(bn_t, d);
+ bn_t *_y = RLC_ALLOCA(bn_t, d);
+ ec_t *_t = RLC_ALLOCA(ec_t, d);
+
+ bn_null(l);
+ bn_null(n);
+ bn_null(u);
+ bn_null(v);
+ ec_null(t);
+ ec_null(w[0]);
+ ec_null(w[1]);
+
+ RLC_TRY {
+ bn_new(l);
+ bn_new(n);
+ bn_new(u);
+ bn_new(v);
+ ec_new(t);
+ ec_new(w[0]);
+ ec_new(w[1]);
+ if (_y == NULL || _t == NULL) {
+ RLC_THROW(ERR_NO_MEMORY);
+ }
+ for (i = 0; i < d; i++) {
+ bn_new(_v[i]);
+ bn_new(_y[i]);
+ ec_new(_t[i]);
+ }
+
+ for (i = 0; i < max; i++) {
+ bn_copy(_y[i], y[i]);
+ ec_mul_gen(_t[i], td[i]);
+ }
+ for (; i < d; i++) {
+ bn_copy(_y[i], s[i - max]->y);
+ ec_copy(_t[i], s[i - max]->h);
+ }
+
+ ec_curve_get_ord(n);
+
+ flag = 1;
+ ec_set_infty(w[0]);
+ for(i = 0; i < d; i++) {
+ for(int j = 0; j < d; j++) {
+ bn_set_dig(_v[j], 1);
+ if (j != i) {
+ bn_sub(_v[j], _y[j], _y[i]);
+ bn_mod(_v[j], _v[j], n);
+ }
+ }
+ bn_mod_inv_sim(_v, _v, n, d);
+ bn_set_dig(l, 1);
+ for(int j = 0; j < d; j++) {
+ if (j != i) {
+ bn_mul(u, _y[j], _v[j]);
+ bn_mod(u, u, n);
+ bn_mul(l, l, u);
+ bn_mod(l, l, n);
+ }
+ }
+
+ ec_mul(t, _t[i], l);
+ ec_add(w[0], w[0], t);
+ }
+ ec_norm(w[0], w[0]);
+ flag &= ec_cmp(w[0], pp) != RLC_EQ;
+
+ for (int i = 0; i < size; i++) {
+ ec_copy(w[0], s[i]->h);
+ ec_copy(w[1], s[i]->pk);
+ flag &= cp_sokor_ver(s[i]->c, s[i]->r, msg, len, w, NULL);
+ }
+ result = flag;
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ bn_free(l);
+ bn_free(n);
+ bn_free(u);
+ bn_free(v);
+ ec_free(t);
+ ec_free(w[0]);
+ ec_free(w[1]);
+ for (int i = 0; i < d; i++) {
+ bn_free(_v[i]);
+ bn_free(_y[i]);
+ ec_free(_t[i]);
+ }
+ RLC_FREE(_v);
+ RLC_FREE(_y);
+ RLC_FREE(_t);
+ }
+ return result;
+}
+
+int cp_etrs_ext(bn_t *td, bn_t *y, int max, etrs_t *p, int *size, uint8_t *msg, int len,
+ ec_t pk, ec_t pp) {
+ bn_t n, r;
+ ec_t w[2];
+ int i, result = RLC_OK;
+
+ bn_null(n);
+ bn_null(r);
+ ec_null(w[0]);
+ ec_null(w[1]);
+
+ for (int i = 0; i < *size; i++) {
+ if (ec_cmp(pk, p[i]->pk) == RLC_EQ) {
+ return RLC_ERR;
+ }
+ }
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(r);
+ ec_new(w[0]);
+ ec_new(w[1]);
+
+ for (i = 0; i < max; i++) {
+ if (!bn_is_zero(td[i])) {
+ break;
+ }
+ }
+ bn_copy(r, td[i]);
+
+ ec_curve_get_ord(n);
+ ec_mul_gen(p[*size]->h, td[i]);
+ bn_copy(p[*size]->y, y[i]);
+
+ bn_zero(td[i]);
+ bn_zero(y[i]);
+
+ ec_copy(p[*size]->pk, pk);
+ ec_copy(w[0], p[*size]->h);
+ ec_copy(w[1], p[*size]->pk);
+ cp_sokor_sig(p[*size]->c, p[*size]->r, msg, len, w, NULL, r, 1);
+ (*size)++;
+ result = RLC_OK;
+ }
+ RLC_CATCH_ANY {
+ result = RLC_ERR;
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ bn_free(r);
+ ec_free(w[0]);
+ ec_free(w[1]);
+ }
+ return result;
+}
+
+int cp_etrs_uni(int thres, bn_t *td, bn_t *y, int max, etrs_t *p, int *size,
+ uint8_t *msg, int len, bn_t sk, ec_t pk, ec_t pp) {
+ int i, result = 0;
+ bn_t l, n, u, v;
+ ec_t t, w[2];
+
+ int d = max + *size;
+ bn_t *_v = RLC_ALLOCA(bn_t, d);
+ bn_t *_y = RLC_ALLOCA(bn_t, d);
+ ec_t *_t = RLC_ALLOCA(ec_t, d);
+
+ bn_null(l);
+ bn_null(n);
+ bn_null(u);
+ bn_null(v);
+ ec_null(t);
+ ec_null(w[0]);
+ ec_null(w[1]);
+
+ RLC_TRY {
+ bn_new(l);
+ bn_new(n);
+ bn_new(u);
+ bn_new(v);
+ ec_new(t);
+ ec_new(w[0]);
+ ec_new(w[1]);
+ if (_v == NULL || _y == NULL || _t == NULL) {
+ RLC_THROW(ERR_NO_MEMORY);
+ }
+ for (i = 0; i < d; i++) {
+ bn_new(_v[i]);
+ bn_new(_y[i]);
+ ec_new(_t[i]);
+ }
+
+ for (i = 0; i < max; i++) {
+ bn_copy(_y[i], y[i]);
+ ec_mul_gen(_t[i], td[i]);
+ }
+ for (; i < d; i++) {
+ bn_copy(_y[i], p[i - max]->y);
+ ec_copy(_t[i], p[i - max]->h);
+ }
+
+ ec_curve_get_ord(n);
+ bn_rand_mod(p[*size]->y, n);
+
+ ec_set_infty(p[*size]->h);
+ for(i = 0; i < d; i++) {
+ for(int j = 0; j < d; j++) {
+ bn_set_dig(_v[j], 1);
+ if (j != i) {
+ bn_sub(_v[j], _y[j], _y[i]);
+ bn_mod(_v[j], _v[j], n);
+ }
+ }
+ bn_mod_inv_sim(_v, _v, n, d);
+ bn_set_dig(l, 1);
+ for(int j = 0; j < d; j++) {
+ if (j != i) {
+ bn_sub(u, _y[j], p[*size]->y);
+ bn_mul(u, u, _v[j]);
+ bn_mod(u, u, n);
+ bn_mul(l, l, u);
+ bn_mod(l, l, n);
+ }
+ }
+ ec_mul(t, _t[i], l);
+ ec_add(p[*size]->h, p[*size]->h, t);
+ }
+ ec_norm(p[*size]->h, p[*size]->h);
+
+ ec_copy(p[*size]->pk, pk);
+ ec_copy(w[0], p[*size]->h);
+ ec_copy(w[1], p[*size]->pk);
+ cp_sokor_sig(p[*size]->c, p[*size]->r, msg, len, w, NULL, sk, 0);
+ (*size)++;
+ result = RLC_OK;
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ bn_free(l);
+ bn_free(n);
+ bn_free(u);
+ bn_free(v);
+ ec_free(t);
+ ec_free(w[0]);
+ ec_free(w[1]);
+ for (int i = 0; i < d; i++) {
+ bn_free(_v[i]);
+ bn_free(_y[i]);
+ ec_free(_t[i]);
+ }
+ RLC_FREE(_v);
+ RLC_FREE(_y);
+ RLC_FREE(_t);
+ }
+ return result;
+}
diff --git a/contrib/relic/src/cp/relic_cp_ghpe.c b/contrib/relic/src/cp/relic_cp_ghpe.c
index 6bfb588ea..d69edb8be 100644
--- a/contrib/relic/src/cp/relic_cp_ghpe.c
+++ b/contrib/relic/src/cp/relic_cp_ghpe.c
@@ -30,16 +30,7 @@
* @ingroup cp
*/
-#include
-
-#include "relic_core.h"
-#include "relic_multi.h"
-#include "relic_conf.h"
-#include "relic_rand.h"
-#include "relic_bn.h"
-#include "relic_util.h"
-#include "relic_cp.h"
-#include "relic_md.h"
+#include "relic.h"
/*============================================================================*/
/* Public definitions */
diff --git a/contrib/relic/src/cp/relic_cp_ibe.c b/contrib/relic/src/cp/relic_cp_ibe.c
index e7af51b8b..8e6b8d50f 100644
--- a/contrib/relic/src/cp/relic_cp_ibe.c
+++ b/contrib/relic/src/cp/relic_cp_ibe.c
@@ -30,8 +30,6 @@
*/
#include "relic.h"
-#include "relic_test.h"
-#include "relic_bench.h"
/*============================================================================*/
/* Public definitions */
diff --git a/contrib/relic/src/cp/relic_cp_lapsi.c b/contrib/relic/src/cp/relic_cp_lapsi.c
new file mode 100644
index 000000000..facdb9ee0
--- /dev/null
+++ b/contrib/relic/src/cp/relic_cp_lapsi.c
@@ -0,0 +1,205 @@
+/*
+ * RELIC is an Efficient LIbrary for Cryptography
+ * Copyright (c) 2021 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 protocols for laconic private set intersection.
+ *
+ * @ingroup cp
+ */
+
+#include "relic.h"
+
+/*============================================================================*/
+/* Public definitions */
+/*============================================================================*/
+
+int cp_lapsi_gen(bn_t sk, g2_t ss, g1_t s[], int m) {
+ int i, result = RLC_OK;
+ bn_t q;
+
+ bn_null(q);
+
+ RLC_TRY {
+ bn_new(q);
+
+ pc_get_ord(q);
+ bn_rand_mod(sk, q);
+ g2_mul_gen(ss, sk);
+
+ g1_get_gen(s[0]);
+ for (i = 1; i <= m; i++) {
+ g1_mul(s[i], s[i - 1], sk);
+ }
+ }
+ RLC_CATCH_ANY {
+ result = RLC_ERR;
+ }
+ RLC_FINALLY {
+ bn_free(q);
+ }
+ return result;
+}
+
+int cp_lapsi_ask(g1_t d, bn_t r, bn_t x[], g1_t s[], int m) {
+ int i, j, result = RLC_OK;
+ bn_t q, *p = RLC_ALLOCA(bn_t, m + 1), *_p = RLC_ALLOCA(bn_t, m + 1);
+
+ bn_null(q);
+
+ RLC_TRY {
+ bn_new(q);
+ for (i = 0; i <= m; i++) {
+ bn_null(p[i]);
+ bn_null(_p[i]);
+ bn_new(p[i]);
+ bn_new(_p[i]);
+ }
+
+ pc_get_ord(q);
+ bn_rand_mod(r, q);
+ if (m == 0) {
+ g1_mul_gen(d, r);
+ } else {
+ bn_set_dig(p[0], 1);
+ for (i = 0; i < m; i++) {
+ bn_zero(_p[0]);
+ for (j = 0; j <= i; j++) {
+ bn_copy(_p[j + 1], p[j]);
+ }
+ for (j = 0; j <= i; j++) {
+ bn_mul(p[j], p[j], x[i]);
+ bn_mod(p[j], p[j], q);
+ bn_sub(p[j], _p[j], p[j]);
+ bn_mod(p[j], p[j], q);
+ }
+ bn_copy(p[j], _p[j]);
+ }
+ g1_mul_sim_lot(d, s, p, m + 1);
+ g1_mul(d, d, r);
+ }
+ }
+ RLC_CATCH_ANY {
+ result = RLC_ERR;
+ }
+ RLC_FINALLY {
+ bn_free(q);
+ for (i = 0; i <= m; i++) {
+ bn_free(p[i]);
+ bn_free(_p[i]);
+ }
+ RLC_FREE(p);
+ RLC_FREE(_p);
+ }
+ return result;
+}
+
+int cp_lapsi_ans(gt_t t[], g2_t u[], g1_t d, g2_t ss, bn_t y[], int n) {
+ int j, result = RLC_OK;
+ bn_t q, tj;
+ g1_t g1;
+ g2_t g2;
+
+ bn_null(q);
+ bn_null(tj);
+ g1_null(g1);
+ g2_null(g2);
+
+ RLC_TRY {
+ bn_new(q);
+ bn_new(tj);
+ g1_new(g1);
+ g2_new(g2);
+
+ pc_get_ord(q);
+ g2_get_gen(g2);
+ for (j = 0; j < n; j++) {
+ bn_rand_mod(tj, q);
+ g1_mul(g1, d, tj);
+ pc_map(t[j], g1, g2);
+ g2_mul_gen(u[j], y[j]);
+ g2_sub(u[j], ss, u[j]);
+ g2_norm(u[j], u[j]);
+ g2_mul(u[j], u[j], tj);
+ }
+ }
+ RLC_CATCH_ANY {
+ result = RLC_ERR;
+ }
+ RLC_FINALLY {
+ bn_free(q);
+ bn_free(tj);
+ g1_free(g1);
+ g1_free(g2);
+ }
+ return result;
+}
+
+int cp_lapsi_int(bn_t z[], int *len, bn_t sk, g1_t d, bn_t x[], int m,
+ gt_t t[], g2_t u[], int n) {
+ int j, k, result = RLC_OK;
+ bn_t i, q;
+ g1_t c;
+ gt_t e;
+
+ bn_null(i);
+ bn_null(q);
+ g1_null(c);
+ gt_null(e);
+
+ RLC_TRY {
+ bn_new(i);
+ bn_new(q);
+ g1_new(c);
+ gt_new(e);
+
+ *len = 0;
+ if (m > 0) {
+ pc_get_ord(q);
+ for (k = 0; k < m; k++) {
+ bn_sub(i, sk, x[k]);
+ bn_mod(i, i, q);
+ bn_mod_inv(i, i, q);
+ g1_mul(c, d, i);
+ for (j = 0; j < n; j++) {
+ pc_map(e, c, u[j]);
+ if (gt_cmp(e, t[j]) == RLC_EQ && !gt_is_unity(e)) {
+ bn_copy(z[*len], x[k]);
+ (*len)++;
+ }
+ }
+ }
+ }
+ }
+ RLC_CATCH_ANY {
+ result = RLC_ERR;
+ }
+ RLC_FINALLY {
+ bn_free(i);
+ bn_free(q);
+ g1_free(c);
+ gt_free(e);
+ }
+ return result;
+}
diff --git a/contrib/relic/src/cp/relic_cp_pcdel.c b/contrib/relic/src/cp/relic_cp_pcdel.c
new file mode 100644
index 000000000..a8ded35e5
--- /dev/null
+++ b/contrib/relic/src/cp/relic_cp_pcdel.c
@@ -0,0 +1,461 @@
+/*
+ * RELIC is an Efficient LIbrary for Cryptography
+ * Copyright (c) 2021 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 delegation protocols.
+ *
+ * @ingroup cp
+ */
+
+#include "relic.h"
+
+/*============================================================================*/
+/* Public definitions */
+/*============================================================================*/
+
+int cp_pdpub_gen(bn_t c, bn_t r, g1_t u1, g2_t u2, g2_t v2, gt_t e) {
+ bn_t n;
+ int result = RLC_OK;
+
+ bn_null(n);
+
+ RLC_TRY {
+ bn_new(n);
+
+ /* Generate random c, U1, r, U2. */
+ pc_get_ord(n);
+ bn_rand(c, RLC_POS, 50);
+ g1_rand(u1);
+ bn_rand_mod(r, n);
+ g2_rand(u2);
+ /* Compute gamma = e(U1, U2) and V2 = [1/r2]U2. */
+ bn_mod_inv(n, r, n);
+ g2_mul(v2, u2, n);
+ pc_map(e, u1, u2);
+ }
+ RLC_CATCH_ANY {
+ result = RLC_ERR;
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ }
+ return result;
+}
+
+int cp_pdpub_ask(g1_t v1, g2_t w2, g1_t p, g2_t q, bn_t c, bn_t r, g1_t u1, g2_t u2, g2_t v2) {
+ int result = RLC_OK;
+
+ /* Compute V1 = [r](P - U1). */
+ g1_sub(v1, p, u1);
+ g1_mul(v1, v1, r);
+ /* Compute W2 = [c]Q + U2. */
+ g2_mul(w2, q, c);
+ g2_add(w2, w2, u2);
+
+ return result;
+}
+
+int cp_pdpub_ans(gt_t g[3], g1_t p, g2_t q, g1_t v1, g2_t v2, g2_t w2) {
+ int result = RLC_OK;
+ pc_map(g[0], p, q);
+ pc_map(g[1], p, w2);
+ pc_map(g[2], v1, v2);
+ return result;
+}
+
+int cp_pdpub_ver(gt_t r, gt_t g[3], bn_t c, gt_t e) {
+ int result = 1;
+ gt_t t;
+
+ gt_null(t);
+
+ RLC_TRY {
+ gt_new(t);
+
+ result &= gt_is_valid(g[0]);
+ result &= gt_is_valid(g[2]);
+
+ gt_exp(t, g[0], c);
+ gt_mul(t, t, g[2]);
+ gt_mul(t, t, e);
+
+ if (!result || gt_cmp(t, g[1]) != RLC_EQ) {
+ gt_set_unity(r);
+ } else {
+ gt_copy(r, g[0]);
+ }
+ } RLC_CATCH_ANY {
+ result = RLC_ERR;
+ }
+ RLC_FINALLY {
+ gt_free(t);
+ }
+ return result;
+}
+
+int cp_pdprv_gen(bn_t c, bn_t r[3], g1_t u1[2], g2_t u2[2], g2_t v2[4], gt_t e[2]) {
+ bn_t n;
+ int result = RLC_OK;
+
+ bn_null(n);
+
+ RLC_TRY {
+ bn_new(n);
+
+ pc_get_ord(n);
+ bn_rand_mod(r[2], n);
+ bn_rand(c, RLC_POS, 50);
+ for (int i = 0; i < 2; i++) {
+ /* Generate random c, r, Ui. */
+ g1_rand(u1[i]);
+ bn_rand_mod(r[i], n);
+ g2_rand(u2[i]);
+ /* Compute gamma = e(U1, U2) and V2 = [1/r2]U2. */
+ pc_get_ord(n);
+ bn_mod_inv(n, r[i], n);
+ g2_mul(v2[i], u2[i], n);
+ pc_map(e[i], u1[i], u2[i]);
+ }
+ g2_mul(v2[2], u2[0], r[2]);
+ g2_neg(v2[2], v2[2]);
+ g2_mul(v2[3], u2[1], r[2]);
+ }
+ RLC_CATCH_ANY {
+ result = RLC_ERR;
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ }
+ return result;
+}
+
+int cp_pdprv_ask(g1_t v1[3], g2_t w2[4], g1_t p, g2_t q, bn_t c, bn_t r[3], g1_t u1[2], g2_t u2[2], g2_t v2[4]) {
+ int result = RLC_OK;
+ bn_t n;
+
+ bn_null(n);
+
+ RLC_TRY {
+ bn_new(n);
+
+ pc_get_ord(n);
+ bn_mod_inv(n, r[2], n);
+ g1_mul(v1[2], p, n);
+ for (int i = 0; i < 2; i++) {
+ /* Compute V1 = [r](A - Ui). */
+ g1_sub(v1[i], p, u1[i]);
+ g1_mul(v1[i], v1[i], r[i]);
+ }
+ g2_mul(w2[0], q, r[2]);
+ g2_add(w2[2], w2[0], v2[2]);
+ g2_mul(w2[3], w2[0], c);
+ g2_add(w2[3], w2[3], v2[3]);
+ g2_copy(w2[0], v2[0]);
+ g2_copy(w2[1], v2[1]);
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ } RLC_FINALLY {
+ bn_free(n);
+ }
+
+ return result;
+}
+
+int cp_pdprv_ans(gt_t g[4], g1_t v1[3], g2_t w2[4]) {
+ int result = RLC_OK;
+ pc_map(g[0], v1[0], w2[0]);
+ pc_map(g[1], v1[1], w2[1]);
+ pc_map(g[2], v1[2], w2[2]);
+ pc_map(g[3], v1[2], w2[3]);
+ return result;
+}
+
+int cp_pdprv_ver(gt_t r, gt_t g[4], bn_t c, gt_t e[2]) {
+ int result = 1;
+ gt_t t;
+
+ gt_null(t);
+
+ RLC_TRY {
+ gt_new(t);
+
+ result &= gt_is_valid(g[0]);
+ result &= gt_is_valid(g[1]);
+ result &= gt_is_valid(g[2]);
+
+ gt_mul(t, g[0], g[2]);
+ gt_mul(r, t, e[0]);
+ gt_exp(t, r, c);
+ gt_mul(t, t, g[1]);
+ gt_mul(t, t, e[1]);
+
+ if (!result || gt_cmp(t, g[3]) != RLC_EQ) {
+ gt_set_unity(r);
+ }
+ } RLC_CATCH_ANY {
+ result = RLC_ERR;
+ }
+ RLC_FINALLY {
+ gt_free(t);
+ }
+ return result;
+}
+
+int cp_lvpub_gen(bn_t r, g1_t u1, g2_t u2, g2_t v2, gt_t e) {
+ bn_t n;
+ int result = RLC_OK;
+
+ bn_null(n);
+
+ RLC_TRY {
+ bn_new(n);
+
+ /* Generate random c, U1, r, U2. */
+ pc_get_ord(n);
+ g1_rand(u1);
+ bn_rand_mod(r, n);
+ g2_rand(u2);
+ /* Compute gamma = e(U1, U2) and V2 = [1/r2]U2. */
+ bn_mod_inv(n, r, n);
+ g2_mul(v2, u2, n);
+ pc_map(e, u1, u2);
+ }
+ RLC_CATCH_ANY {
+ result = RLC_ERR;
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ }
+ return result;
+}
+
+int cp_lvpub_ask(bn_t c, g1_t v1, g2_t w2, g1_t p, g2_t q, bn_t r, g1_t u1, g2_t u2, g2_t v2) {
+ int result = RLC_OK;
+
+ /* Sample random c. */
+ bn_rand(c, RLC_POS, 50);
+ /* Compute V1 = [r](P - U1). */
+ g1_sub(v1, p, u1);
+ g1_mul(v1, v1, r);
+ /* Compute W2 = [c]Q + U_2. */
+ g2_mul(w2, q, c);
+ g2_add(w2, w2, u2);
+
+ return result;
+}
+
+int cp_lvpub_ans(gt_t g[2], g1_t p, g2_t q, g1_t v1, g2_t v2, g2_t w2) {
+ int result = RLC_OK;
+ g1_t _p[2];
+ g2_t _q[2];
+
+ g1_null(_p[0]);
+ g1_null(_p[1]);
+ g2_null(_q[0]);
+ g2_null(_q[1]);
+
+ RLC_TRY {
+ g1_new(_p[0]);
+ g1_new(_p[1]);
+ g2_new(_q[0]);
+ g2_new(_q[1]);
+
+ g1_copy(_p[0], p);
+ g1_copy(_p[1], v1);
+ g2_copy(_q[0], w2);
+ g2_neg(_q[1], v2);
+ pc_map_sim(g[1], _p, _q, 2);
+ pc_map(g[0], p, q);
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ } RLC_FINALLY {
+ g1_free(_p[0]);
+ g1_free(_p[1]);
+ g2_free(_q[0]);
+ g2_free(_q[1]);
+ }
+
+ return result;
+}
+
+int cp_lvpub_ver(gt_t r, gt_t g[2], bn_t c, gt_t e) {
+ int result = 1;
+ gt_t t;
+
+ gt_null(t);
+
+ RLC_TRY {
+ gt_new(t);
+
+ result &= gt_is_valid(g[0]);
+
+ gt_exp(t, g[0], c);
+ gt_inv(t, t);
+ gt_mul(t, t, g[1]);
+
+ if (!result || gt_cmp(t, e) != RLC_EQ) {
+ gt_set_unity(r);
+ } else {
+ gt_copy(r, g[0]);
+ }
+ } RLC_CATCH_ANY {
+ result = RLC_ERR;
+ }
+ RLC_FINALLY {
+ gt_free(t);
+ }
+ return result;
+}
+
+int cp_lvprv_gen(bn_t c, bn_t r[3], g1_t u1[2], g2_t u2[2], g2_t v2[4], gt_t e[2]) {
+ bn_t n;
+ int result = RLC_OK;
+
+ bn_null(n);
+
+ RLC_TRY {
+ bn_new(n);
+
+ pc_get_ord(n);
+ bn_rand_mod(r[2], n);
+ bn_rand(c, RLC_POS, 50);
+ for (int i = 0; i < 2; i++) {
+ /* Generate random c, r, Ui. */
+ g1_rand(u1[i]);
+ bn_rand_mod(r[i], n);
+ g2_rand(u2[i]);
+ /* Compute gamma = e(U1, U2) and V2 = [1/r2]U2. */
+ pc_get_ord(n);
+ bn_mod_inv(n, r[i], n);
+ g2_mul(v2[i], u2[i], n);
+ pc_map(e[i], u1[i], u2[i]);
+ }
+ g2_mul(v2[2], u2[0], r[2]);
+ g2_neg(v2[2], v2[2]);
+ g2_mul(v2[3], u2[1], r[2]);
+ }
+ RLC_CATCH_ANY {
+ result = RLC_ERR;
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ }
+ return result;
+}
+
+int cp_lvprv_ask(g1_t v1[3], g2_t w2[4], g1_t p, g2_t q, bn_t c, bn_t r[3], g1_t u1[2], g2_t u2[2], g2_t v2[4]) {
+ int result = RLC_OK;
+ bn_t n;
+
+ bn_null(n);
+
+ RLC_TRY {
+ bn_new(n);
+
+ pc_get_ord(n);
+ bn_mod_inv(n, r[2], n);
+ g1_mul(v1[2], p, n);
+ for (int i = 0; i < 2; i++) {
+ /* Compute V1 = [r](A - Ui). */
+ g1_sub(v1[i], p, u1[i]);
+ g1_mul(v1[i], v1[i], r[i]);
+ }
+ g2_mul(w2[0], q, r[2]);
+ g2_add(w2[2], w2[0], v2[2]);
+ g2_mul(w2[3], w2[0], c);
+ g2_add(w2[3], w2[3], v2[3]);
+ g2_copy(w2[0], v2[0]);
+ g2_copy(w2[1], v2[1]);
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ } RLC_FINALLY {
+ bn_free(n);
+ }
+
+ return result;
+}
+
+int cp_lvprv_ans(gt_t g[4], g1_t v1[3], g2_t w2[4]) {
+ int result = RLC_OK;
+ g1_t _p[2];
+ g2_t _q[2];
+
+ g1_null(_p[0]);
+ g1_null(_p[1]);
+ g2_null(_q[0]);
+ g2_null(_q[1]);
+
+ RLC_TRY {
+ g1_new(_p[0]);
+ g1_new(_p[1]);
+ g2_new(_q[0]);
+ g2_new(_q[1]);
+
+ g1_copy(_p[0], v1[0]);
+ g1_copy(_p[1], v1[2]);
+ g2_copy(_q[0], w2[0]);
+ g2_copy(_q[1], w2[2]);
+ pc_map_sim(g[0], _p, _q, 2);
+ pc_map(g[1], v1[1], w2[1]);
+ pc_map(g[2], v1[2], w2[3]);
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ } RLC_FINALLY {
+ g1_free(_p[0]);
+ g1_free(_p[1]);
+ g2_free(_q[0]);
+ g2_free(_q[1]);
+ }
+ return result;
+}
+
+int cp_lvprv_ver(gt_t r, gt_t g[4], bn_t c, gt_t e[2]) {
+ int result = 1;
+ gt_t t;
+
+ gt_null(t);
+
+ RLC_TRY {
+ gt_new(t);
+
+ result &= gt_is_valid(g[0]);
+ result &= gt_is_valid(g[1]);
+
+ gt_mul(r, g[0], e[0]);
+ gt_exp(t, r, c);
+ gt_mul(t, t, g[1]);
+ gt_mul(t, t, e[1]);
+
+ if (!result || gt_cmp(t, g[2]) != RLC_EQ) {
+ gt_set_unity(r);
+ }
+ } RLC_CATCH_ANY {
+ result = RLC_ERR;
+ }
+ RLC_FINALLY {
+ gt_free(t);
+ }
+ return result;
+}
diff --git a/contrib/relic/src/cp/relic_cp_phpe.c b/contrib/relic/src/cp/relic_cp_phpe.c
index ce1971b1f..c10e0f453 100644
--- a/contrib/relic/src/cp/relic_cp_phpe.c
+++ b/contrib/relic/src/cp/relic_cp_phpe.c
@@ -29,16 +29,7 @@
* @ingroup cp
*/
-#include
-
-#include "relic_core.h"
-#include "relic_multi.h"
-#include "relic_conf.h"
-#include "relic_rand.h"
-#include "relic_bn.h"
-#include "relic_util.h"
-#include "relic_cp.h"
-#include "relic_md.h"
+#include "relic.h"
/*============================================================================*/
/* Public definitions */
diff --git a/contrib/relic/src/cp/relic_cp_pok.c b/contrib/relic/src/cp/relic_cp_pok.c
new file mode 100644
index 000000000..236408875
--- /dev/null
+++ b/contrib/relic/src/cp/relic_cp_pok.c
@@ -0,0 +1,265 @@
+/*
+ * RELIC is an Efficient LIbrary for Cryptography
+ * Copyright (c) 2021 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 protocols for proof of knowledge of discrete logarithms.
+ *
+ * @ingroup cp
+ */
+
+#include "relic.h"
+
+/*============================================================================*/
+/* Public definitions */
+/*============================================================================*/
+
+/*
+ * Source: "Proof Systems for General Statements about Discrete Logarithms"
+ * Authors: Jan Camenisc, Markus Stadler (1997)
+ */
+
+int cp_pokdl_prv(bn_t c, bn_t r, ec_t y, bn_t x) {
+ bn_t n, v;
+ ec_t t;
+ int l, result = RLC_OK;
+ uint8_t *buf, bin[3 * (RLC_FC_BYTES + 1)] = { 0 }, h[RLC_MD_LEN];
+
+ bn_null(n);
+ bn_null(v);
+ ec_null(t);
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(v);
+ ec_new(t);
+
+ buf = bin;
+ ec_curve_get_ord(n);
+ ec_curve_get_gen(t);
+ l = ec_size_bin(t, 1);
+ ec_write_bin(buf, l, t, 1);
+ buf += l;
+ l = ec_size_bin(y, 1);
+ ec_write_bin(buf, l, y, 1);
+ buf += l;
+
+ bn_rand_mod(v, n);
+ ec_mul_gen(t, v);
+ l = ec_size_bin(t, 1);
+ ec_write_bin(buf, l, t, 1);
+ md_map(h, bin, sizeof(bin));
+ bn_read_bin(c, h, RLC_MD_LEN);
+ bn_mod(c, c, n);
+ bn_mul(r, c, x);
+ bn_sub(r, v, r);
+ bn_mod(r, r, n);
+ }
+ RLC_CATCH_ANY {
+ result = RLC_ERR;
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ bn_free(v);
+ ec_free(t);
+ }
+ return result;
+}
+
+int cp_pokdl_ver(bn_t c, bn_t r, ec_t y) {
+ bn_t n, v;
+ ec_t t;
+ int l, result = 0;
+ uint8_t *buf, bin[3 * (RLC_FC_BYTES + 1)] = { 0 }, h[RLC_MD_LEN];
+
+ bn_null(n);
+ bn_null(v);
+ ec_null(t);
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(v);
+ ec_new(t);
+
+ buf = bin;
+ ec_curve_get_ord(n);
+ ec_curve_get_gen(t);
+ l = ec_size_bin(t, 1);
+ ec_write_bin(buf, l, t, 1);
+ buf += l;
+ l = ec_size_bin(y, 1);
+ ec_write_bin(buf, l, y, 1);
+ buf += l;
+
+ /* Compute t' = [r]G + [c]Y. */
+ ec_mul_sim_gen(t, r, y, c);
+ l = ec_size_bin(t, 1);
+ ec_write_bin(buf, l, t, 1);
+ md_map(h, bin, sizeof(bin));
+ bn_read_bin(v, h, RLC_MD_LEN);
+ bn_mod(v, v, n);
+ if (bn_cmp(v, c) == RLC_EQ) {
+ result = 1;
+ }
+ }
+ RLC_CATCH_ANY {
+ result = RLC_ERR;
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ bn_free(v);
+ ec_free(t);
+ }
+ return result;
+}
+
+int cp_pokor_prv(bn_t c[2], bn_t r[2], ec_t y[2], bn_t x) {
+ bn_t n, v[2], z;
+ ec_t t;
+ int l, result = RLC_OK;
+ uint8_t *buf, bin[6 * (RLC_FC_BYTES + 1)] = { 0 }, h[RLC_MD_LEN];
+
+ bn_null(n);
+ bn_null(v[0]);
+ bn_null(v[1]);
+ bn_null(z);
+ ec_null(t);
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(v[0]);
+ bn_new(v[1]);
+ bn_new(z);
+ ec_new(t);
+
+ buf = bin;
+ ec_curve_get_ord(n);
+ bn_rand_mod(c[0], n);
+
+ for (int i = 0; i < 2; i++) {
+ bn_rand_mod(v[i], n);
+ ec_curve_get_gen(t);
+ l = ec_size_bin(t, 1);
+ ec_write_bin(buf, l, t, 1);
+ buf += l;
+ l = ec_size_bin(y[i], 1);
+ ec_write_bin(buf, l, y[i], 1);
+ buf += l;
+
+ if (i == 0) {
+ /* T1 = [w]Y1 + [v1]G. */
+ ec_mul_sim_gen(t, v[i], y[i], c[i]);
+ } else {
+ /* T2 = [v2]G. */
+ ec_mul_gen(t, v[i]);
+ }
+ l = ec_size_bin(t, 1);
+ ec_write_bin(buf, l, t, 1);
+ buf += l;
+ }
+ md_map(h, bin, sizeof(bin));
+ bn_read_bin(z, h, RLC_MD_LEN);
+ bn_mod(z, z, n);
+
+ bn_sub(c[1], z, c[0]);
+ bn_mod(c[1], c[1], n);
+
+ bn_copy(r[0], v[0]);
+ bn_mul(r[1], c[1], x);
+ bn_sub(r[1], v[1], r[1]);
+ bn_mod(r[1], r[1], n);
+ }
+ RLC_CATCH_ANY {
+ result = RLC_ERR;
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ bn_free(v[0]);
+ bn_free(v[1]);
+ bn_free(z);
+ ec_free(t);
+ }
+ return result;
+}
+
+int cp_pokor_ver(bn_t c[2], bn_t r[2], ec_t y[2]) {
+ bn_t n, v[2], z;
+ ec_t t;
+ int l, result = 0;
+ uint8_t *buf, bin[6 * (RLC_FC_BYTES + 1)] = { 0 }, h[RLC_MD_LEN];
+
+ bn_null(n);
+ bn_null(v[0]);
+ bn_null(v[1]);
+ bn_null(z);
+ ec_null(t);
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(v[0]);
+ bn_new(v[1]);
+ bn_new(z);
+ ec_new(t);
+
+ buf = bin;
+ ec_curve_get_ord(n);
+
+ for (int i = 0; i < 2; i++) {
+ ec_curve_get_gen(t);
+ l = ec_size_bin(t, 1);
+ ec_write_bin(buf, l, t, 1);
+ buf += l;
+ l = ec_size_bin(y[i], 1);
+ ec_write_bin(buf, l, y[i], 1);
+ buf += l;
+
+ ec_mul_sim_gen(t, r[i], y[i], c[i]);
+ l = ec_size_bin(t, 1);
+ ec_write_bin(buf, l, t, 1);
+ buf += l;
+ }
+ md_map(h, bin, sizeof(bin));
+ bn_read_bin(z, h, RLC_MD_LEN);
+ bn_mod(z, z, n);
+
+ bn_sub(z, z, c[0]);
+ bn_sub(z, z, c[1]);
+ bn_mod(z, z, n);
+
+ if (bn_is_zero(z)) {
+ result = 1;
+ }
+ }
+ RLC_CATCH_ANY {
+ result = RLC_ERR;
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ bn_free(v[0]);
+ bn_free(v[1]);
+ bn_free(z);
+ ec_free(t);
+ }
+ return result;
+}
diff --git a/contrib/relic/src/cp/relic_cp_rabin.c b/contrib/relic/src/cp/relic_cp_rabin.c
index f47eaa1d3..d945f7eef 100644
--- a/contrib/relic/src/cp/relic_cp_rabin.c
+++ b/contrib/relic/src/cp/relic_cp_rabin.c
@@ -29,15 +29,7 @@
* @ingroup cp
*/
-#include
-
-#include "relic_core.h"
-#include "relic_conf.h"
-#include "relic_rand.h"
-#include "relic_bn.h"
-#include "relic_util.h"
-#include "relic_cp.h"
-#include "relic_md.h"
+#include "relic.h"
/*============================================================================*/
/* Private definitions */
diff --git a/contrib/relic/src/cp/relic_cp_rsa.c b/contrib/relic/src/cp/relic_cp_rsa.c
index 62749dbd8..e8e7a7ca9 100644
--- a/contrib/relic/src/cp/relic_cp_rsa.c
+++ b/contrib/relic/src/cp/relic_cp_rsa.c
@@ -29,16 +29,7 @@
* @ingroup cp
*/
-#include
-
-#include "relic_core.h"
-#include "relic_conf.h"
-#include "relic_rand.h"
-#include "relic_bn.h"
-#include "relic_util.h"
-#include "relic_cp.h"
-#include "relic_md.h"
-#include "relic_multi.h"
+#include "relic.h"
/*============================================================================*/
/* Private definitions */
@@ -274,10 +265,8 @@ static int pad_pkcs1(bn_t m, int *p_len, int m_len, int k_len, int operation) {
} while (pad == 0);
bn_add_dig(m, m, pad);
}
- bn_lsh(m, m, 8);
- bn_add_dig(m, m, 0);
- /* Make room for the real message. */
- bn_lsh(m, m, m_len * 8);
+ /* Make room for the zero and real message. */
+ bn_lsh(m, m, (m_len + 1) * 8);
result = RLC_OK;
break;
case RSA_DEC:
@@ -313,9 +302,8 @@ static int pad_pkcs1(bn_t m, int *p_len, int m_len, int k_len, int operation) {
bn_lsh(m, m, 8);
bn_add_dig(m, m, RSA_PAD);
}
- bn_lsh(m, m, 8);
- bn_add_dig(m, m, 0);
- bn_lsh(m, m, 8 * len);
+ /* Make room for the zero and hash id. */
+ bn_lsh(m, m, 8 * (len + 1));
bn_read_bin(t, id, len);
bn_add(m, m, t);
/* Make room for the real message. */
@@ -333,10 +321,8 @@ static int pad_pkcs1(bn_t m, int *p_len, int m_len, int k_len, int operation) {
bn_lsh(m, m, 8);
bn_add_dig(m, m, RSA_PAD);
}
- bn_lsh(m, m, 8);
- bn_add_dig(m, m, 0);
- /* Make room for the real message. */
- bn_lsh(m, m, m_len * 8);
+ /* Make room for the zero and hash. */
+ bn_lsh(m, m, 8 * (m_len + 1));
result = RLC_OK;
break;
case RSA_VER:
@@ -356,19 +342,22 @@ static int pad_pkcs1(bn_t m, int *p_len, int m_len, int k_len, int operation) {
} while (pad == RSA_PAD && m_len > 0);
/* Remove padding and trailing zero. */
id = hash_id(MD_MAP, &len);
- m_len -= len;
-
- bn_rsh(t, m, m_len * 8);
- int r = 0;
- for (int i = 0; i < len; i++) {
- pad = (uint8_t)t->dp[0];
- r |= pad ^ id[len - i - 1];
- bn_rsh(t, t, 8);
- }
- *p_len = k_len - m_len;
- bn_mod_2b(m, m, m_len * 8);
- if (r == 0 && m_len > 0 && counter >= 8) {
- result = RLC_OK;
+ bn_rsh(t, m, 8 * m_len);
+ bn_mod_2b(t, t, 8);
+ if (bn_is_zero(t)) {
+ m_len -= len;
+ bn_rsh(t, m, 8 * m_len);
+ int r = 0;
+ for (int i = 0; i < len; i++) {
+ pad = (uint8_t)t->dp[0];
+ r |= pad ^ id[len - i - 1];
+ bn_rsh(t, t, 8);
+ }
+ *p_len = k_len - m_len;
+ bn_mod_2b(m, m, m_len * 8);
+ if (r == 0 && m_len == RLC_MD_LEN && counter >= 8) {
+ result = RLC_OK;
+ }
}
}
}
@@ -390,9 +379,13 @@ static int pad_pkcs1(bn_t m, int *p_len, int m_len, int k_len, int operation) {
} while (pad == RSA_PAD && m_len > 0);
/* Remove padding and trailing zero. */
*p_len = k_len - m_len;
- bn_mod_2b(m, m, m_len * 8);
- if (m_len > 0 && counter >= 8) {
- result = RLC_OK;
+ bn_rsh(t, m, 8 * m_len);
+ bn_mod_2b(t, t, 8);
+ if (bn_is_zero(t)) {
+ bn_mod_2b(m, m, m_len * 8);
+ if (m_len == RLC_MD_LEN && counter >= 8) {
+ result = RLC_OK;
+ }
}
}
}
diff --git a/contrib/relic/src/cp/relic_cp_smlers.c b/contrib/relic/src/cp/relic_cp_smlers.c
new file mode 100644
index 000000000..6dbe0b1cb
--- /dev/null
+++ b/contrib/relic/src/cp/relic_cp_smlers.c
@@ -0,0 +1,187 @@
+/*
+ * RELIC is an Efficient LIbrary for Cryptography
+ * Copyright (c) 2021 RELIC Authors
+ *
+ * This file is part of RELIC. RELIC is legal property of its developsmlers,
+ * 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 vsmlersion 2.1 (or later) of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; or vsmlersion 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 extendable ring signatures.
+ *
+ * @ingroup cp
+ */
+
+#include "relic.h"
+
+/*============================================================================*/
+/* Public definitions */
+/*============================================================================*/
+
+int cp_smlers_sig(bn_t td, smlers_t p, uint8_t *msg, int len, bn_t sk, ec_t pk,
+ ec_t pp) {
+ ec_t g[2], y[2];
+ int result = RLC_OK;
+
+ ec_null(g[0]);
+ ec_null(g[1]);
+ ec_null(y[0]);
+ ec_null(y[1]);
+
+ RLC_TRY {
+ ec_new(g[0]);
+ ec_new(g[1]);
+ ec_new(y[0]);
+ ec_new(y[1]);
+
+ ec_curve_get_gen(g[0]);
+ ec_map(g[1], msg, len);
+ ec_mul(p->tau, g[1], sk);
+
+ cp_ers_sig(td, p->sig, msg, len, sk, pk, pp);
+
+ ec_copy(y[0], p->sig->h);
+ ec_copy(y[1], p->tau);
+ cp_sokor_sig(p->c, p->r, msg, len, y, g, sk, 0);
+ }
+ RLC_CATCH_ANY {
+ result = RLC_ERR;
+ }
+ RLC_FINALLY {
+ ec_free(g[0]);
+ ec_free(g[1]);
+ ec_free(y[0]);
+ ec_free(y[1]);
+ }
+ return result;
+}
+
+int cp_smlers_ver(bn_t td, smlers_t *s, int size, uint8_t *msg, int len, ec_t pp) {
+ bn_t n;
+ ec_t t, g[2], y[2];
+ int flag = 0, result = 0;
+
+ bn_null(n);
+ ec_null(t);
+ ec_null(g[0]);
+ ec_null(g[1]);
+ ec_null(y[0]);
+ ec_null(y[1]);
+
+ RLC_TRY {
+ bn_new(n);
+ ec_new(t);
+ ec_new(g[0]);
+ ec_new(g[1]);
+ ec_new(y[0]);
+ ec_new(y[1]);
+
+ ec_curve_get_ord(n);
+ ec_mul_gen(t, td);
+ ec_curve_get_gen(g[0]);
+ ec_map(g[1], msg, len);
+
+ for (int i = 0; i < size; i++) {
+ ec_add(t, t, s[i]->sig->h);
+ }
+ if (ec_cmp(pp, t) == RLC_EQ) {
+ flag = 1;
+ for (int i = 0; i < size; i++) {
+ ec_copy(y[0], s[i]->sig->h);
+ ec_copy(y[1], s[i]->sig->pk);
+ flag &= cp_sokor_ver(s[i]->sig->c, s[i]->sig->r, msg, len, y, NULL);
+ ec_copy(y[1], s[i]->tau);
+ flag &= cp_sokor_ver(s[i]->c, s[i]->r, msg, len, y, g);
+ }
+ }
+ result = flag;
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ ec_free(t);
+ ec_free(g[0]);
+ ec_free(g[1]);
+ ec_free(y[0]);
+ ec_free(y[1]);
+ }
+ return result;
+}
+
+int cp_smlers_ext(bn_t td, smlers_t *p, int *size, uint8_t *msg, int len, ec_t pk,
+ ec_t pp) {
+ bn_t n, r;
+ ec_t g[2], y[2];
+ int result = RLC_OK;
+
+ bn_null(n);
+ bn_null(r);
+ ec_null(g[0]);
+ ec_null(g[1]);
+ ec_null(y[0]);
+ ec_null(y[1]);
+
+ for (int i = 0; i < *size; i++) {
+ if (ec_cmp(pk, p[i]->sig->pk) == RLC_EQ) {
+ return RLC_ERR;
+ }
+ }
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(r);
+ ec_new(g[0]);
+ ec_new(g[1]);
+ ec_new(y[0]);
+ ec_new(y[1]);
+
+ ec_curve_get_ord(n);
+ bn_rand_mod(r, n);
+ bn_sub(td, td, r);
+ bn_mod(td, td, n);
+ ec_mul_gen(p[*size]->sig->h, r);
+ ec_curve_get_gen(g[0]);
+ ec_map(g[1], msg, len);
+
+ ec_copy(p[*size]->sig->pk, pk);
+ ec_copy(y[0], p[*size]->sig->h);
+ ec_copy(y[1], p[*size]->sig->pk);
+ cp_sokor_sig(p[*size]->sig->c, p[*size]->sig->r, msg, len, y, NULL, r, 1);
+ ec_copy(p[*size]->tau, p[*size - 1]->tau);
+ ec_copy(y[1], p[*size]->tau);
+ cp_sokor_sig(p[*size]->c, p[*size]->r, msg, len, y, g, r, 1);
+ (*size)++;
+ result = RLC_OK;
+ }
+ RLC_CATCH_ANY {
+ result = RLC_ERR;
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ bn_free(r);
+ ec_free(g[0]);
+ ec_free(g[1]);
+ ec_free(y[0]);
+ ec_free(y[1]);
+ }
+ return result;
+}
diff --git a/contrib/relic/src/cp/relic_cp_sok.c b/contrib/relic/src/cp/relic_cp_sok.c
new file mode 100644
index 000000000..0713910f0
--- /dev/null
+++ b/contrib/relic/src/cp/relic_cp_sok.c
@@ -0,0 +1,333 @@
+/*
+ * RELIC is an Efficient LIbrary for Cryptography
+ * Copyright (c) 2021 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 protocols for proof of knowledge of discrete logarithms.
+ *
+ * @ingroup cp
+ */
+
+#include "relic.h"
+
+/*============================================================================*/
+/* Public definitions */
+/*============================================================================*/
+
+/*
+ * Source: "Efficient Group Signature for Large Groups"
+ * Authors: Jan Camenisch, Markus Stadler
+ */
+
+int cp_sokdl_sig(bn_t c, bn_t s, uint8_t *msg, int len, ec_t y, bn_t x) {
+ bn_t n, r;
+ ec_t t;
+ uint8_t h[RLC_MD_LEN];
+ uint8_t *buf, *m = RLC_ALLOCA(uint8_t, len + 3 * (RLC_FC_BYTES + 1));
+ int l, result = RLC_OK;
+
+ bn_null(n);
+ bn_null(r);
+ ec_null(t);
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(r);
+ ec_new(t);
+ if (m == NULL) {
+ RLC_THROW(ERR_NO_MEMORY);
+ }
+
+ buf = m;
+ ec_curve_get_ord(n);
+ ec_curve_get_gen(t);
+ memcpy(buf, msg, len);
+ buf += len;
+ l = ec_size_bin(t, 1);
+ ec_write_bin(buf, l, t, 1);
+ buf += l;
+ l = ec_size_bin(y, 1);
+ ec_write_bin(buf, l, y, 1);
+ buf += l;
+
+ bn_rand_mod(r, n);
+ ec_mul_gen(t, r);
+ l = ec_size_bin(t, 1);
+ ec_write_bin(buf, l, t, 1);
+ buf += l;
+
+ md_map(h, m, len + 3 * (RLC_FC_BYTES + 1));
+ bn_read_bin(c, h, RLC_MD_LEN);
+ bn_mod(c, c, n);
+
+ bn_mul(s, c, x);
+ bn_sub(s, r, s);
+ bn_mod(s, s, n);
+ }
+ RLC_CATCH_ANY {
+ result = RLC_ERR;
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ bn_free(r);
+ ec_free(t);
+ RLC_FREE(m);
+ }
+ return result;
+}
+
+int cp_sokdl_ver(bn_t c, bn_t s, uint8_t *msg, int len, ec_t y) {
+ bn_t n, v;
+ ec_t t;
+ uint8_t h[RLC_MD_LEN];
+ uint8_t *buf, *m = RLC_ALLOCA(uint8_t, len + 3 * (RLC_FC_BYTES + 1));
+ int l, result = 0;
+
+ bn_null(n);
+ bn_null(v);
+ ec_null(t);
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(v);
+ ec_new(t);
+ if (m == NULL) {
+ RLC_THROW(ERR_NO_MEMORY);
+ }
+
+ buf = m;
+ ec_curve_get_ord(n);
+ ec_curve_get_gen(t);
+ memcpy(buf, msg, len);
+ buf += len;
+ l = ec_size_bin(t, 1);
+ ec_write_bin(buf, l, t, 1);
+ buf += l;
+ l = ec_size_bin(y, 1);
+ ec_write_bin(buf, l, y, 1);
+ buf += l;
+
+ /* Compute t' = [r]G + [c]Y. */
+ ec_mul_sim_gen(t, s, y, c);
+ l = ec_size_bin(t, 1);
+ ec_write_bin(buf, l, t, 1);
+
+ md_map(h, m, len + 3 * (RLC_FC_BYTES + 1));
+ bn_read_bin(v, h, RLC_MD_LEN);
+ bn_mod(v, v, n);
+
+ if (bn_cmp(v, c) == RLC_EQ) {
+ result = 1;
+ }
+ }
+ RLC_CATCH_ANY {
+ result = RLC_ERR;
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ bn_free(v);
+ ec_free(t);
+ RLC_FREE(m);
+ }
+ return result;
+}
+
+int cp_sokor_sig(bn_t c[2], bn_t s[2], uint8_t *msg, int len, ec_t y[2],
+ ec_t g[2], bn_t x, int first) {
+ bn_t n, v[2], z;
+ ec_t u, t[2];
+ uint8_t h[RLC_MD_LEN];
+ uint8_t *buf, *m = RLC_ALLOCA(uint8_t, len + 6 * (RLC_FC_BYTES + 1));
+ int l, result = RLC_OK;
+ int one = 1 ^ first;
+ int zero = 0 ^ first;
+
+ bn_null(n);
+ bn_null(v[0]);
+ bn_null(v[1]);
+ bn_null(z);
+ ec_null(u);
+ ec_null(t[0]);
+ ec_null(t[1]);
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(v[0]);
+ bn_new(v[1]);
+ bn_new(z);
+ ec_new(u);
+ ec_new(t[0]);
+ ec_new(t[1]);
+ if (m == NULL) {
+ RLC_THROW(ERR_NO_MEMORY);
+ }
+
+ buf = m;
+ ec_curve_get_ord(n);
+ bn_rand_mod(c[zero], n);
+ memcpy(buf, msg, len);
+ buf += len;
+
+ bn_rand_mod(v[0], n);
+ bn_rand_mod(v[1], n);
+ if (first) {
+ if (g != NULL) {
+ ec_mul(t[0], g[0], v[0]);
+ ec_mul_sim(t[1], g[1], v[1], y[1], c[zero]);
+ } else {
+ ec_mul_gen(t[0], v[0]);
+ ec_mul_sim_gen(t[1], v[1], y[1], c[zero]);
+ }
+ } else {
+ if (g != NULL) {
+ /* T1 = [w]Y1 + [v1]G. */
+ ec_mul_sim(t[0], g[0], v[0], y[0], c[zero]);
+ /* T2 = [v2]G. */
+ ec_mul(t[1], g[1], v[1]);
+ } else {
+ /* T1 = [w]Y1 + [v1]G. */
+ ec_mul_sim_gen(t[0], v[0], y[0], c[zero]);
+ /* T2 = [v2]G. */
+ ec_mul_gen(t[1], v[1]);
+ }
+ }
+
+ ec_curve_get_gen(u);
+ for (int i = 0; i < 2; i++) {
+ if (g != NULL) {
+ ec_copy(u, g[i]);
+ }
+ l = ec_size_bin(u, 1);
+ ec_write_bin(buf, l, u, 1);
+ buf += l;
+ l = ec_size_bin(y[i], 1);
+ ec_write_bin(buf, l, y[i], 1);
+ buf += l;
+ l = ec_size_bin(t[i], 1);
+ ec_write_bin(buf, l, t[i], 1);
+ buf += l;
+ }
+ md_map(h, m, len + 6 * (RLC_FC_BYTES + 1));
+ bn_read_bin(z, h, RLC_MD_LEN);
+ bn_mod(z, z, n);
+
+ bn_sub(c[one], z, c[zero]);
+ bn_mod(c[one], c[one], n);
+
+ bn_copy(s[zero], v[zero]);
+ bn_mul(s[one], c[one], x);
+ bn_sub(s[one], v[one], s[one]);
+ bn_mod(s[one], s[one], n);
+ }
+ RLC_CATCH_ANY {
+ result = RLC_ERR;
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ bn_free(v[0]);
+ bn_free(v[1]);
+ bn_free(z);
+ ec_free(u);
+ ec_free(t[0]);
+ ec_free(t[1]);
+ RLC_FREE(m);
+ }
+ return result;
+}
+
+int cp_sokor_ver(bn_t c[2], bn_t s[2], uint8_t *msg, int len, ec_t y[2],
+ ec_t g[2]) {
+ bn_t n, v[2], z;
+ ec_t t;
+ uint8_t h[RLC_MD_LEN];
+ uint8_t *buf, *m = RLC_ALLOCA(uint8_t, len + 6 * (RLC_FC_BYTES + 1));
+ int l, result = 0;
+
+ bn_null(n);
+ bn_null(v[0]);
+ bn_null(v[1]);
+ bn_null(z);
+ ec_null(t);
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(v[0]);
+ bn_new(v[1]);
+ bn_new(z);
+ ec_new(t);
+ if (m == NULL) {
+ RLC_THROW(ERR_NO_MEMORY);
+ }
+
+ buf = m;
+ ec_curve_get_ord(n);
+ memcpy(buf, msg, len);
+ buf += len;
+
+ for (int i = 0; i < 2; i++) {
+ if (g != NULL) {
+ ec_copy(t, g[i]);
+ } else {
+ ec_curve_get_gen(t);
+ }
+ l = ec_size_bin(t, 1);
+ ec_write_bin(buf, l, t, 1);
+ buf += l;
+ l = ec_size_bin(y[i], 1);
+ ec_write_bin(buf, l, y[i], 1);
+ buf += l;
+ if (g != NULL) {
+ ec_mul_sim(t, g[i], s[i], y[i], c[i]);
+ } else {
+ ec_mul_sim_gen(t, s[i], y[i], c[i]);
+ }
+ l = ec_size_bin(t, 1);
+ ec_write_bin(buf, l, t, 1);
+ buf += l;
+ }
+ md_map(h, m, len + 6 * (RLC_FC_BYTES + 1));
+ bn_read_bin(z, h, RLC_MD_LEN);
+ bn_mod(z, z, n);
+
+ bn_sub(z, z, c[0]);
+ bn_sub(z, z, c[1]);
+ bn_mod(z, z, n);
+
+ if (bn_is_zero(z)) {
+ result = 1;
+ }
+ }
+ RLC_CATCH_ANY {
+ result = RLC_ERR;
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ bn_free(v[0]);
+ bn_free(v[1]);
+ bn_free(z);
+ ec_free(t);
+ RLC_FREE(m);
+ }
+ return result;
+}
diff --git a/contrib/relic/src/cp/relic_cp_sokaka.c b/contrib/relic/src/cp/relic_cp_sokaka.c
index 03ecd1bb8..303fab912 100644
--- a/contrib/relic/src/cp/relic_cp_sokaka.c
+++ b/contrib/relic/src/cp/relic_cp_sokaka.c
@@ -30,15 +30,7 @@
* @ingroup test
*/
-#include
-#include
-#include
-#include
-#include
-
#include "relic.h"
-#include "relic_test.h"
-#include "relic_bench.h"
/*============================================================================*/
/* Public definitions */
diff --git a/contrib/relic/src/cp/relic_cp_vbnn.c b/contrib/relic/src/cp/relic_cp_vbnn.c
index a07dac6bd..c904d0f85 100644
--- a/contrib/relic/src/cp/relic_cp_vbnn.c
+++ b/contrib/relic/src/cp/relic_cp_vbnn.c
@@ -33,8 +33,6 @@
*/
#include "relic.h"
-#include "relic_test.h"
-#include "relic_bench.h"
/*============================================================================*/
/* Public definitions */
@@ -216,7 +214,7 @@ int cp_vbnn_ver(ec_t r, bn_t z, bn_t h, uint8_t *id, int id_len,
if (buf == NULL) {
RLC_THROW(ERR_NO_MEMORY);
}
-
+
/* get order of ECC group */
ec_curve_get_ord(n);
diff --git a/contrib/relic/src/cp/relic_cp_zss.c b/contrib/relic/src/cp/relic_cp_zss.c
index 9f16d967d..2e0e70920 100644
--- a/contrib/relic/src/cp/relic_cp_zss.c
+++ b/contrib/relic/src/cp/relic_cp_zss.c
@@ -31,8 +31,6 @@
*/
#include "relic.h"
-#include "relic_test.h"
-#include "relic_bench.h"
/*============================================================================*/
/* Public definitions */
diff --git a/contrib/relic/src/dv/relic_dv_util.c b/contrib/relic/src/dv/relic_dv_util.c
index 9ecb043f1..d5329da35 100644
--- a/contrib/relic/src/dv/relic_dv_util.c
+++ b/contrib/relic/src/dv/relic_dv_util.c
@@ -109,7 +109,7 @@ int dv_cmp(const dig_t *a, const dig_t *b, int size) {
}
int dv_cmp_const(const dig_t *a, const dig_t *b, int size) {
- int r = 0;
+ dig_t r = 0;
for (int i = 0; i < size; i++) {
r |= a[i] ^ b[i];
diff --git a/contrib/relic/src/eb/relic_eb_curve.c b/contrib/relic/src/eb/relic_eb_curve.c
index 2fe6228e0..9d829d824 100644
--- a/contrib/relic/src/eb/relic_eb_curve.c
+++ b/contrib/relic/src/eb/relic_eb_curve.c
@@ -73,8 +73,8 @@ void eb_curve_init(void) {
fb_zero(ctx->eb_g.x);
fb_zero(ctx->eb_g.y);
fb_zero(ctx->eb_g.z);
- bn_init(&(ctx->eb_r), RLC_FB_DIGS);
- bn_init(&(ctx->eb_h), RLC_FB_DIGS);
+ bn_make(&(ctx->eb_r), RLC_FB_DIGS);
+ bn_make(&(ctx->eb_h), RLC_FB_DIGS);
}
void eb_curve_clean(void) {
diff --git a/contrib/relic/src/eb/relic_eb_mul.c b/contrib/relic/src/eb/relic_eb_mul.c
index 1bab3c82d..cd3cdb02c 100644
--- a/contrib/relic/src/eb/relic_eb_mul.c
+++ b/contrib/relic/src/eb/relic_eb_mul.c
@@ -890,7 +890,7 @@ void eb_mul_rwnaf(eb_t r, const eb_t p, const bn_t k) {
void eb_mul_halve(eb_t r, const eb_t p, const bn_t k) {
int i, j, l, trc, cof;
- int8_t naf[RLC_FB_BITS + 1] = { 0 }, *_k;
+ int8_t naf[RLC_FB_BITS + 1], *_k;
eb_t q, s, t[1 << (EB_WIDTH - 2)];
bn_t n, m;
fb_t u, v, w, z;
@@ -937,9 +937,6 @@ void eb_mul_halve(eb_t r, const eb_t p, const bn_t k) {
l = sizeof(naf);
bn_rec_naf(naf, &l, m, EB_WIDTH);
- for (i = l; i <= bn_bits(n); i++) {
- naf[i] = 0;
- }
if (naf[bn_bits(n)] == 1) {
eb_dbl(t[0], p);
}
diff --git a/contrib/relic/src/eb/relic_eb_mul_sim.c b/contrib/relic/src/eb/relic_eb_mul_sim.c
index 947bb981d..31d878ea8 100644
--- a/contrib/relic/src/eb/relic_eb_mul_sim.c
+++ b/contrib/relic/src/eb/relic_eb_mul_sim.c
@@ -222,13 +222,6 @@ static void eb_mul_sim_plain(eb_t r, const eb_t p, const bn_t k, const eb_t q,
bn_rec_naf(naf1, &l1, m, EB_WIDTH);
l = RLC_MAX(l0, l1);
- for (i = l0; i < l; i++) {
- naf0[i] = 0;
- }
- for (i = l1; i < l; i++) {
- naf1[i] = 0;
- }
-
if (bn_sign(k) == RLC_NEG) {
for (i = 0; i < l0; i++) {
naf0[i] = -naf0[i];
diff --git a/contrib/relic/src/eb/relic_eb_norm.c b/contrib/relic/src/eb/relic_eb_norm.c
index 7ddce052a..9f0e38681 100644
--- a/contrib/relic/src/eb/relic_eb_norm.c
+++ b/contrib/relic/src/eb/relic_eb_norm.c
@@ -135,10 +135,11 @@ void eb_norm_sim(eb_t *r, const eb_t *t, int n) {
fb_copy(r[i]->z, a[i]);
}
}
-
+#if EB_ADD == PROJC || !defined(STRIP)
for (int i = 0; i < n; i++) {
eb_norm_imp(r[i], r[i], 1);
}
+#endif /* EB_ADD == PROJC */
}
RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
diff --git a/contrib/relic/src/eb/relic_eb_util.c b/contrib/relic/src/eb/relic_eb_util.c
index 942366352..0671fbb0e 100644
--- a/contrib/relic/src/eb/relic_eb_util.c
+++ b/contrib/relic/src/eb/relic_eb_util.c
@@ -543,6 +543,11 @@ void eb_read_bin(eb_t a, const uint8_t *bin, int len) {
return;
}
}
+
+ if (!eb_on_curve(a)) {
+ RLC_THROW(ERR_NO_VALID);
+ return;
+ }
}
void eb_write_bin(uint8_t *bin, int len, const eb_t a, int pack) {
@@ -550,12 +555,13 @@ void eb_write_bin(uint8_t *bin, int len, const eb_t a, int pack) {
eb_null(t);
+ memset(bin, 0, len);
+
if (eb_is_infty(a)) {
if (len < 1) {
RLC_THROW(ERR_NO_BUFFER);
return;
} else {
- bin[0] = 0;
return;
}
}
diff --git a/contrib/relic/src/ed/relic_ed_add.c b/contrib/relic/src/ed/relic_ed_add.c
index 9e4fd2d17..2bfee3f50 100644
--- a/contrib/relic/src/ed/relic_ed_add.c
+++ b/contrib/relic/src/ed/relic_ed_add.c
@@ -281,7 +281,7 @@ void ed_add_extnd(ed_t r, const ed_t p, const ed_t q) {
fp_mul(r->t, t2, r->z);
fp_mul(r->z, t3, t4);
- r->coord = PROJC;
+ r->coord = EXTND;
} RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT)
} RLC_FINALLY {
diff --git a/contrib/relic/src/ed/relic_ed_curve.c b/contrib/relic/src/ed/relic_ed_curve.c
index 0c4153bc5..0e1550e89 100644
--- a/contrib/relic/src/ed/relic_ed_curve.c
+++ b/contrib/relic/src/ed/relic_ed_curve.c
@@ -40,8 +40,8 @@ void ed_curve_init(void) {
}
#endif
ed_set_infty(&ctx->ed_g);
- bn_init(&ctx->ed_r, RLC_FP_DIGS);
- bn_init(&ctx->ed_h, RLC_FP_DIGS);
+ bn_make(&ctx->ed_r, RLC_FP_DIGS);
+ bn_make(&ctx->ed_h, RLC_FP_DIGS);
}
void ed_curve_clean(void) {
diff --git a/contrib/relic/src/ed/relic_ed_dbl.c b/contrib/relic/src/ed/relic_ed_dbl.c
index 4a41a6a50..e62ecfe53 100644
--- a/contrib/relic/src/ed/relic_ed_dbl.c
+++ b/contrib/relic/src/ed/relic_ed_dbl.c
@@ -184,6 +184,8 @@ void ed_dbl_extnd(ed_t r, const ed_t p) {
// efd: dbl-2008-hwcd, rfc edition
// 4M + 4S + 1D + 7add
+ r->coord = PROJC;
+
/* A = X^2, B = Y^2 */
fp_sqr(t0, p->x);
fp_sqr(t1, p->y);
@@ -213,11 +215,10 @@ void ed_dbl_extnd(ed_t r, const ed_t p) {
if (r->coord != EXTND) {
/* T = E * H */
fp_mul(r->t, t2, r->z);
+ r->coord = EXTND;
}
/* Z = F * G */
fp_mul(r->z, t3, t4);
-
- r->coord = PROJC;
} RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
} RLC_FINALLY {
diff --git a/contrib/relic/src/ed/relic_ed_mul.c b/contrib/relic/src/ed/relic_ed_mul.c
index 09a17e7e0..725401590 100644
--- a/contrib/relic/src/ed/relic_ed_mul.c
+++ b/contrib/relic/src/ed/relic_ed_mul.c
@@ -406,27 +406,37 @@ void ed_mul_gen(ed_t r, const bn_t k) {
}
void ed_mul_dig(ed_t r, const ed_t p, dig_t k) {
- int i, l;
ed_t t;
+ bn_t _k;
+ int8_t u, naf[RLC_DIG + 1];
+ int l;
ed_null(t);
+ bn_null(_k);
- if (k == 0) {
+ if (k == 0 || ed_is_infty(p)) {
ed_set_infty(r);
return;
}
RLC_TRY {
ed_new(t);
+ bn_new(_k);
- l = util_bits_dig(k);
+ bn_set_dig(_k, k);
- ed_copy(t, p);
+ l = RLC_DIG + 1;
+ bn_rec_naf(naf, &l, _k, 2);
- for (i = l - 2; i >= 0; i--) {
+ ed_set_infty(t);
+ for (int i = l - 1; i >= 0; i--) {
ed_dbl(t, t);
- if (k & ((dig_t)1 << i)) {
+
+ u = naf[i];
+ if (u > 0) {
ed_add(t, t, p);
+ } else if (u < 0) {
+ ed_sub(t, t, p);
}
}
@@ -437,5 +447,6 @@ void ed_mul_dig(ed_t r, const ed_t p, dig_t k) {
}
RLC_FINALLY {
ed_free(t);
+ bn_free(_k);
}
}
diff --git a/contrib/relic/src/ed/relic_ed_mul_sim.c b/contrib/relic/src/ed/relic_ed_mul_sim.c
index acbc8e14c..b9b70410e 100644
--- a/contrib/relic/src/ed/relic_ed_mul_sim.c
+++ b/contrib/relic/src/ed/relic_ed_mul_sim.c
@@ -88,13 +88,6 @@ static void ed_mul_sim_plain(ed_t r, const ed_t p, const bn_t k, const ed_t q,
bn_rec_naf(naf1, &l1, m, ED_WIDTH);
l = RLC_MAX(l0, l1);
- for (i = l0; i < l; i++) {
- naf0[i] = 0;
- }
- for (i = l1; i < l; i++) {
- naf1[i] = 0;
- }
-
if (bn_sign(k) == RLC_NEG) {
for (i = 0; i < l0; i++) {
naf0[i] = -naf0[i];
diff --git a/contrib/relic/src/ed/relic_ed_norm.c b/contrib/relic/src/ed/relic_ed_norm.c
index cc06c42aa..8979df0cc 100644
--- a/contrib/relic/src/ed/relic_ed_norm.c
+++ b/contrib/relic/src/ed/relic_ed_norm.c
@@ -37,8 +37,6 @@
#if ED_ADD == PROJC || ED_ADD == EXTND || !defined(STRIP)
-#include "assert.h"
-
/**
* Normalizes a point represented in projective coordinates.
*
@@ -111,9 +109,11 @@ void ed_norm_sim(ed_t *r, const ed_t *t, int n) {
}
}
+#if ED_ADD == PROJC || ED_ADD == EXTND || !defined(STRIP)
for (int i = 0; i < n; i++) {
ed_norm_imp(r[i], r[i], 1);
}
+#endif /* ED_ADD != BASIC*/
}
RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
diff --git a/contrib/relic/src/ed/relic_ed_util.c b/contrib/relic/src/ed/relic_ed_util.c
index c43fbaf41..55c3d68d5 100644
--- a/contrib/relic/src/ed/relic_ed_util.c
+++ b/contrib/relic/src/ed/relic_ed_util.c
@@ -122,12 +122,16 @@ void ed_blind(ed_t r, const ed_t p) {
RLC_TRY {
fp_new(rand);
-
fp_rand(rand);
+#if ED_ADD == BASIC
+ (void)rand;
+ ed_copy(r, p);
+#elif ED_ADD == PROJC || ED_ADD == EXTND
fp_mul(r->x, p->x, rand);
fp_mul(r->y, p->y, rand);
fp_mul(r->z, p->z, rand);
r->coord = PROJC;
+#endif
#if ED_ADD == EXTND
fp_mul(r->t, p->t, rand);
#endif
@@ -287,6 +291,10 @@ void ed_read_bin(ed_t a, const uint8_t *bin, int len) {
fp_mul(a->y, a->y, a->z);
fp_sqr(a->z, a->z);
#endif
+
+ if (!ed_on_curve(a)) {
+ RLC_THROW(ERR_NO_VALID);
+ }
}
void ed_write_bin(uint8_t *bin, int len, const ed_t a, int pack) {
@@ -294,12 +302,13 @@ void ed_write_bin(uint8_t *bin, int len, const ed_t a, int pack) {
ed_null(t);
+ memset(bin, 0, len);
+
if (ed_is_infty(a)) {
if (len < 1) {
RLC_THROW(ERR_NO_BUFFER);
return;
} else {
- bin[0] = 0;
return;
}
}
@@ -310,7 +319,7 @@ void ed_write_bin(uint8_t *bin, int len, const ed_t a, int pack) {
ed_norm(t, a);
if (pack) {
- if (len != RLC_FP_BYTES + 1) {
+ if (len < RLC_FP_BYTES + 1) {
RLC_THROW(ERR_NO_BUFFER);
} else {
ed_pck(t, t);
@@ -318,7 +327,7 @@ void ed_write_bin(uint8_t *bin, int len, const ed_t a, int pack) {
fp_write_bin(bin + 1, RLC_FP_BYTES, t->y);
}
} else {
- if (len != 2 * RLC_FP_BYTES + 1) {
+ if (len < 2 * RLC_FP_BYTES + 1) {
RLC_THROW(ERR_NO_BUFFER);
} else {
bin[0] = 4;
@@ -326,8 +335,7 @@ void ed_write_bin(uint8_t *bin, int len, const ed_t a, int pack) {
fp_write_bin(bin + RLC_FP_BYTES + 1, RLC_FP_BYTES, t->x);
}
}
- }
- RLC_CATCH_ANY {
+ } RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
}
RLC_FINALLY {
diff --git a/contrib/relic/src/ep/relic_ep_curve.c b/contrib/relic/src/ep/relic_ep_curve.c
index b4e21c577..f4aa0f329 100644
--- a/contrib/relic/src/ep/relic_ep_curve.c
+++ b/contrib/relic/src/ep/relic_ep_curve.c
@@ -209,12 +209,12 @@ void ep_curve_init(void) {
}
#endif
ep_set_infty(&ctx->ep_g);
- bn_init(&ctx->ep_r, RLC_FP_DIGS);
- bn_init(&ctx->ep_h, RLC_FP_DIGS);
+ bn_make(&ctx->ep_r, RLC_FP_DIGS);
+ bn_make(&ctx->ep_h, RLC_FP_DIGS);
#if defined(EP_ENDOM) && (EP_MUL == LWNAF || EP_FIX == COMBS || EP_FIX == LWNAF || !defined(STRIP))
for (int i = 0; i < 3; i++) {
- bn_init(&(ctx->ep_v1[i]), RLC_FP_DIGS);
- bn_init(&(ctx->ep_v2[i]), RLC_FP_DIGS);
+ bn_make(&(ctx->ep_v1[i]), RLC_FP_DIGS);
+ bn_make(&(ctx->ep_v2[i]), RLC_FP_DIGS);
}
#endif
}
diff --git a/contrib/relic/src/ep/relic_ep_dbl.c b/contrib/relic/src/ep/relic_ep_dbl.c
index 66369fdb2..1a160d02c 100644
--- a/contrib/relic/src/ep/relic_ep_dbl.c
+++ b/contrib/relic/src/ep/relic_ep_dbl.c
@@ -513,10 +513,6 @@ void ep_dbl_projc(ep_t r, const ep_t p) {
return;
}
- if (fp_is_zero(p->x)) {
- ep_set_infty(r);
- return;
- }
ep_dbl_projc_imp(r, p);
}
@@ -530,10 +526,6 @@ void ep_dbl_jacob(ep_t r, const ep_t p) {
return;
}
- if (fp_is_zero(p->x)) {
- ep_set_infty(r);
- return;
- }
ep_dbl_jacob_imp(r, p);
}
diff --git a/contrib/relic/src/ep/relic_ep_map.c b/contrib/relic/src/ep/relic_ep_map.c
index a2fa26b8b..10c2c57ad 100644
--- a/contrib/relic/src/ep/relic_ep_map.c
+++ b/contrib/relic/src/ep/relic_ep_map.c
@@ -49,27 +49,23 @@
* @param[in] deg - the degree of the polynomial.
*/
TMPL_MAP_HORNER(fp, fp_st)
-
/**
* Generic isogeny map evaluation for use with SSWU map.
*/
-TMPL_MAP_ISOGENY_MAP(ep, fp, iso)
+ TMPL_MAP_ISOGENY_MAP(ep, fp, iso)
#endif /* EP_CTMAP */
-
/**
* Simplified SWU mapping from Section 4 of
* "Fast and simple constant-time hashing to the BLS12-381 Elliptic Curve"
*/
#define EP_MAP_COPY_COND(O, I, C) dv_copy_cond(O, I, RLC_FP_DIGS, C)
-TMPL_MAP_SSWU(ep, fp, dig_t, EP_MAP_COPY_COND)
-
+ TMPL_MAP_SSWU(ep, fp, dig_t, EP_MAP_COPY_COND)
/**
* Shallue--van de Woestijne map, based on the definition from
* draft-irtf-cfrg-hash-to-curve-06, Section 6.6.1
*/
TMPL_MAP_SVDW(ep, fp, dig_t, EP_MAP_COPY_COND)
#undef EP_MAP_COPY_COND
-
/* caution: this function overwrites k, which it uses as an auxiliary variable */
static inline int fp_sgn0(const fp_t t, bn_t k) {
fp_prime_back(k, t);
@@ -80,51 +76,50 @@ static inline int fp_sgn0(const fp_t t, bn_t k) {
/* Public definitions */
/*============================================================================*/
-void ep_map_dst(ep_t p, const uint8_t *msg, int len, const uint8_t *dst, int dst_len) {
+void ep_map_from_field(ep_t p, const uint8_t *uniform_bytes, int len) {
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;
- uint8_t *pseudo_random_bytes = RLC_ALLOCA(uint8_t, 2 * len_per_elm);
bn_null(k);
fp_null(t);
ep_null(q);
RLC_TRY {
+ if (len != 2 * len_per_elm) {
+ RLC_THROW(ERR_NO_VALID);
+ }
+
bn_new(k);
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;
-
- /* 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);
-
-#define EP_MAP_CONVERT_BYTES(IDX) \
- do { \
- bn_read_bin(k, pseudo_random_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)
+ 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)
+
+#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)
/* first map invocation */
EP_MAP_CONVERT_BYTES(0);
@@ -152,6 +147,7 @@ void ep_map_dst(ep_t p, const uint8_t *msg, int len, const uint8_t *dst, int dst
/* h = 1 */
break;
case EP_B12:
+ case EP_B24:
/* multiply by 1-x (x the BLS parameter) to get the correct group. */
/* XXX(rsw) is this guaranteed to work? It could fail if one
* of the prime-squared subgroups is cyclic, but
@@ -183,6 +179,28 @@ void ep_map_dst(ep_t p, const uint8_t *msg, int len, const uint8_t *dst, int dst
bn_free(k);
fp_free(t);
ep_free(q);
+ }
+}
+
+void ep_map_dst(ep_t p, const uint8_t *msg, int len, const uint8_t *dst,
+ int dst_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);
+
+ 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);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
RLC_FREE(pseudo_random_bytes);
}
}
diff --git a/contrib/relic/src/ep/relic_ep_mul.c b/contrib/relic/src/ep/relic_ep_mul.c
index ff64143b6..d73353c3b 100644
--- a/contrib/relic/src/ep/relic_ep_mul.c
+++ b/contrib/relic/src/ep/relic_ep_mul.c
@@ -72,11 +72,7 @@ static void ep_mul_glv_imp(ep_t r, const ep_t p, const bn_t k) {
ep_curve_get_v1(v1);
ep_curve_get_v2(v2);
- bn_copy(_k, k);
- if (bn_cmp_abs(_k, n) == RLC_GT) {
- 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);
s1 = bn_sign(k1);
@@ -97,10 +93,6 @@ static void ep_mul_glv_imp(ep_t r, const ep_t p, const bn_t k) {
l = RLC_MAX(l0, l1);
t0 = naf0 + l - 1;
t1 = naf1 + l - 1;
- for (i = l0; i < l; i++)
- naf0[i] = 0;
- for (i = l1; i < l; i++)
- naf1[i] = 0;
ep_set_infty(r);
for (i = l - 1; i >= 0; i--, t0--, t1--) {
@@ -180,10 +172,7 @@ static void ep_mul_naf_imp(ep_t r, const ep_t p, const bn_t k) {
}
ep_curve_get_ord(n);
- bn_copy(_k, k);
- if (bn_cmp_abs(_k, n) == RLC_GT) {
- bn_mod(_k, _k, n);
- }
+ bn_mod(_k, k, n);
/* Compute the precomputation table. */
ep_tab(t, p, EP_WIDTH);
@@ -235,11 +224,6 @@ static void ep_mul_reg_glv(ep_t r, const ep_t p, const bn_t k) {
bn_t n, _k, k0, k1, v1[3], v2[3];
ep_t q, t[1 << (EP_WIDTH - 2)], u, v, w;
- if (bn_is_zero(k)) {
- ep_set_infty(r);
- return;
- }
-
bn_null(n);
bn_null(_k);
bn_null(k0);
@@ -274,10 +258,8 @@ 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_copy(_k, k);
- if (bn_cmp_abs(_k, n) == RLC_GT) {
- bn_mod(_k, _k, n);
- }
+ bn_abs(_k, k);
+ bn_mod(_k, _k, n);
bn_rec_glv(k0, k1, _k, n, (const bn_t *)v1, (const bn_t *)v2);
s0 = bn_sign(k0);
@@ -358,7 +340,7 @@ 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);
+ dv_copy_cond(r->y, u->y, RLC_FP_DIGS, bn_sign(k) == RLC_NEG);
}
RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
@@ -417,7 +399,7 @@ static void ep_mul_reg_imp(ep_t r, const ep_t p, const bn_t k) {
/* Make a copy of the scalar for processing. */
bn_abs(_k, k);
- _k->dp[0] |= bn_is_even(_k);
+ _k->dp[0] |= 1;
/* Compute the regular w-NAF representation of k. */
l = RLC_CEIL(n, EP_WIDTH - 1) + 1;
@@ -481,8 +463,6 @@ static void ep_mul_reg_imp(ep_t r, const ep_t p, const bn_t k) {
/* Public definitions */
/*============================================================================*/
-#if EP_MUL == BASIC || !defined(STRIP)
-
void ep_mul_basic(ep_t r, const ep_t p, const bn_t k) {
ep_t t;
@@ -517,8 +497,6 @@ void ep_mul_basic(ep_t r, const ep_t p, const bn_t k) {
}
}
-#endif
-
#if EP_MUL == SLIDE || !defined(STRIP)
void ep_mul_slide(ep_t r, const ep_t p, const bn_t k) {
@@ -553,10 +531,7 @@ void ep_mul_slide(ep_t r, const ep_t p, const bn_t k) {
#endif
ep_curve_get_ord(n);
- bn_copy(_k, k);
- if (bn_cmp_abs(_k, n) == RLC_GT) {
- bn_mod(_k, _k, n);
- }
+ bn_mod(_k, k, n);
/* Create table. */
for (i = 1; i < (1 << (EP_WIDTH - 1)); i++) {
@@ -629,11 +604,7 @@ void ep_mul_monty(ep_t r, const ep_t p, const bn_t k) {
ep_curve_get_ord(n);
bits = bn_bits(n);
- bn_copy(_k, k);
- if (bn_cmp_abs(_k, n) == RLC_GT) {
- bn_mod(_k, _k, n);
- }
-
+ bn_mod(_k, k, n);
bn_abs(l, _k);
bn_add(l, l, n);
bn_add(n, l, n);
@@ -750,8 +721,12 @@ 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) {
ep_t t;
+ bn_t _k;
+ int8_t u, naf[RLC_DIG + 1];
+ int l;
ep_null(t);
+ bn_null(_k);
if (k == 0 || ep_is_infty(p)) {
ep_set_infty(r);
@@ -760,12 +735,22 @@ void ep_mul_dig(ep_t r, const ep_t p, dig_t k) {
RLC_TRY {
ep_new(t);
+ bn_new(_k);
- ep_copy(t, p);
- for (int i = util_bits_dig(k) - 2; i >= 0; i--) {
+ bn_set_dig(_k, k);
+
+ l = RLC_DIG + 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 (k & ((dig_t)1 << i)) {
+
+ u = naf[i];
+ if (u > 0) {
ep_add(t, t, p);
+ } else if (u < 0) {
+ ep_sub(t, t, p);
}
}
@@ -776,5 +761,6 @@ void ep_mul_dig(ep_t r, const ep_t p, dig_t k) {
}
RLC_FINALLY {
ep_free(t);
+ bn_free(_k);
}
}
diff --git a/contrib/relic/src/ep/relic_ep_mul_fix.c b/contrib/relic/src/ep/relic_ep_mul_fix.c
index a4e6589bf..913c392d7 100644
--- a/contrib/relic/src/ep/relic_ep_mul_fix.c
+++ b/contrib/relic/src/ep/relic_ep_mul_fix.c
@@ -121,11 +121,7 @@ static void ep_mul_combs_endom(ep_t r, const ep_t *t, const bn_t k) {
ep_curve_get_v2(v2);
l = RLC_CEIL(bn_bits(n), (2 * EP_DEPTH));
- bn_copy(_k, k);
- if (bn_cmp_abs(_k, n) == RLC_GT) {
- 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);
s1 = bn_sign(k1);
@@ -223,11 +219,7 @@ static void ep_mul_combs_plain(ep_t r, const ep_t *t, const bn_t k) {
ep_curve_get_ord(n);
l = RLC_CEIL(bn_bits(n), EP_DEPTH);
- bn_copy(_k, k);
- if (bn_cmp_abs(_k, n) == RLC_GT) {
- bn_mod(_k, _k, n);
- }
-
+ bn_mod(_k, k, n);
n0 = bn_bits(_k);
p0 = (EP_DEPTH) * l - 1;
@@ -321,10 +313,7 @@ void ep_mul_fix_basic(ep_t r, const ep_t *t, const bn_t k) {
bn_new(_k);
ep_curve_get_ord(n);
- bn_copy(_k, k);
- if (bn_cmp_abs(_k, n) == RLC_GT) {
- bn_mod(_k, _k, n);
- }
+ bn_mod(_k, k, n);
ep_set_infty(r);
for (int i = 0; i < bn_bits(_k); i++) {
@@ -480,11 +469,7 @@ void ep_mul_fix_combd(ep_t r, const ep_t *t, const bn_t k) {
d = RLC_CEIL(bn_bits(n), EP_DEPTH);
e = (d % 2 == 0 ? (d / 2) : (d / 2) + 1);
- bn_copy(_k, k);
- if (bn_cmp_abs(_k, n) == RLC_GT) {
- bn_mod(_k, _k, n);
- }
-
+ bn_mod(_k, k, n);
ep_set_infty(r);
n0 = bn_bits(_k);
@@ -551,11 +536,7 @@ void ep_mul_fix_lwnaf(ep_t r, const ep_t *t, const bn_t k) {
bn_new(_k);
ep_curve_get_ord(n);
- bn_copy(_k, k);
- if (bn_cmp_abs(_k, n) == RLC_GT) {
- bn_mod(_k, _k, n);
- }
-
+ bn_mod(_k, k, n);
ep_mul_fix_plain(r, t, _k);
} RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
@@ -564,4 +545,5 @@ void ep_mul_fix_lwnaf(ep_t r, const ep_t *t, const bn_t k) {
bn_free(_k);
}
}
+
#endif
diff --git a/contrib/relic/src/ep/relic_ep_mul_sim.c b/contrib/relic/src/ep/relic_ep_mul_sim.c
index f04de0e82..68e503eb7 100644
--- a/contrib/relic/src/ep/relic_ep_mul_sim.c
+++ b/contrib/relic/src/ep/relic_ep_mul_sim.c
@@ -139,18 +139,6 @@ static void ep_mul_sim_endom(ep_t r, const ep_t p, const bn_t k, const ep_t q,
t1 = naf1 + l - 1;
t2 = naf2 + l - 1;
t3 = naf3 + l - 1;
- for (i = l0; i < l; i++) {
- naf0[i] = 0;
- }
- for (i = l1; i < l; i++) {
- naf1[i] = 0;
- }
- for (i = l2; i < l; i++) {
- naf2[i] = 0;
- }
- for (i = l3; i < l; i++) {
- naf3[i] = 0;
- }
if (bn_sign(k) == RLC_NEG) {
for (i = 0; i < l0; i++) {
@@ -265,6 +253,221 @@ static void ep_mul_sim_endom(ep_t r, const ep_t p, const bn_t k, const ep_t q,
}
}
+/**
+ * Multiplies and adds multiple elliptic curve points simultaneously.
+ * Computes R = \Sum_i=0..n [k_i]P_i.
+ *
+ * @param[out] r - the result.
+ * @param[out] p - the elements to multiply.
+ * @param[out] k - the integer scalars.
+ * @param[out] n - the number of elements to multiply.
+ */
+void ep_mul_sim_lot_endom(ep_t r, const ep_t p[], const bn_t k[], int n) {
+ const int len = RLC_FP_BITS + 1;
+ int i, j, m, l, _l[2], sk;
+ bn_t _k[2], q, v1[3], v2[3];
+ int8_t ptr, *naf = RLC_ALLOCA(int8_t, 2 * n * len);
+
+ bn_null(q);
+
+ if (n <= 10) {
+ ep_t *_p = RLC_ALLOCA(ep_t, 2 * n);
+
+ RLC_TRY {
+ if (naf == NULL || _p == NULL) {
+ RLC_THROW(ERR_NO_MEMORY);
+ }
+ bn_new(q);
+ for (j = 0; j < 2; j++) {
+ bn_null(_k[j]);
+ bn_new(_k[j]);
+ }
+ for (i = 0; i < n; i++) {
+ ep_null(_p[i]);
+ ep_new(_p[i]);
+ }
+
+ for (i = 0; i < 3; i++) {
+ bn_null(v1[i]);
+ bn_null(v2[i]);
+ bn_new(v1[i]);
+ bn_new(v2[i]);
+ }
+
+ l = 0;
+ ep_curve_get_ord(q);
+ ep_curve_get_v1(v1);
+ ep_curve_get_v2(v2);
+ for (i = 0; i < n; i++) {
+ ep_norm(_p[2*i], p[i]);
+ ep_psi(_p[2*i + 1], _p[2*i]);
+ bn_mod(_k[0], k[i], q);
+ sk = bn_sign(_k[0]);
+ bn_rec_glv(_k[0], _k[1], _k[0], q, (const bn_t *)v1, (const bn_t *)v2);
+ if (sk == RLC_NEG) {
+ bn_neg(_k[0], _k[0]);
+ bn_neg(_k[1], _k[1]);
+ }
+ for (j = 0; j < 2; j++) {
+ _l[j] = len;
+ bn_rec_naf(&naf[(2*i + j)*len], &_l[j], _k[j], 2);
+ if (bn_sign(_k[j]) == RLC_NEG) {
+ ep_neg(_p[2*i + j], _p[2*i + j]);
+ }
+ l = RLC_MAX(l, _l[j]);
+ }
+ }
+
+ ep_set_infty(r);
+ for (i = l - 1; i >= 0; i--) {
+ ep_dbl(r, r);
+ for (j = 0; j < n; j++) {
+ for (m = 0; m < 2; m++) {
+ if (naf[(2*j + m)*len + i] > 0) {
+ ep_add(r, r, _p[2*j + m]);
+ }
+ if (naf[(2*j + m)*len + i] < 0) {
+ ep_sub(r, r, _p[2*j + m]);
+ }
+ }
+ }
+ }
+ ep_norm(r, r);
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ } RLC_FINALLY {
+ bn_free(q);
+ bn_free(_k[0]);
+ bn_free(_k[1]);
+ for (i = 0; i < n; i++) {
+ ep_free(_p[i]);
+ }
+ RLC_FREE(_p);
+ RLC_FREE(naf);
+ for (i = 0; i < 3; i++) {
+ bn_free(v1[i]);
+ bn_free(v2[i]);
+ }
+ }
+ } else {
+ const int w = RLC_MAX(2, util_bits_dig(n) - 2), c = (1 << (w - 2));
+ ep_t s, t, u, v, *_p = RLC_ALLOCA(ep_t, 2 * c);
+
+ ep_null(s);
+ ep_null(t);
+ ep_null(u);
+ ep_null(v);
+
+ RLC_TRY {
+ if (naf == NULL || _p == NULL) {
+ RLC_THROW(ERR_NO_MEMORY);
+ }
+ bn_new(q);
+ ep_new(s);
+ ep_new(t);
+ ep_new(u);
+ ep_new(v);
+ for (i = 0; i < 2; i++) {
+ bn_null(_k[i]);
+ bn_new(_k[i]);
+ for (j = 0; j < c; j++) {
+ ep_null(_p[i*c + j]);
+ ep_new(_p[i*c + j]);
+ ep_set_infty(_p[i*c + j]);
+ }
+ }
+ for (i = 0; i < 3; i++) {
+ bn_null(v1[i]);
+ bn_null(v2[i]);
+ bn_new(v1[i]);
+ bn_new(v2[i]);
+ }
+
+ l = 0;
+ ep_curve_get_ord(q);
+ ep_curve_get_v1(v1);
+ ep_curve_get_v2(v2);
+ for (i = 0; i < n; i++) {
+ bn_mod(_k[0], k[i], q);
+ sk = bn_sign(_k[0]);
+ bn_rec_glv(_k[0], _k[1], _k[0], q, (const bn_t *)v1, (const bn_t *)v2);
+ if (sk == RLC_NEG) {
+ bn_neg(_k[0], _k[0]);
+ bn_neg(_k[1], _k[1]);
+ }
+ for (j = 0; j < 2; j++) {
+ _l[j] = len;
+ bn_rec_naf(&naf[(2*i + j)*len], &_l[j], _k[j], w);
+ if (bn_sign(_k[j]) == RLC_NEG) {
+ for (m = 0; m < _l[j]; m++) {
+ naf[(2*i + j)*len + m] = -naf[(2*i + j)*len + m];
+ }
+ }
+ l = RLC_MAX(l, _l[j]);
+ }
+ }
+
+ ep_set_infty(s);
+ for (i = l - 1; i >= 0; i--) {
+ for (j = 0; j < n; j++) {
+ for (m = 0; m < 2; m++) {
+ ptr = naf[(2*j + m)*len + i];
+ if (ptr != 0) {
+ ep_copy(t, p[j]);
+ if (ptr < 0) {
+ ptr = -ptr;
+ ep_neg(t, t);
+ }
+ ep_add(_p[m*c + (ptr >> 1)], _p[m*c + (ptr >> 1)], t);
+ }
+ }
+ }
+
+ ep_set_infty(t);
+ for (m = 1; m >= 0; m--) {
+ ep_psi(t, t);
+ ep_set_infty(u);
+ ep_set_infty(v);
+ for (j = c - 1; j >= 0; j--) {
+ ep_add(u, u, _p[m*c + j]);
+ if (j == 0) {
+ ep_dbl(v, v);
+ }
+ ep_add(v, v, u);
+ ep_set_infty(_p[m*c + j]);
+ }
+ ep_add(t, t, v);
+ }
+ ep_dbl(s, s);
+ ep_add(s, s, t);
+ }
+
+ /* Convert r to affine coordinates. */
+ ep_norm(r, s);
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ } RLC_FINALLY {
+ bn_free(q);
+ ep_free(s);
+ ep_free(t);
+ ep_free(u);
+ ep_free(v);
+ for (i = 0; i < 2; i++) {
+ bn_free(_k[i]);
+ for (j = 0; j < c; j++) {
+ ep_free(_p[i*c + j]);
+ }
+ }
+ RLC_FREE(_p);
+ RLC_FREE(naf);
+ for (i = 0; i < 3; i++) {
+ bn_free(v1[i]);
+ bn_free(v2[i]);
+ }
+ }
+ }
+}
+
#endif /* EP_ENDOM */
#if defined(EP_PLAIN) || defined(EP_SUPER)
@@ -319,13 +522,6 @@ static void ep_mul_sim_plain(ep_t r, const ep_t p, const bn_t k, const ep_t q,
bn_rec_naf(naf1, &l1, m, EP_WIDTH);
l = RLC_MAX(l0, l1);
- for (i = l0; i < l; i++) {
- naf0[i] = 0;
- }
- for (i = l1; i < l; i++) {
- naf1[i] = 0;
- }
-
if (bn_sign(k) == RLC_NEG) {
for (i = 0; i < l0; i++) {
naf0[i] = -naf0[i];
@@ -377,6 +573,77 @@ static void ep_mul_sim_plain(ep_t r, const ep_t p, const bn_t k, const ep_t q,
}
}
+/**
+ * Multiplies and adds multiple elliptic curve points simultaneously.
+ * Computes R = \Sum_i=0..n [k_i]P_i.
+ *
+ * @param[out] r - the result.
+ * @param[out] p - the elements to multiply.
+ * @param[out] k - the integer scalars.
+ * @param[out] n - the number of elements to multiply.
+ */
+void ep_mul_sim_lot_plain(ep_t r, const ep_t p[], const bn_t k[], int n) {
+ int i, j, l, *_l = RLC_ALLOCA(int, n);
+ ep_t *_p = RLC_ALLOCA(ep_t, n);
+ int8_t *naf = NULL;
+
+ RLC_TRY {
+ l = 0;
+ for (i = 0; i < n; i++) {
+ l = RLC_MAX(l, bn_bits(k[i]) + 1);
+ }
+ naf = RLC_ALLOCA(int8_t, n * l);
+ if (naf == NULL || _p == NULL || _l == NULL) {
+ RLC_THROW(ERR_NO_MEMORY);
+ }
+
+ for (i = 0; i < n; i++) {
+ ep_null(_p[i]);
+ ep_new(_p[i]);
+ }
+
+ for (i = 0; i < n; i++) {
+ _l[i] = l;
+ ep_norm(_p[i], p[i]);
+ bn_rec_naf(&naf[i*l], &_l[i], k[i], 2);
+ if (bn_sign(k[i]) == RLC_NEG) {
+ ep_neg(_p[i], _p[i]);
+ }
+ }
+
+ for (i = 0; i < n; i++) {
+ for (j = _l[i]; j < l; j++) {
+ naf[i*l + j] = 0;
+ }
+ }
+
+ ep_set_infty(r);
+ for (i = l - 1; i >= 0; i--) {
+ ep_dbl(r, r);
+ for (j = 0; j < n; j++) {
+ if (naf[j*l + i] > 0) {
+ ep_add(r, r, _p[j]);
+ }
+ if (naf[j*l + i] < 0) {
+ ep_sub(r, r, _p[j]);
+ }
+ }
+ }
+
+ /* Convert r to affine coordinates. */
+ ep_norm(r, r);
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ } RLC_FINALLY {
+ for (i = 0; i < n; i++) {
+ ep_free(_p[i]);
+ }
+ RLC_FREE(_l);
+ RLC_FREE(_p);
+ RLC_FREE(naf);
+ }
+}
+
#endif /* EP_PLAIN || EP_SUPER */
#endif /* EP_SIM == INTER */
@@ -449,14 +716,8 @@ void ep_mul_sim_trick(ep_t r, const ep_t p, const bn_t k, const ep_t q,
}
ep_curve_get_ord(n);
- bn_copy(_k, k);
- if (bn_cmp_abs(_k, n) == RLC_GT) {
- bn_mod(_k, _k, n);
- }
- bn_copy(_m, m);
- if (bn_cmp_abs(_m, n) == RLC_GT) {
- bn_mod(_m, _m, n);
- }
+ bn_mod(_k, k, n);
+ bn_mod(_m, m, n);
ep_set_infty(t0[0]);
ep_copy(t0[1], p);
@@ -549,14 +810,8 @@ void ep_mul_sim_inter(ep_t r, const ep_t p, const bn_t k, const ep_t q,
/* Handle this here to reduce complexity of static functions. */
ep_curve_get_ord(n);
- bn_copy(_k, k);
- if (bn_cmp_abs(_k, n) == RLC_GT) {
- bn_mod(_k, _k, n);
- }
- bn_copy(_m, m);
- if (bn_cmp_abs(_m, n) == RLC_GT) {
- bn_mod(_m, _m, n);
- }
+ bn_mod(_k, k, n);
+ bn_mod(_m, m, n);
#if defined(EP_ENDOM)
if (ep_curve_is_endom()) {
@@ -615,14 +870,8 @@ void ep_mul_sim_joint(ep_t r, const ep_t p, const bn_t k, const ep_t q,
}
ep_curve_get_ord(n);
- bn_copy(_k, k);
- if (bn_cmp_abs(_k, n) == RLC_GT) {
- bn_mod(_k, _k, n);
- }
- bn_copy(_m, m);
- if (bn_cmp_abs(_m, n) == RLC_GT) {
- bn_mod(_m, _m, n);
- }
+ bn_mod(_k, k, n);
+ bn_mod(_m, m, n);
ep_set_infty(t[0]);
ep_copy(t[1], q);
@@ -707,14 +956,8 @@ void ep_mul_sim_gen(ep_t r, const bn_t k, const ep_t q, const bn_t m) {
ep_curve_get_gen(g);
ep_curve_get_ord(n);
- bn_copy(_k, k);
- if (bn_cmp_abs(_k, n) == RLC_GT) {
- bn_mod(_k, _k, n);
- }
- bn_copy(_m, m);
- if (bn_cmp_abs(_m, n) == RLC_GT) {
- bn_mod(_m, _m, n);
- }
+ bn_mod(_k, k, n);
+ bn_mod(_m, m, n);
#if defined(EP_ENDOM)
#if EP_SIM == INTER && EP_FIX == LWNAF && defined(EP_PRECO)
@@ -751,14 +994,14 @@ void ep_mul_sim_gen(ep_t r, const bn_t k, const ep_t q, const bn_t m) {
}
}
-void ep_mul_sim_dig(ep_t r, const ep_t p[], const dig_t k[], int len) {
+void ep_mul_sim_dig(ep_t r, const ep_t p[], const dig_t k[], int n) {
ep_t t;
int max;
ep_null(t);
max = util_bits_dig(k[0]);
- for (int i = 1; i < len; i++) {
+ for (int i = 1; i < n; i++) {
max = RLC_MAX(max, util_bits_dig(k[i]));
}
@@ -768,7 +1011,7 @@ void ep_mul_sim_dig(ep_t r, const ep_t p[], const dig_t k[], int len) {
ep_set_infty(t);
for (int i = max - 1; i >= 0; i--) {
ep_dbl(t, t);
- for (int j = 0; j < len; j++) {
+ for (int j = 0; j < n; j++) {
if (k[j] & ((dig_t)1 << i)) {
ep_add(t, t, p[j]);
}
@@ -785,65 +1028,25 @@ void ep_mul_sim_dig(ep_t r, const ep_t p[], const dig_t k[], int len) {
}
}
-void ep_mul_sim_lot(ep_t r, ep_t p[], const bn_t k[], int n) {
- int i, j, l, *_l = RLC_ALLOCA(int, n);
- ep_t *_p = RLC_ALLOCA(ep_t, n);
- int8_t *naf = NULL;
-
- RLC_TRY {
- l = 0;
- for (i = 0; i < n; i++) {
- l = RLC_MAX(l, bn_bits(k[i]) + 1);
- }
- naf = RLC_ALLOCA(int8_t, n * l);
- if (naf == NULL || _p == NULL || _l == NULL) {
- RLC_THROW(ERR_NO_MEMORY);
- }
-
- for (i = 0; i < n; i++) {
- ep_null(_p[i]);
- ep_new(_p[i]);
- }
-
-
- for (i = 0; i < n; i++) {
- _l[i] = l;
- ep_norm(_p[i], p[i]);
- bn_rec_naf(&naf[i*l], &_l[i], k[i], 2);
- if (bn_sign(k[i]) == RLC_NEG) {
- ep_neg(_p[i], _p[i]);
- }
- }
-
- for (i = 0; i < n; i++) {
- for (j = _l[i]; j < l; j++) {
- naf[i*l + j] = 0;
- }
- }
+void ep_mul_sim_lot(ep_t r, const ep_t p[], const bn_t k[], int n) {
+ int flag = 0;
+ if (n == 0) {
ep_set_infty(r);
- for (i = l - 1; i >= 0; i--) {
- ep_dbl(r, r);
- for (j = 0; j < n; j++) {
- if (naf[j*l + i] > 0) {
- ep_add(r, r, _p[j]);
- }
- if (naf[j*l + i] < 0) {
- ep_sub(r, r, _p[j]);
- }
- }
- }
+ return;
+ }
- /* Convert r to affine coordinates. */
- ep_norm(r, r);
- } RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- } RLC_FINALLY {
- for (i = 0; i < n; i++) {
- ep_free(_p[i]);
- }
- RLC_FREE(_l);
- RLC_FREE(_p);
- RLC_FREE(naf);
+#if defined(EP_ENDOM)
+ if (ep_curve_is_endom()) {
+ ep_mul_sim_lot_endom(r, p, k, n);
+ flag = 1;
}
+#endif
+
+#if defined(EP_PLAIN) || defined(EP_SUPER)
+ if (!flag) {
+ ep_mul_sim_lot_plain(r, p, k, n);
+ }
+#endif
+ (void)flag;
}
diff --git a/contrib/relic/src/ep/relic_ep_norm.c b/contrib/relic/src/ep/relic_ep_norm.c
index 4499a3d02..f5c924529 100644
--- a/contrib/relic/src/ep/relic_ep_norm.c
+++ b/contrib/relic/src/ep/relic_ep_norm.c
@@ -132,10 +132,11 @@ void ep_norm_sim(ep_t *r, const ep_t *t, int n) {
fp_copy(r[i]->z, a[i]);
}
}
-
+#if EP_ADD == PROJC || EP_ADD == JACOB || !defined(STRIP)
for (i = 0; i < n; i++) {
ep_norm_imp(r[i], r[i], 1);
}
+#endif /* EP_ADD == PROJC */
}
RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
diff --git a/contrib/relic/src/ep/relic_ep_param.c b/contrib/relic/src/ep/relic_ep_param.c
index bc250d6ec..cfc50f881 100644
--- a/contrib/relic/src/ep/relic_ep_param.c
+++ b/contrib/relic/src/ep/relic_ep_param.c
@@ -355,8 +355,6 @@
#define BN_P254_Y "1"
#define BN_P254_R "2523648240000001BA344D8000000007FF9F800000000010A10000000000000D"
#define BN_P254_H "1"
-#define BN_P254_BETA "25236482400000017080EB4000000006181800000000000CD98000000000000B"
-#define BN_P254_LAMB "252364824000000126CD8900000000024908FFFFFFFFFFFCF9FFFFFFFFFFFFF6"
#define BN_P254_MAPU "-1"
/** @} */
#endif
@@ -389,12 +387,25 @@
#define BN_P256_Y "4"
#define BN_P256_R "B64000000000FF2F2200000085FD547FD8001F44B6B7F4B7C2BC818F7B6BEF99"
#define BN_P256_H "1"
-#define BN_P256_BETA "B64000000000FF2E2F00000085FC555230001F445D656FB022BC77236CD54C89"
-#define BN_P256_LAMB "B64000000000FF2D3C00000085FB562050001F44040FF68D82BC6CB6D9E8694E"
#define BN_P256_MAPU "1"
/** @} */
#endif
+#if defined(EP_ENDOM) && FP_PRIME == 256
+/**
+ * Parameters for a 256-bit pairing-friendly prime curve standardized in China.
+ */
+/** @{ */
+#define SM9_P256_A "0"
+#define SM9_P256_B "5"
+#define SM9_P256_X "93DE051D62BF718FF5ED0704487D01D6E1E4086909DC3280E8C4E4817C66DDDD"
+#define SM9_P256_Y "21FE8DDA4F21E607631065125C395BBC1C1C00CBFA6024350C464CD70A3EA616"
+#define SM9_P256_R "B640000002A3A6F1D603AB4FF58EC74449F2934B18EA8BEEE56EE19CD69ECF25"
+#define SM9_P256_H "1"
+#define SM9_P256_MAPU "-1"
+/** @} */
+#endif
+
#if defined(EP_ENDOM) && FP_PRIME == 381
/**
* Parameters for a 381-bit pairing-friendly prime curve.
@@ -431,9 +442,22 @@
#define BN_P382_Y "1"
#define BN_P382_R "24009015183F94892D996CC179C6D1666F82CEFBE47879BB46E4CDA2E2E2281D08DC008E80108252004200000000000D"
#define BN_P382_H "1"
-#define BN_P382_BETA "4800D81F38406C6AA53C1444D128028A40C60B760288002AC006C0F3001B000000000007"
-#define BN_P382_LAMB "9001B03E7080D8D54A78288AC2524566A1E61CA70654006D801382BE004E000000000016"
-#define BN_P382_MAPU "-1"
+#define BN_P382_MAPU "2"
+/** @} */
+#endif
+
+#if defined(EP_ENDOM) && FP_PRIME == 383
+/**
+ * Parameters for a 383-bit pairing-friendly prime curve.
+ */
+/** @{ */
+#define B12_P383_A "0"
+#define B12_P383_B "4"
+#define B12_P383_X "4ECB5D037AAE9F176171C5D83FC0D6C7AB9195D3D1442B4809F4A6F577722D5DADC9737D5D368545441992AB647A89BE"
+#define B12_P383_Y "DD3BFDE4A26B777CEDA2A8F1C4C4E6192C586D8227CC05A34705CCC5A32288C0944408D54909F31BF5C664E81778B03"
+#define B12_P383_R "1002001800C00B809C04401C81698B381DE05F095A120D3973B2099EBFEBC0001"
+#define B12_P383_H "555AAAC000AABBFFB550556155169EAB"
+#define B12_P383_MAPU "5"
/** @} */
#endif
@@ -448,8 +472,6 @@
#define BN_P446_Y "10"
#define BN_P446_R "2400000000000000002400000002D00000000D800000021C00000017A0000000870000000AD400000054C000000156000000126000000061"
#define BN_P446_H "1"
-#define BN_P446_BETA "4800000000000000003600000004800000000D800000024000000019E00000004800000006300000002E"
-#define BN_P446_LAMB "9000000000000000006C00000007E00000001B00000003F000000027C00000007E00000009600000003D"
#define BN_P446_MAPU "1"
#endif
@@ -481,23 +503,6 @@
#define B12_P455_MAPU "-1"
#endif
-#if defined(EP_ENDOM) && FP_PRIME == 477
-/**
- * Parameters for a 477-bit pairing-friendly prime curve at the 192-bit security level.
- */
-/** @{ */
-#define B24_P477_A "0"
-#define B24_P477_B "4"
-#define B24_P477_X "15DFD8E4893A408A34B600532B51CC86CAB3AF07103CFCF3EC7B9AF836904CFB60AB0FA8AC91EE6255E5EF6286FA0C24DF9D76EA50599C2E103E40AD"
-#define B24_P477_Y "0A683957A59B1B488FA657E11B44815056BDE33C09D6AAD392D299F89C7841B91A683BF01B7E70547E48E0FBE1CA9E991983131470F886BA9B6FCE2E"
-#define B24_P477_R "57F52EE445CC41781FCD53D13E45F6ACDFE4F9F2A3CD414E71238AFC9FCFC7D38CAEF64F4FF79F90013FFFFFF0000001"
-#define B24_P477_H "41550AAAC04B3FD5000015AB"
-#define B24_P477_BETA "13D9011CCEAD3E74042D5F515F5F04BD3F8EDD703A4BC74ADDB36A479C0D9AD61475466C5CC1F64BC109A18B162560A1743C98DEF233CCCB5F717BEC"
-#define B24_P477_LAMB "1001740B431D14BFD17F4BD000300173FFFFFFFEFFFFFFFED"
-#define B24_P477_MAPU "1"
-/** @} */
-#endif
-
#if defined(EP_ENDOM) && FP_PRIME == 508
/**
* Parameters for a 508-bit pairing-friendly prime curve at the 192-bit security level.
@@ -515,6 +520,21 @@
/** @} */
#endif
+#if defined(EP_ENDOM) && FP_PRIME == 509
+/**
+ * Parameters for a 477-bit pairing-friendly prime curve at the 192-bit security level.
+ */
+/** @{ */
+#define B24_P509_A "0"
+#define B24_P509_B "1"
+#define B24_P509_X "3A1ADC72F714991991F491FA07B2429302EE6CB4FD3A8663BA38F36F81984232A749B91C286A4579F7736D120DC572C42719E75C7F58AC1426DB4827CF4A46A"
+#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.
@@ -537,15 +557,15 @@
* Parameters for the 544-bit Cocks-Pinch curve.
*/
/** @{ */
-#define CP8_P544_A "2"
-#define CP8_P544_B "0"
-#define CP8_P544_X "251670DB162D336F28505AE026E94316A074EFF8A26AD412D22C58A9CD154E4643CFC40DE884D3D54B95455267566445CB284DF1E413E11CB190BB760CD5665B12456771"
-#define CP8_P544_Y "A18EC01733AE4D3AA2B087933D739A4987D839A136695CEE9D7C5B0E24EC62754B70DCD5EFE918C626728C2C31BD9616BC2F724015BCC2CF4DD139897799DA9D198B26CF"
-#define CP8_P544_R "FF0060739E18D7594A978B0AB6AE4CE3DBFD52A9D00197603FFFDF0000000101"
-#define CP8_P544_H "BC5A106E29D336CBF340F2BB98248FFC0719523D3233C6B3909C882E2BD2251BD3B22F14"
-#define CP8_P544_BETA "AEB8BAFC09BEB98DE5FB37D9FC56F9EAC4F908F09D88B1CD8622513C94499803C18F54E6B4FB9180292A2FD4C8AFD2AF43F54BCF308198872F3A6B591394AED0EBF7961A"
-#define CP8_P544_LAMB "FF801041EF80043901FFFEF800000010"
-#define CP8_P544_MAPU "5"
+#define GMT8_P544_A "2"
+#define GMT8_P544_B "0"
+#define GMT8_P544_X "251670DB162D336F28505AE026E94316A074EFF8A26AD412D22C58A9CD154E4643CFC40DE884D3D54B95455267566445CB284DF1E413E11CB190BB760CD5665B12456771"
+#define GMT8_P544_Y "A18EC01733AE4D3AA2B087933D739A4987D839A136695CEE9D7C5B0E24EC62754B70DCD5EFE918C626728C2C31BD9616BC2F724015BCC2CF4DD139897799DA9D198B26CF"
+#define GMT8_P544_R "FF0060739E18D7594A978B0AB6AE4CE3DBFD52A9D00197603FFFDF0000000101"
+#define GMT8_P544_H "BC5A106E29D336CBF340F2BB98248FFC0719523D3233C6B3909C882E2BD2251BD3B22F14"
+#define GMT8_P544_BETA "AEB8BAFC09BEB98DE5FB37D9FC56F9EAC4F908F09D88B1CD8622513C94499803C18F54E6B4FB9180292A2FD4C8AFD2AF43F54BCF308198872F3A6B591394AED0EBF7961A"
+#define GMT8_P544_LAMB "FF801041EF80043901FFFEF800000010"
+#define GMT8_P544_MAPU "5"
#endif
/** @} */
@@ -743,6 +763,7 @@ static inline void ep_param_set_ctmap(const char *a_str, const char *b_str,
coeffs->deg_yn = ep_param_get_coeffs(coeffs->yn, yn_str);
coeffs->deg_yd = ep_param_get_coeffs(coeffs->yd, yd_str);
}
+
#endif /* EP_CTMAP */
/*============================================================================*/
@@ -877,6 +898,11 @@ void ep_param_set(int param) {
ASSIGN(SECG_K256, SECG_256);
endom = 1;
break;
+ case SM9_P256:
+ ASSIGN(SM9_P256, SM9_256);
+ endom = 1;
+ pairf = EP_BN;
+ break;
case BN_P256:
ASSIGN(BN_P256, BN_256);
endom = 1;
@@ -913,6 +939,13 @@ void ep_param_set(int param) {
plain = 1;
break;
#endif
+#if defined(EP_ENDOM) && FP_PRIME == 383
+ case B12_P383:
+ ASSIGN(B12_P383, B12_383);
+ endom = 1;
+ pairf = EP_B12;
+ break;
+#endif
#if defined(EP_PLAIN) && FP_PRIME == 384
case NIST_P384:
ASSIGN(NIST_P384, NIST_384);
@@ -938,18 +971,19 @@ void ep_param_set(int param) {
pairf = EP_B12;
break;
#endif
-#if defined(EP_ENDOM) && FP_PRIME == 477
- case B24_P477:
- ASSIGNK(B24_P477, B24_477);
- plain = 1;
- break;
-#endif
#if defined(EP_ENDOM) && FP_PRIME == 508
case KSS_P508:
ASSIGNK(KSS_P508, KSS_508);
endom = 1;
break;
#endif
+#if defined(EP_ENDOM) && FP_PRIME == 509
+ case B24_P509:
+ ASSIGN(B24_P509, B24_509);
+ endom = 1;
+ pairf = EP_B24;
+ break;
+#endif
#if defined(EP_ENDOM) && FP_PRIME == 511
case OT8_P511:
ASSIGNK(OT8_P511, OT_511);
@@ -969,8 +1003,8 @@ void ep_param_set(int param) {
break;
#endif
#if defined(EP_ENDOM) && FP_PRIME == 544
- case CP8_P544:
- ASSIGN(CP8_P544, CP8_544);
+ case GMT8_P544:
+ ASSIGN(GMT8_P544, GMT8_544);
endom = 1;
break;
#endif
@@ -1043,6 +1077,18 @@ void ep_param_set(int param) {
bn_sqr(lamb, lamb);
bn_sub_dig(lamb, lamb, 1);
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);
+ 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. */
@@ -1188,6 +1234,8 @@ int ep_param_set_any_endom(void) {
ep_param_set(B12_P381);
#elif FP_PRIME == 382
ep_param_set(BN_P382);
+#elif FP_PRIME == 383
+ ep_param_set(B12_P383);
#elif FP_PRIME == 446
#ifdef FP_QNRES
ep_param_set(B12_P446);
@@ -1196,14 +1244,14 @@ int ep_param_set_any_endom(void) {
#endif
#elif FP_PRIME == 455
ep_param_set(B12_P455);
-#elif FP_PRIME == 477
- ep_param_set(B24_P477);
#elif FP_PRIME == 508
ep_param_set(KSS_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(CP8_P544);
+ ep_param_set(GMT8_P544);
#elif FP_PRIME == 638
#ifdef FP_QNRES
ep_param_set(B12_P638);
@@ -1258,6 +1306,10 @@ int ep_param_set_any_pairf(void) {
ep_param_set(BN_P382);
type = RLC_EP_DTYPE;
degree = 2;
+#elif FP_PRIME == 383
+ ep_param_set(B12_P383);
+ type = RLC_EP_MTYPE;
+ degree = 2;
#elif FP_PRIME == 446
#ifdef FP_QNRES
ep_param_set(B12_P446);
@@ -1272,20 +1324,20 @@ int ep_param_set_any_pairf(void) {
ep_param_set(B12_P455);
type = RLC_EP_DTYPE;
degree = 2;
-#elif FP_PRIME == 477
- ep_param_set(B24_P477);
- type = RLC_EP_MTYPE;
- degree = 4;
#elif FP_PRIME == 508
ep_param_set(KSS_P508);
type = RLC_EP_DTYPE;
degree = 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;
#elif FP_PRIME == 544
- ep_param_set(CP8_P544);
+ ep_param_set(GMT8_P544);
type = RLC_EP_MTYPE;
degree = 2;
#elif FP_PRIME == 569
@@ -1323,10 +1375,15 @@ int ep_param_set_any_pairf(void) {
switch (degree) {
case 0:
ep2_curve_set_twist(0);
+ /* Compute pairing generator. */
+ pc_core_calc();
break;
case 2:
ep2_curve_set_twist(type);
break;
+ case 4:
+ ep4_curve_set_twist(type);
+ break;
}
}
#else
@@ -1383,14 +1440,20 @@ void ep_param_print(void) {
case BN_P256:
util_banner("Curve BN-P256:", 0);
break;
- case BN_P382:
- util_banner("Curve BN-P382:", 0);
+ case SM9_P256:
+ util_banner("Curve SM9-P256:", 0);
break;
case B12_P381:
util_banner("Curve B12-P381:", 0);
break;
- case CP8_P544:
- util_banner("Curve CP8-P544:", 0);
+ case BN_P382:
+ util_banner("Curve BN-P382:", 0);
+ break;
+ case B12_P383:
+ util_banner("Curve B12-P383:", 0);
+ break;
+ case GMT8_P544:
+ util_banner("Curve GMT8-P544:", 0);
break;
case BN_P446:
util_banner("Curve BN-P446:", 0);
@@ -1401,12 +1464,12 @@ void ep_param_print(void) {
case B12_P455:
util_banner("Curve B12-P455:", 0);
break;
- case B24_P477:
- util_banner("Curve B24-P477:", 0);
- break;
case KSS_P508:
util_banner("Curve KSS-P508:", 0);
break;
+ case B24_P509:
+ util_banner("Curve B24-P509:", 0);
+ break;
case OT8_P511:
util_banner("Curve OT8-P511:", 0);
break;
@@ -1458,6 +1521,7 @@ int ep_param_level(void) {
return 112;
case BN_P254:
case BN_P256:
+ case SM9_P256:
return 112;
case NIST_P256:
case SECG_K256:
@@ -1466,14 +1530,16 @@ int ep_param_level(void) {
return 128;
case B12_P381:
case BN_P382:
+ case B12_P383:
case BN_P446:
case B12_P446:
- case CP8_544:
+ case GMT8_544:
case SS_P1536:
return 128;
case B12_P455:
return 140;
case NIST_P384:
+ case B24_P509:
return 192;
case NIST_P521:
return 256;
@@ -1486,22 +1552,26 @@ int ep_param_level(void) {
int ep_param_embed(void) {
switch (ep_param_get()) {
+ case SS_P1536:
+ return 2;
+ case OT8_P511:
+ case GMT8_P544:
+ return 8;
case BN_P158:
case BN_P254:
case BN_P256:
+ case SM9_P256:
case BN_P382:
case BN_P446:
case B12_P446:
case BN_P638:
case B12_P381:
+ case B12_P383:
case B12_P455:
case B12_P638:
return 12;
- case SS_P1536:
- return 2;
- case OT8_P511:
- case CP8_P544:
- return 8;
+ case B24_P509:
+ return 24;
case B48_P575:
return 48;
case K54_P569:
diff --git a/contrib/relic/src/ep/relic_ep_psi.c b/contrib/relic/src/ep/relic_ep_psi.c
index b353f459f..c700be38c 100644
--- a/contrib/relic/src/ep/relic_ep_psi.c
+++ b/contrib/relic/src/ep/relic_ep_psi.c
@@ -1,6 +1,6 @@
/*
* RELIC is an Efficient LIbrary for Cryptography
- * Copyright (c) 2009 RELIC Authors
+ * Copyright (c) 2021 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
diff --git a/contrib/relic/src/ep/relic_ep_util.c b/contrib/relic/src/ep/relic_ep_util.c
index 8b97aca51..54b13eab9 100644
--- a/contrib/relic/src/ep/relic_ep_util.c
+++ b/contrib/relic/src/ep/relic_ep_util.c
@@ -83,7 +83,6 @@ void ep_blind(ep_t r, const ep_t p) {
RLC_TRY {
fp_new(rand);
-
fp_rand(rand);
#if EP_ADD == BASIC
(void)rand;
@@ -278,6 +277,11 @@ void ep_read_bin(ep_t a, const uint8_t *bin, int len) {
return;
}
}
+
+ if (!ep_on_curve(a)) {
+ RLC_THROW(ERR_NO_VALID);
+ return;
+ }
}
void ep_write_bin(uint8_t *bin, int len, const ep_t a, int pack) {
@@ -285,12 +289,13 @@ void ep_write_bin(uint8_t *bin, int len, const ep_t a, int pack) {
ep_null(t);
+ memset(bin, 0, len);
+
if (ep_is_infty(a)) {
if (len < 1) {
RLC_THROW(ERR_NO_BUFFER);
return;
} else {
- bin[0] = 0;
return;
}
}
diff --git a/contrib/relic/src/epx/relic_ep2_curve.c b/contrib/relic/src/epx/relic_ep2_curve.c
index dfc60515f..cdf301946 100644
--- a/contrib/relic/src/epx/relic_ep2_curve.c
+++ b/contrib/relic/src/epx/relic_ep2_curve.c
@@ -92,6 +92,23 @@
/** @} */
#endif
+#if defined(EP_ENDOM) && FP_PRIME == 256
+/** @{ */
+#define SM9_P256_A0 "0"
+#define SM9_P256_A1 "0"
+#define SM9_P256_B0 "0"
+#define SM9_P256_B1 "5"
+#define SM9_P256_X0 "3722755292130B08D2AAB97FD34EC120EE265948D19C17ABF9B7213BAF82D65B"
+#define SM9_P256_X1 "85AEF3D078640C98597B6027B441A01FF1DD2C190F5E93C454806C11D8806141"
+#define SM9_P256_Y0 "A7CF28D519BE3DA65F3170153D278FF247EFBA98A71A08116215BBA5C999A7C7"
+#define SM9_P256_Y1 "17509B092E845C1266BA0D262CBEE6ED0736A96FA347C8BD856DC76B84EBEB96"
+#define SM9_P256_R "B640000002A3A6F1D603AB4FF58EC74449F2934B18EA8BEEE56EE19CD69ECF25"
+#define SM9_P256_H "B640000002A3A6F1D603AB4FF58EC745F9F2934B1C0B51C8E57054B2F003BBD5"
+#define SM9_P256_MAPU0 "-1"
+#define SM9_P256_MAPU1 "0"
+/** @} */
+#endif
+
#if defined(EP_ENDOM) && FP_PRIME == 381
/** @{ */
#define B12_P381_A0 "0"
@@ -139,6 +156,23 @@
/** @} */
#endif
+#if defined(EP_ENDOM) && FP_PRIME == 383
+/** @{ */
+#define B12_P383_A0 "0"
+#define B12_P383_A1 "0"
+#define B12_P383_B0 "4"
+#define B12_P383_B1 "4"
+#define B12_P383_X0 "2E4DCF4E55CBA1075B3325DD25C2B80BD907686E55E175F0B5D097E46E78B6B5F8E600B80D2EBD4E410BCCCBAE018976"
+#define B12_P383_X1 "0BE0128C473D6A90202AC72A60E988CF7901242A2A4623A89253256CC11C1519D3C633897E071D8F466EA0BFFA5F9313"
+#define B12_P383_Y0 "44900D049962DF1BBCB29872FDA90D0DFC2253033569F7D684080F6A5B4F669120A29F908FED5B64AAA9A56502405B39"
+#define B12_P383_Y1 "1459B073246773B35CBCBFC9318AC47DDC1C284887D1DA4BE13593ACC0E45B748AF4115011A3EA730A7DB21A83562411"
+#define B12_P383_R "1002001800C00B809C04401C81698B381DE05F095A120D3973B2099EBFEBC0001"
+#define B12_P383_H "1C78E45562AB68EE641721902ED56C9B45EB1276A5C15CB19C7BF81F7A7B6F22053BAC3422240A3F4A7E3C25D470E7BABDB8A2E1E1793BF9CEBDD1BF2EFE30E5"
+#define B12_P383_MAPU0 "0"
+#define B12_P383_MAPU1 "1"
+/** @} */
+#endif
+
#if defined(EP_ENDOM) && FP_PRIME == 446
/** @{ */
#define BN_P446_A0 "0"
@@ -209,18 +243,18 @@
#if defined(EP_ENDOM) && FP_PRIME == 544
/** @{ */
-#define CP8_P544_A0 "0"
-#define CP8_P544_A1 "2"
-#define CP8_P544_B0 "0"
-#define CP8_P544_B1 "0"
-#define CP8_P544_X0 "1EE84A939A46EAE4287805E2FFABBCED3605B74F5FD7E545F390D2E3D34AD0C60851EA65A18CF92396B9318FCAB3205D79C8D03E928590F719E4086A1C42AF2D40EB6C3A"
-#define CP8_P544_X1 "065F721D63381C07D1BF556D65A3A82B0E969BA031FB3812F49709926D5159324DFB685048D4EAFC914F893A0D5382868D1D252619AA964149258DCC1A86B68775F36A82"
-#define CP8_P544_Y0 "9B80046683050F459F48D7CE4C83992D5B044718326AEE2DD86F3E5557BD240441A763BC40030F21FC3A64483B450330930BAFA62E7B573B565404A9DB2A5BFF7D6994D4"
-#define CP8_P544_Y1 "AB457A64E140799D3D9B77ECEA828957F3AEADB3278FEE32E9AD77F068DD2F95B469607E8CE3CE5705276F869CFB18270C0A8FC8D8AD0D17545F4DCCC9E599853A7BAB76"
-#define CP8_P544_R "FF0060739E18D7594A978B0AB6AE4CE3DBFD52A9D00197603FFFDF0000000101"
-#define CP8_P544_H "8A0A079FC7C3D421A4986FAAA10A6593F60BC94E32AEE8067E35551B86D59F0F61BD6A750917746236DD39CB4710BD44B7BE86F0A8E5324DFE802973060F04BF37C018705B78072182D139A8D2BD338A630511676FDAFD47C60DB5393F9DFC96089B1FFB60B78FB2"
-#define CP8_P544_MAPU0 "0"
-#define CP8_P544_MAPU1 "1"
+#define GMT8_P544_A0 "0"
+#define GMT8_P544_A1 "2"
+#define GMT8_P544_B0 "0"
+#define GMT8_P544_B1 "0"
+#define GMT8_P544_X0 "1EE84A939A46EAE4287805E2FFABBCED3605B74F5FD7E545F390D2E3D34AD0C60851EA65A18CF92396B9318FCAB3205D79C8D03E928590F719E4086A1C42AF2D40EB6C3A"
+#define GMT8_P544_X1 "065F721D63381C07D1BF556D65A3A82B0E969BA031FB3812F49709926D5159324DFB685048D4EAFC914F893A0D5382868D1D252619AA964149258DCC1A86B68775F36A82"
+#define GMT8_P544_Y0 "9B80046683050F459F48D7CE4C83992D5B044718326AEE2DD86F3E5557BD240441A763BC40030F21FC3A64483B450330930BAFA62E7B573B565404A9DB2A5BFF7D6994D4"
+#define GMT8_P544_Y1 "AB457A64E140799D3D9B77ECEA828957F3AEADB3278FEE32E9AD77F068DD2F95B469607E8CE3CE5705276F869CFB18270C0A8FC8D8AD0D17545F4DCCC9E599853A7BAB76"
+#define GMT8_P544_R "FF0060739E18D7594A978B0AB6AE4CE3DBFD52A9D00197603FFFDF0000000101"
+#define GMT8_P544_H "8A0A079FC7C3D421A4986FAAA10A6593F60BC94E32AEE8067E35551B86D59F0F61BD6A750917746236DD39CB4710BD44B7BE86F0A8E5324DFE802973060F04BF37C018705B78072182D139A8D2BD338A630511676FDAFD47C60DB5393F9DFC96089B1FFB60B78FB2"
+#define GMT8_P544_MAPU0 "0"
+#define GMT8_P544_MAPU1 "1"
/** @} */
#endif
@@ -478,7 +512,7 @@ static void detect_opt(int *opt, fp2_t a) {
RLC_TRY {
fp2_new(t);
fp2_set_dig(t, 3);
- fp_neg(t[0], t[0]);
+ fp2_neg(t, t);
if (fp2_cmp(a, t) == RLC_EQ) {
*opt = RLC_MIN3;
@@ -523,6 +557,8 @@ void ep2_curve_init(void) {
for (unsigned i = 0; i < 4; ++i) {
fp2_new(ctx->ep2_map_c[i]);
}
+ fp2_new(ctx->ep2_frb[0]);
+ fp2_new(ctx->ep2_frb[1]);
#endif
#ifdef EP_PRECO
@@ -535,8 +571,8 @@ void ep2_curve_init(void) {
#endif
#endif
ep2_set_infty(ctx->ep2_g);
- bn_init(&(ctx->ep2_r), RLC_FP_DIGS);
- bn_init(&(ctx->ep2_h), RLC_FP_DIGS);
+ bn_make(&(ctx->ep2_r), RLC_FP_DIGS);
+ bn_make(&(ctx->ep2_h), RLC_FP_DIGS);
#ifdef EP_CTMAP
iso2_t iso = ep2_curve_get_iso();
@@ -590,6 +626,8 @@ void ep2_curve_clean(void) {
for (unsigned i = 0; i < 4; ++i) {
fp2_free(ctx->ep2_map_c[i]);
}
+ fp2_free(ctx->ep2_frb[0]);
+ fp2_free(ctx->ep2_frb[1]);
}
}
@@ -706,8 +744,7 @@ void ep2_curve_set_twist(int type) {
char str[4 * RLC_FP_BYTES + 1];
ctx_t *ctx = core_get();
ep2_t g;
- fp2_t a;
- fp2_t b, u;
+ fp2_t a, b, u;
bn_t r, h;
ep2_null(g);
@@ -745,6 +782,9 @@ void ep2_curve_set_twist(int type) {
case BN_P256:
ASSIGN(BN_P256);
break;
+ case SM9_P256:
+ ASSIGN(SM9_P256);
+ break;
#elif FP_PRIME == 381
case B12_P381:
ASSIGN(B12_P381);
@@ -757,6 +797,10 @@ void ep2_curve_set_twist(int type) {
case BN_P382:
ASSIGN(BN_P382);
break;
+#elif FP_PRIME == 383
+ case B12_P383:
+ ASSIGN(B12_P383);
+ break;
#elif FP_PRIME == 446
case BN_P446:
ASSIGN(BN_P446);
@@ -773,8 +817,8 @@ void ep2_curve_set_twist(int type) {
ASSIGN(OT8_P511);
break;
#elif FP_PRIME == 544
- case CP8_P544:
- ASSIGN(CP8_P544);
+ case GMT8_P544:
+ ASSIGN(GMT8_P544);
break;
#elif FP_PRIME == 638
case BN_P638:
@@ -791,7 +835,7 @@ void ep2_curve_set_twist(int type) {
}
fp2_zero(g->z);
- fp_set_dig(g->z[0], 1);
+ fp2_set_dig(g->z, 1);
g->coord = BASIC;
ep2_copy(ctx->ep2_g, g);
@@ -808,6 +852,15 @@ void ep2_curve_set_twist(int type) {
/* I don't have a better place for this. */
fp_prime_calc();
+ fp_copy(ctx->ep2_frb[0][0], ctx->fp2_p1[1][0]);
+ fp_copy(ctx->ep2_frb[0][1], ctx->fp2_p1[1][1]);
+ fp_copy(ctx->ep2_frb[1][0], ctx->fp2_p1[2][0]);
+ fp_copy(ctx->ep2_frb[1][1], ctx->fp2_p1[2][1]);
+ if (type == RLC_EP_MTYPE) {
+ fp2_inv(ctx->ep2_frb[0], ctx->ep2_frb[0]);
+ fp2_inv(ctx->ep2_frb[1], ctx->ep2_frb[1]);
+ }
+
/* compute constants for hash-to-curve */
ep2_curve_set_map();
@@ -837,10 +890,8 @@ void ep2_curve_set(fp2_t a, fp2_t b, ep2_t g, bn_t r, bn_t h) {
ctx_t *ctx = core_get();
ctx->ep2_is_twist = 0;
- fp_copy(ctx->ep2_a[0], a[0]);
- fp_copy(ctx->ep2_a[1], a[1]);
- fp_copy(ctx->ep2_b[0], b[0]);
- fp_copy(ctx->ep2_b[1], b[1]);
+ fp2_copy(ctx->ep2_a, a);
+ fp2_copy(ctx->ep2_b, b);
ep2_norm(ctx->ep2_g, g);
bn_copy(&(ctx->ep2_r), r);
diff --git a/contrib/relic/src/epx/relic_ep2_frb.c b/contrib/relic/src/epx/relic_ep2_frb.c
index c2d7e0143..e16be1702 100644
--- a/contrib/relic/src/epx/relic_ep2_frb.c
+++ b/contrib/relic/src/epx/relic_ep2_frb.c
@@ -37,18 +37,14 @@
/*============================================================================*/
void ep2_frb(ep2_t r, ep2_t p, int i) {
+ 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);
- if (ep2_curve_is_twist() == RLC_EP_MTYPE) {
- fp2_mul_frb(r->x, r->x, 1, 4);
- fp2_mul_art(r->x, r->x);
- fp2_mul_art(r->y, r->y);
- } else {
- fp2_mul_frb(r->x, r->x, 1, 2);
- }
- fp2_mul_frb(r->y, r->y, 1, 3);
+ fp2_mul(r->x, r->x, ctx->ep2_frb[0]);
+ fp2_mul(r->y, r->y, ctx->ep2_frb[1]);
}
}
diff --git a/contrib/relic/src/epx/relic_ep2_map.c b/contrib/relic/src/epx/relic_ep2_map.c
index bf45f373f..7764679ab 100644
--- a/contrib/relic/src/epx/relic_ep2_map.c
+++ b/contrib/relic/src/epx/relic_ep2_map.c
@@ -89,83 +89,103 @@ static inline int fp2_sgn0(const fp2_t t, bn_t k) {
/* Public definitions */
/*============================================================================*/
-void ep2_map_dst(ep2_t p, const uint8_t *msg, int len, const uint8_t *dst, int dst_len) {
- bn_t k;
- fp2_t t;
- ep2_t q;
- int neg;
- /* enough space for two extension 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, 4 * len_per_elm);
-
- bn_null(k);
- fp2_null(t);
- ep2_null(q);
-
- RLC_TRY {
- bn_new(k);
- fp2_new(t);
- ep2_new(q);
-
- /* 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;
-
- /* 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 * len_per_elm, msg, len, dst, dst_len);
+void ep2_map_from_field(ep2_t p, const uint8_t *uniform_bytes, int len) {
+ bn_t k;
+ fp2_t t;
+ ep2_t q;
+ int neg;
+ /* enough space for two extension field elements plus extra bytes for uniformity */
+ const int len_per_elm = (FP_PRIME + ep_param_level() + 7) / 8;
+
+ bn_null(k);
+ fp2_null(t);
+ ep2_null(q);
+
+ RLC_TRY {
+ if (len != 2* len_per_elm) {
+ RLC_THROW(ERR_NO_VALID);
+ }
+
+ bn_new(k);
+ fp2_new(t);
+ ep2_new(q);
+
+ /* 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;
#define EP2_MAP_CONVERT_BYTES(IDX) \
- do { \
- bn_read_bin(k, pseudo_random_bytes + 2 * IDX * len_per_elm, len_per_elm); \
- fp_prime_conv(t[0], k); \
- bn_read_bin(k, pseudo_random_bytes + (2 * IDX + 1) * len_per_elm, len_per_elm); \
- fp_prime_conv(t[1], k); \
- } while (0)
+ do { \
+ bn_read_bin(k, uniform_bytes + 2 * IDX * len_per_elm, len_per_elm); \
+ fp_prime_conv(t[0], k); \
+ bn_read_bin(k, uniform_bytes + (2 * IDX + 1) * len_per_elm, len_per_elm); \
+ fp_prime_conv(t[1], k); \
+ } while (0)
#define EP2_MAP_APPLY_MAP(PT) \
- do { \
- /* sign of t */ \
- neg = fp2_sgn0(t, k); \
- /* convert */ \
- map_fn(PT, t); \
- /* compare sign of y to sign of t; fix if necessary */ \
- neg = neg != fp2_sgn0(PT->y, k); \
- fp2_neg(t, PT->y); \
- dv_copy_cond(PT->y[0], t[0], RLC_FP_DIGS, neg); \
- dv_copy_cond(PT->y[1], t[1], RLC_FP_DIGS, neg); \
- } while (0)
+ do { \
+ /* sign of t */ \
+ neg = fp2_sgn0(t, k); \
+ /* convert */ \
+ map_fn(PT, t); \
+ /* compare sign of y to sign of t; fix if necessary */ \
+ neg = neg != fp2_sgn0(PT->y, k); \
+ fp2_neg(t, PT->y); \
+ dv_copy_cond(PT->y[0], t[0], RLC_FP_DIGS, neg); \
+ dv_copy_cond(PT->y[1], t[1], RLC_FP_DIGS, neg); \
+ } while (0)
+
+ /* first map invocation */
+ EP2_MAP_CONVERT_BYTES(0);
+ EP2_MAP_APPLY_MAP(p);
+ TMPL_MAP_CALL_ISOMAP(ep2, p);
+
+ /* second map invocation */
+ EP2_MAP_CONVERT_BYTES(1);
+ EP2_MAP_APPLY_MAP(q);
+ TMPL_MAP_CALL_ISOMAP(ep2, q);
+
+ /* XXX(rsw) could add p and q and then apply isomap,
+ * but need ep_add to support addition on isogeny curves */
- /* first map invocation */
- EP2_MAP_CONVERT_BYTES(0);
- EP2_MAP_APPLY_MAP(p);
- TMPL_MAP_CALL_ISOMAP(ep2, p);
+#undef EP2_MAP_CONVERT_BYTES
+#undef EP2_MAP_APPLY_MAP
- /* second map invocation */
- EP2_MAP_CONVERT_BYTES(1);
- EP2_MAP_APPLY_MAP(q);
- TMPL_MAP_CALL_ISOMAP(ep2, q);
+ /* sum the result */
+ ep2_add(p, p, q);
+ ep2_norm(p, p);
+ ep2_mul_cof(p, p);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ bn_free(k);
+ fp2_free(t);
+ ep2_free(q);
+ }
+}
- /* XXX(rsw) could add p and q and then apply isomap,
- * but need ep_add to support addition on isogeny curves */
-#undef EP2_MAP_CONVERT_BYTES
-#undef EP2_MAP_APPLY_MAP
+void ep2_map_dst(ep2_t p, const uint8_t *msg, int len, const uint8_t *dst, int dst_len) {
- /* sum the result */
- ep2_add(p, p, q);
- ep2_norm(p, p);
- ep2_mul_cof(p, p);
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- bn_free(k);
- fp2_free(t);
- ep2_free(q);
- RLC_FREE(pseudo_random_bytes);
- }
+ /* 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, 4 * len_per_elm);
+
+ RLC_TRY {
+
+ /* 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 * len_per_elm, msg, len, dst, dst_len);
+ ep2_map_from_field(p, pseudo_random_bytes, 2 * len_per_elm);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ RLC_FREE(pseudo_random_bytes);
+ }
}
void ep2_map(ep2_t p, const uint8_t *msg, int len) {
diff --git a/contrib/relic/src/epx/relic_ep2_mul.c b/contrib/relic/src/epx/relic_ep2_mul.c
index 7111f130b..beec8ba86 100644
--- a/contrib/relic/src/epx/relic_ep2_mul.c
+++ b/contrib/relic/src/epx/relic_ep2_mul.c
@@ -41,153 +41,54 @@
#if defined(EP_ENDOM)
static void ep2_mul_glv_imp(ep2_t r, ep2_t p, const bn_t k) {
- int i, j, l;
- bn_t n, _k[4], u[4], v[4];
+ int i, j, l, _l[4];
+ bn_t n, _k[4], u;
+ int8_t naf[4][RLC_FP_BITS + 1];
ep2_t q[4];
bn_null(n);
+ bn_null(u);
RLC_TRY {
bn_new(n);
+ bn_new(u);
for (i = 0; i < 4; i++) {
- bn_null(u[i]);
- bn_null(v[i]);
bn_null(_k[i]);
ep2_null(q[i]);
- bn_new(u[i]);
- bn_new(v[i]);
bn_new(_k[i]);
ep2_new(q[i]);
}
ep2_curve_get_ord(n);
-
- switch (ep_curve_is_pairf()) {
- case EP_BN:
- ep2_curve_get_vs(v);
-
- for (i = 0; i < 4; i++) {
- bn_mul(v[i], v[i], k);
- bn_div(v[i], v[i], n);
- if (bn_sign(v[i]) == RLC_NEG) {
- bn_add_dig(v[i], v[i], 1);
- }
- bn_zero(_k[i]);
- }
-
- /* u0 = x + 1, u1 = 2x + 1, u2 = 2x, u3 = x - 1. */
- fp_prime_get_par(u[0]);
- bn_dbl(u[2], u[0]);
- bn_add_dig(u[1], u[2], 1);
- bn_sub_dig(u[3], u[0], 1);
- bn_add_dig(u[0], u[0], 1);
- bn_copy(_k[0], k);
- for (i = 0; i < 4; i++) {
- bn_mul(u[i], u[i], v[i]);
- bn_mod(u[i], u[i], n);
- bn_add(_k[0], _k[0], n);
- bn_sub(_k[0], _k[0], u[i]);
- bn_mod(_k[0], _k[0], n);
- }
-
- /* u0 = x, u1 = -x, u2 = 2x + 1, u3 = 4x + 2. */
- fp_prime_get_par(u[0]);
- bn_neg(u[1], u[0]);
- bn_dbl(u[2], u[0]);
- bn_add_dig(u[2], u[2], 1);
- bn_dbl(u[3], u[2]);
- for (i = 0; i < 4; i++) {
- bn_mul(u[i], u[i], v[i]);
- bn_mod(u[i], u[i], n);
- bn_add(_k[1], _k[1], n);
- bn_sub(_k[1], _k[1], u[i]);
- bn_mod(_k[1], _k[1], n);
- }
-
- /* u0 = x, u1 = -(x + 1), u2 = 2x + 1, u3 = -(2x - 1). */
- fp_prime_get_par(u[0]);
- bn_add_dig(u[1], u[0], 1);
- bn_neg(u[1], u[1]);
- bn_dbl(u[2], u[0]);
- bn_add_dig(u[2], u[2], 1);
- bn_sub_dig(u[3], u[2], 2);
- bn_neg(u[3], u[3]);
- for (i = 0; i < 4; i++) {
- bn_mul(u[i], u[i], v[i]);
- bn_mod(u[i], u[i], n);
- bn_add(_k[2], _k[2], n);
- bn_sub(_k[2], _k[2], u[i]);
- bn_mod(_k[2], _k[2], n);
- }
-
- /* u0 = -2x, u1 = -x, u2 = 2x + 1, u3 = x - 1. */
- fp_prime_get_par(u[1]);
- bn_dbl(u[0], u[1]);
- bn_neg(u[0], u[0]);
- bn_dbl(u[2], u[1]);
- bn_add_dig(u[2], u[2], 1);
- bn_sub_dig(u[3], u[1], 1);
- bn_neg(u[1], u[1]);
- for (i = 0; i < 4; i++) {
- bn_mul(u[i], u[i], v[i]);
- bn_mod(u[i], u[i], n);
- bn_add(_k[3], _k[3], n);
- bn_sub(_k[3], _k[3], u[i]);
- bn_mod(_k[3], _k[3], n);
- }
-
- for (i = 0; i < 4; i++) {
- l = bn_bits(_k[i]);
- bn_sub(_k[i], n, _k[i]);
- if (bn_bits(_k[i]) > l) {
- bn_sub(_k[i], _k[i], n);
- _k[i]->sign = RLC_POS;
- } else {
- _k[i]->sign = RLC_NEG;
- }
- }
- break;
- default:
- bn_abs(v[0], k);
- fp_prime_get_par(u[0]);
- bn_copy(u[1], u[0]);
- if (bn_sign(u[0]) == RLC_NEG) {
- bn_neg(u[0], u[0]);
- }
-
- for (i = 0; i < 4; i++) {
- bn_mod(_k[i], v[0], u[0]);
- bn_div(v[0], v[0], u[0]);
- if ((bn_sign(u[1]) == RLC_NEG) && (i % 2 != 0)) {
- bn_neg(_k[i], _k[i]);
- }
- if (bn_sign(k) == RLC_NEG) {
- bn_neg(_k[i], _k[i]);
- }
- }
-
- break;
- }
+ fp_prime_get_par(u);
+ bn_mod(_k[0], k, n);
+ bn_rec_frb(_k, 4, _k[0], u, n, ep_curve_is_pairf() == EP_B12);
ep2_norm(q[0], p);
ep2_frb(q[1], q[0], 1);
ep2_frb(q[2], q[1], 1);
ep2_frb(q[3], q[2], 1);
+ l = 0;
for (i = 0; i < 4; i++) {
if (bn_sign(_k[i]) == RLC_NEG) {
ep2_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(bn_bits(_k[0]), bn_bits(_k[1]));
- l = RLC_MAX(l, RLC_MAX(bn_bits(_k[2]), bn_bits(_k[3])));
ep2_set_infty(r);
- for (i = l - 1; i >= 0; i--) {
+ for (j = l - 1; j >= 0; j--) {
ep2_dbl(r, r);
- for (j = 0; j < 4; j++) {
- if (bn_get_bit(_k[j], i)) {
- ep2_add(r, r, q[j]);
+
+ for (i = 0; i < 4; i++) {
+ if (naf[i][j] > 0) {
+ ep2_add(r, r, q[i]);
+ }
+ if (naf[i][j] < 0) {
+ ep2_sub(r, r, q[i]);
}
}
}
@@ -200,9 +101,8 @@ static void ep2_mul_glv_imp(ep2_t r, ep2_t p, const bn_t k) {
}
RLC_FINALLY {
bn_free(n);
+ bn_free(u);
for (i = 0; i < 4; i++) {
- bn_free(u[i]);
- bn_free(v[i]);
bn_free(_k[i]);
ep2_free(q[i]);
}
@@ -440,7 +340,7 @@ void ep2_mul_lwnaf(ep2_t r, ep2_t p, const bn_t k) {
#if defined(EP_ENDOM)
if (ep_curve_is_endom()) {
- if (ep_curve_opt_a() == RLC_ZERO) {
+ if (ep2_curve_opt_a() == RLC_ZERO) {
ep2_mul_glv_imp(r, p, k);
} else {
ep2_mul_naf_imp(r, p, k);
@@ -484,10 +384,13 @@ void ep2_mul_gen(ep2_t r, bn_t k) {
}
void ep2_mul_dig(ep2_t r, ep2_t p, dig_t k) {
- int i, l;
ep2_t t;
+ bn_t _k;
+ int8_t u, naf[RLC_DIG + 1];
+ int l;
ep2_null(t);
+ bn_null(_k);
if (k == 0 || ep2_is_infty(p)) {
ep2_set_infty(r);
@@ -496,15 +399,22 @@ void ep2_mul_dig(ep2_t r, ep2_t p, dig_t k) {
RLC_TRY {
ep2_new(t);
+ bn_new(_k);
- l = util_bits_dig(k);
+ bn_set_dig(_k, k);
- ep2_copy(t, p);
+ l = RLC_DIG + 1;
+ bn_rec_naf(naf, &l, _k, 2);
- for (i = l - 2; i >= 0; i--) {
+ ep2_set_infty(t);
+ for (int i = l - 1; i >= 0; i--) {
ep2_dbl(t, t);
- if (k & ((dig_t)1 << i)) {
+
+ u = naf[i];
+ if (u > 0) {
ep2_add(t, t, p);
+ } else if (u < 0) {
+ ep2_sub(t, t, p);
}
}
@@ -515,5 +425,6 @@ void ep2_mul_dig(ep2_t r, ep2_t p, dig_t k) {
}
RLC_FINALLY {
ep2_free(t);
+ bn_free(_k);
}
}
diff --git a/contrib/relic/src/epx/relic_ep2_mul_cof.c b/contrib/relic/src/epx/relic_ep2_mul_cof.c
index 42a8e3c1c..575c40a17 100644
--- a/contrib/relic/src/epx/relic_ep2_mul_cof.c
+++ b/contrib/relic/src/epx/relic_ep2_mul_cof.c
@@ -24,7 +24,7 @@
/**
* @file
*
- * Implementation of scalar multiplication of a prime elliptic curve over a
+ * Implementation of point multiplication of a prime elliptic curve over a
* quadratic extension by the curve cofactor.
*
* @ingroup epx
diff --git a/contrib/relic/src/epx/relic_ep2_mul_fix.c b/contrib/relic/src/epx/relic_ep2_mul_fix.c
index d16b14dab..fc9e3d9bd 100755
--- a/contrib/relic/src/epx/relic_ep2_mul_fix.c
+++ b/contrib/relic/src/epx/relic_ep2_mul_fix.c
@@ -38,36 +38,6 @@
#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 ep2_mul_pre_ordin(ep2_t *t, ep2_t p) {
- int i;
-
- ep2_dbl(t[0], p);
-#if defined(EP_MIXED)
- ep2_norm(t[0], t[0]);
-#endif
-
-#if EP_DEPTH > 2
- ep2_add(t[1], t[0], p);
- for (i = 2; i < (1 << (EP_DEPTH - 2)); i++) {
- ep2_add(t[i], t[i - 1], t[0]);
- }
-
-#if defined(EP_MIXED)
- for (i = 1; i < (1 << (EP_DEPTH - 2)); i++) {
- ep2_norm(t[i], t[i]);
- }
-#endif
-
-#endif
- ep2_copy(t[0], p);
-}
-
/**
* Multiplies a binary elliptic curve point by an integer using the w-NAF
* method.
@@ -76,7 +46,7 @@ static void ep2_mul_pre_ordin(ep2_t *t, ep2_t p) {
* @param[in] p - the point to multiply.
* @param[in] k - the integer.
*/
-static void ep2_mul_fix_ordin(ep2_t r, ep2_t *table, bn_t k) {
+static void ep2_mul_fix_plain(ep2_t r, ep2_t *table, bn_t k) {
int len, i, n;
int8_t naf[2 * RLC_FP_BITS + 1], *t;
@@ -141,21 +111,38 @@ void ep2_mul_pre_basic(ep2_t *t, ep2_t p) {
}
void ep2_mul_fix_basic(ep2_t r, ep2_t *t, bn_t k) {
+ bn_t n, _k;
+
if (bn_is_zero(k)) {
ep2_set_infty(r);
return;
}
- ep2_set_infty(r);
+ bn_null(n);
+ bn_null(_k);
- for (int i = 0; i < bn_bits(k); i++) {
- if (bn_get_bit(k, i)) {
- ep2_add(r, r, t[i]);
+ RLC_TRY {
+ bn_new(n);
+ bn_new(_k);
+
+ ep2_curve_get_ord(n);
+ bn_mod(_k, k, n);
+
+ ep2_set_infty(r);
+ for (int i = 0; i < bn_bits(_k); i++) {
+ if (bn_get_bit(_k, i)) {
+ ep2_add(r, r, t[i]);
+ }
}
- }
- ep2_norm(r, r);
- if (bn_sign(k) == RLC_NEG) {
- ep2_neg(r, r);
+ ep2_norm(r, r);
+ if (bn_sign(_k) == RLC_NEG) {
+ ep2_neg(r, r);
+ }
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ } RLC_FINALLY {
+ bn_free(n);
+ bn_free(_k);
}
}
@@ -207,7 +194,7 @@ void ep2_mul_pre_combs(ep2_t *t, ep2_t p) {
void ep2_mul_fix_combs(ep2_t r, ep2_t *t, bn_t k) {
int i, j, l, w, n0, p0, p1;
- bn_t n;
+ bn_t n, _k;
if (bn_is_zero(k)) {
ep2_set_infty(r);
@@ -215,15 +202,18 @@ void ep2_mul_fix_combs(ep2_t r, ep2_t *t, bn_t k) {
}
bn_null(n);
+ bn_null(_k);
RLC_TRY {
bn_new(n);
+ bn_new(_k);
ep2_curve_get_ord(n);
l = bn_bits(n);
l = ((l % EP_DEPTH) == 0 ? (l / EP_DEPTH) : (l / EP_DEPTH) + 1);
- n0 = bn_bits(k);
+ bn_mod(_k, k, n);
+ n0 = bn_bits(_k);
p0 = (EP_DEPTH) * l - 1;
@@ -231,7 +221,7 @@ void ep2_mul_fix_combs(ep2_t r, ep2_t *t, bn_t k) {
p1 = p0--;
for (j = EP_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;
}
}
@@ -244,7 +234,7 @@ void ep2_mul_fix_combs(ep2_t r, ep2_t *t, bn_t k) {
p1 = p0--;
for (j = EP_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;
}
}
@@ -253,7 +243,7 @@ void ep2_mul_fix_combs(ep2_t r, ep2_t *t, bn_t k) {
}
}
ep2_norm(r, r);
- if (bn_sign(k) == RLC_NEG) {
+ if (bn_sign(_k) == RLC_NEG) {
ep2_neg(r, r);
}
}
@@ -262,6 +252,7 @@ void ep2_mul_fix_combs(ep2_t r, ep2_t *t, bn_t k) {
}
RLC_FINALLY {
bn_free(n);
+ bn_free(_k);
}
}
@@ -320,7 +311,7 @@ void ep2_mul_pre_combd(ep2_t *t, ep2_t p) {
void ep2_mul_fix_combd(ep2_t r, ep2_t *t, bn_t k) {
int i, j, d, e, w0, w1, n0, p0, p1;
- bn_t n;
+ bn_t n, _k;
if (bn_is_zero(k)) {
ep2_set_infty(r);
@@ -328,6 +319,7 @@ void ep2_mul_fix_combd(ep2_t r, ep2_t *t, bn_t k) {
}
bn_null(n);
+ bn_null(_k);
RLC_TRY {
bn_new(n);
@@ -338,7 +330,8 @@ void ep2_mul_fix_combd(ep2_t r, ep2_t *t, bn_t k) {
e = (d % 2 == 0 ? (d / 2) : (d / 2) + 1);
ep2_set_infty(r);
- n0 = bn_bits(k);
+ bn_mod(_k, k, n);
+ n0 = bn_bits(_k);
p1 = (e - 1) + (EP_DEPTH - 1) * d;
for (i = e - 1; i >= 0; i--) {
@@ -348,7 +341,7 @@ void ep2_mul_fix_combd(ep2_t r, ep2_t *t, bn_t k) {
p0 = p1;
for (j = EP_DEPTH - 1; j >= 0; j--, p0 -= d) {
w0 = w0 << 1;
- if (p0 < n0 && bn_get_bit(k, p0)) {
+ if (p0 < n0 && bn_get_bit(_k, p0)) {
w0 = w0 | 1;
}
}
@@ -357,7 +350,7 @@ void ep2_mul_fix_combd(ep2_t r, ep2_t *t, bn_t k) {
p0 = p1-- + e;
for (j = EP_DEPTH - 1; j >= 0; j--, p0 -= d) {
w1 = w1 << 1;
- if (i + e < d && p0 < n0 && bn_get_bit(k, p0)) {
+ if (i + e < d && p0 < n0 && bn_get_bit(_k, p0)) {
w1 = w1 | 1;
}
}
@@ -366,7 +359,7 @@ void ep2_mul_fix_combd(ep2_t r, ep2_t *t, bn_t k) {
ep2_add(r, r, t[(1 << EP_DEPTH) + w1]);
}
ep2_norm(r, r);
- if (bn_sign(k) == RLC_NEG) {
+ if (bn_sign(_k) == RLC_NEG) {
ep2_neg(r, r);
}
}
@@ -375,6 +368,7 @@ void ep2_mul_fix_combd(ep2_t r, ep2_t *t, bn_t k) {
}
RLC_FINALLY {
bn_free(n);
+ bn_free(_k);
}
}
@@ -383,11 +377,33 @@ void ep2_mul_fix_combd(ep2_t r, ep2_t *t, bn_t k) {
#if EP_FIX == LWNAF || !defined(STRIP)
void ep2_mul_pre_lwnaf(ep2_t *t, ep2_t p) {
- ep2_mul_pre_ordin(t, p);
+ ep2_tab(t, p, EP_DEPTH);
}
void ep2_mul_fix_lwnaf(ep2_t r, ep2_t *t, bn_t k) {
- ep2_mul_fix_ordin(r, t, k);
+ bn_t n, _k;
+
+ if (bn_is_zero(k)) {
+ ep2_set_infty(r);
+ return;
+ }
+
+ bn_null(n);
+ bn_null(_k);
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(_k);
+
+ ep2_curve_get_ord(n);
+ bn_mod(_k, k, n);
+ ep2_mul_fix_plain(r, t, _k);
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ } RLC_FINALLY {
+ bn_free(n);
+ bn_free(_k);
+ }
}
#endif
diff --git a/contrib/relic/src/epx/relic_ep2_mul_sim.c b/contrib/relic/src/epx/relic_ep2_mul_sim.c
index 11911ad5c..f4aa5c64b 100644
--- a/contrib/relic/src/epx/relic_ep2_mul_sim.c
+++ b/contrib/relic/src/epx/relic_ep2_mul_sim.c
@@ -40,146 +40,6 @@
#if defined(EP_ENDOM)
-/**
- * Recodes a scalar in subscalars according to Frobenius endomorphism.
- *
- * @param[out] _k - the recoded subscalars.
- * @param[in] k - the scalar to recode.
- */
-static void ep2_glv(bn_t _k[4], const bn_t k) {
- int i, l;
- bn_t n, u[4], v[4];
-
- bn_null(n);
-
- RLC_TRY {
- bn_new(n);
- for (i = 0; i < 4; i++) {
- bn_null(u[i]);
- bn_null(v[i]);
- bn_new(u[i]);
- bn_new(v[i]);
- }
-
- ep2_curve_get_ord(n);
-
- switch (ep_curve_is_pairf()) {
- case EP_BN:
- ep2_curve_get_vs(v);
-
- for (i = 0; i < 4; i++) {
- bn_mul(v[i], v[i], k);
- bn_div(v[i], v[i], n);
- if (bn_sign(v[i]) == RLC_NEG) {
- bn_add_dig(v[i], v[i], 1);
- }
- bn_zero(_k[i]);
- }
-
- /* u0 = x + 1, u1 = 2x + 1, u2 = 2x, u3 = x - 1. */
- fp_prime_get_par(u[0]);
- bn_dbl(u[2], u[0]);
- bn_add_dig(u[1], u[2], 1);
- bn_sub_dig(u[3], u[0], 1);
- bn_add_dig(u[0], u[0], 1);
- bn_copy(_k[0], k);
- for (i = 0; i < 4; i++) {
- bn_mul(u[i], u[i], v[i]);
- bn_mod(u[i], u[i], n);
- bn_add(_k[0], _k[0], n);
- bn_sub(_k[0], _k[0], u[i]);
- bn_mod(_k[0], _k[0], n);
- }
-
- /* u0 = x, u1 = -x, u2 = 2x + 1, u3 = 4x + 2. */
- fp_prime_get_par(u[0]);
- bn_neg(u[1], u[0]);
- bn_dbl(u[2], u[0]);
- bn_add_dig(u[2], u[2], 1);
- bn_dbl(u[3], u[2]);
- for (i = 0; i < 4; i++) {
- bn_mul(u[i], u[i], v[i]);
- bn_mod(u[i], u[i], n);
- bn_add(_k[1], _k[1], n);
- bn_sub(_k[1], _k[1], u[i]);
- bn_mod(_k[1], _k[1], n);
- }
-
- /* u0 = x, u1 = -(x + 1), u2 = 2x + 1, u3 = -(2x - 1). */
- fp_prime_get_par(u[0]);
- bn_add_dig(u[1], u[0], 1);
- bn_neg(u[1], u[1]);
- bn_dbl(u[2], u[0]);
- bn_add_dig(u[2], u[2], 1);
- bn_sub_dig(u[3], u[2], 2);
- bn_neg(u[3], u[3]);
- for (i = 0; i < 4; i++) {
- bn_mul(u[i], u[i], v[i]);
- bn_mod(u[i], u[i], n);
- bn_add(_k[2], _k[2], n);
- bn_sub(_k[2], _k[2], u[i]);
- bn_mod(_k[2], _k[2], n);
- }
-
- /* u0 = -2x, u1 = -x, u2 = 2x + 1, u3 = x - 1. */
- fp_prime_get_par(u[1]);
- bn_dbl(u[0], u[1]);
- bn_neg(u[0], u[0]);
- bn_dbl(u[2], u[1]);
- bn_add_dig(u[2], u[2], 1);
- bn_sub_dig(u[3], u[1], 1);
- bn_neg(u[1], u[1]);
- for (i = 0; i < 4; i++) {
- bn_mul(u[i], u[i], v[i]);
- bn_mod(u[i], u[i], n);
- bn_add(_k[3], _k[3], n);
- bn_sub(_k[3], _k[3], u[i]);
- bn_mod(_k[3], _k[3], n);
- }
-
- for (i = 0; i < 4; i++) {
- l = bn_bits(_k[i]);
- bn_sub(_k[i], n, _k[i]);
- if (bn_bits(_k[i]) > l) {
- bn_sub(_k[i], _k[i], n);
- _k[i]->sign = RLC_POS;
- } else {
- _k[i]->sign = RLC_NEG;
- }
- }
- break;
- default:
- bn_abs(v[0], k);
- fp_prime_get_par(u[0]);
- bn_copy(u[1], u[0]);
- if (bn_sign(u[0]) == RLC_NEG) {
- bn_neg(u[0], u[0]);
- }
-
- for (i = 0; i < 4; i++) {
- bn_mod(_k[i], v[0], u[0]);
- bn_div(v[0], v[0], u[0]);
- if ((bn_sign(u[1]) == RLC_NEG) && (i % 2 != 0)) {
- bn_neg(_k[i], _k[i]);
- }
- if (bn_sign(k) == RLC_NEG) {
- bn_neg(_k[i], _k[i]);
- }
- }
-
- break;
- }
- } RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- } RLC_FINALLY {
- bn_free(n);
- for (i = 0; i < 4; i++) {
- bn_free(u[i]);
- bn_free(v[i]);
- }
- }
-}
-
/**
* Multiplies and adds two prime elliptic curve points simultaneously,
* optionally choosing the first point as the generator depending on an optional
@@ -194,10 +54,15 @@ static void ep2_glv(bn_t _k[4], const bn_t k) {
*/
static void ep2_mul_sim_endom(ep2_t r, ep2_t p, const bn_t k, ep2_t q, const bn_t m) {
int i, j, l;
- bn_t _k[4], _m[4];
+ bn_t n, u, _k[4], _m[4];
ep2_t _p[4], _q[4];
+ bn_null(n);
+ bn_null(u);
+
RLC_TRY {
+ bn_new(n);
+ bn_new(u);
for (i = 0; i < 4; i++) {
bn_null(_k[i]);
bn_null(_m[i]);
@@ -209,8 +74,10 @@ static void ep2_mul_sim_endom(ep2_t r, ep2_t p, const bn_t k, ep2_t q, const bn_
ep2_new(_q[i]);
}
- ep2_glv(_k, k);
- ep2_glv(_m, m);
+ ep2_curve_get_ord(n);
+ fp_prime_get_par(u);
+ bn_rec_frb(_k, 4, k, u, n, ep_curve_is_pairf() == EP_B12);
+ bn_rec_frb(_m, 4, m, u, n, ep_curve_is_pairf() == EP_B12);
ep2_norm(_p[0], p);
ep2_frb(_p[1], _p[0], 1);
@@ -253,6 +120,8 @@ static void ep2_mul_sim_endom(ep2_t r, ep2_t p, const bn_t k, ep2_t q, const bn_
} RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
} RLC_FINALLY {
+ bn_free(n);
+ bn_free(u);
for (i = 0; i < 4; i++) {
bn_free(_k[i]);
bn_free(_m[i]);
@@ -315,13 +184,6 @@ static void ep2_mul_sim_plain(ep2_t r, ep2_t p, bn_t k, ep2_t q, bn_t m,
l = RLC_MAX(l0, l1);
_k = naf0 + l - 1;
_m = naf1 + l - 1;
- for (i = l0; i < l; i++) {
- naf0[i] = 0;
- }
- for (i = l1; i < l; i++) {
- naf1[i] = 0;
- }
-
if (bn_sign(k) == RLC_NEG) {
for (i = 0; i < l0; i++) {
naf0[i] = -naf0[i];
@@ -407,11 +269,13 @@ void ep2_mul_sim_trick(ep2_t r, ep2_t p, bn_t k, ep2_t q, bn_t m) {
ep2_t t0[1 << (EP_WIDTH / 2)];
ep2_t t1[1 << (EP_WIDTH / 2)];
ep2_t t[1 << EP_WIDTH];
- bn_t n;
+ bn_t n, _k, _m;
int l0, l1, w = EP_WIDTH / 2;
uint8_t w0[2 * RLC_FP_BITS], w1[2 * RLC_FP_BITS];
bn_null(n);
+ bn_null(_k);
+ bn_null(_m);
if (bn_is_zero(k) || ep2_is_infty(p)) {
ep2_mul(r, q, m);
@@ -424,8 +288,12 @@ void ep2_mul_sim_trick(ep2_t r, ep2_t p, bn_t k, ep2_t q, bn_t m) {
RLC_TRY {
bn_new(n);
+ bn_new(_k);
+ bn_new(_m);
ep2_curve_get_ord(n);
+ bn_mod(_k, k, n);
+ bn_mod(_m, m, n);
for (int i = 0; i < (1 << w); i++) {
ep2_null(t0[i]);
@@ -490,6 +358,8 @@ void ep2_mul_sim_trick(ep2_t r, ep2_t p, bn_t k, ep2_t q, bn_t m) {
}
RLC_FINALLY {
bn_free(n);
+ bn_free(_k);
+ bn_free(_m);
for (int i = 0; i < (1 << w); i++) {
ep2_free(t0[i]);
ep2_free(t1[i]);
@@ -504,6 +374,9 @@ void ep2_mul_sim_trick(ep2_t r, ep2_t p, bn_t k, ep2_t q, bn_t m) {
#if EP_SIM == INTER || !defined(STRIP)
void ep2_mul_sim_inter(ep2_t r, ep2_t p, bn_t k, ep2_t q, bn_t m) {
+ int flag = 0;
+ bn_t n, _k, _m;
+
if (bn_is_zero(k) || ep2_is_infty(p)) {
ep2_mul(r, q, m);
return;
@@ -513,20 +386,41 @@ void ep2_mul_sim_inter(ep2_t r, ep2_t p, bn_t k, ep2_t q, bn_t m) {
return;
}
+ bn_null(n);
+ bn_null(_k);
+ bn_null(_m);
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(_k);
+ bn_new(_m);
+
+ /* Handle this here to reduce complexity of static functions. */
+ ep2_curve_get_ord(n);
+ bn_mod(_k, k, n);
+ bn_mod(_m, m, n);
+
#if defined(EP_ENDOM)
- if (ep_curve_is_endom()) {
- if (ep_curve_opt_a() == RLC_ZERO) {
- ep2_mul_sim_endom(r, p, k, q, m);
- } else {
- ep2_mul_sim_plain(r, p, k, q, m, NULL);
+ if (ep_curve_is_endom()) {
+ ep2_mul_sim_endom(r, p, _k, q, _m);
+ flag = 1;
}
- return;
- }
#endif
-#if defined(EP_PLAIN)
- ep2_mul_sim_plain(r, p, k, q, m, NULL);
+#if defined(EP_PLAIN) || defined(EP_SUPER)
+ if (!flag) {
+ ep2_mul_sim_plain(r, p, _k, q, _m, NULL);
+ }
#endif
+ (void)flag;
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ bn_free(_k);
+ bn_free(_m);
+ }
}
#endif
@@ -534,9 +428,10 @@ void ep2_mul_sim_inter(ep2_t r, ep2_t p, bn_t k, ep2_t q, bn_t m) {
#if EP_SIM == JOINT || !defined(STRIP)
void ep2_mul_sim_joint(ep2_t r, ep2_t p, bn_t k, ep2_t q, bn_t m) {
+ bn_t n, _k, _m;
ep2_t t[5];
int i, l, u_i, offset;
- int8_t jsf[4 * (RLC_FP_BITS + 1)];
+ int8_t jsf[2 * (RLC_FP_BITS + 1)];
if (bn_is_zero(k) || ep2_is_infty(p)) {
ep2_mul(r, q, m);
@@ -547,19 +442,30 @@ void ep2_mul_sim_joint(ep2_t r, ep2_t p, bn_t k, ep2_t q, bn_t m) {
return;
}
+ bn_null(n);
+ bn_null(_k);
+ bn_null(_m);
+
RLC_TRY {
+ bn_new(n);
+ bn_new(_k);
+ bn_new(_m);
for (i = 0; i < 5; i++) {
ep2_null(t[i]);
ep2_new(t[i]);
}
+ ep2_curve_get_ord(n);
+ bn_mod(_k, k, n);
+ bn_mod(_m, m, n);
+
ep2_set_infty(t[0]);
ep2_copy(t[1], q);
- if (bn_sign(m) == RLC_NEG) {
+ if (bn_sign(_m) == RLC_NEG) {
ep2_neg(t[1], t[1]);
}
ep2_copy(t[2], p);
- if (bn_sign(k) == RLC_NEG) {
+ if (bn_sign(_k) == RLC_NEG) {
ep2_neg(t[2], t[2]);
}
ep2_add(t[3], t[2], t[1]);
@@ -568,12 +474,12 @@ void ep2_mul_sim_joint(ep2_t r, ep2_t p, bn_t k, ep2_t q, bn_t m) {
ep2_norm_sim(t + 3, t + 3, 2);
#endif
- l = 4 * (RLC_FP_BITS + 1);
- bn_rec_jsf(jsf, &l, k, m);
+ l = 2 * (RLC_FP_BITS + 1);
+ bn_rec_jsf(jsf, &l, _k, _m);
ep2_set_infty(r);
- offset = RLC_MAX(bn_bits(k), bn_bits(m)) + 1;
+ offset = RLC_MAX(bn_bits(_k), bn_bits(_m)) + 1;
for (i = l - 1; i >= 0; i--) {
ep2_dbl(r, r);
if (jsf[i] != 0 && jsf[i] == -jsf[i + offset]) {
@@ -598,6 +504,9 @@ void ep2_mul_sim_joint(ep2_t r, ep2_t p, bn_t k, ep2_t q, bn_t m) {
RLC_THROW(ERR_CAUGHT);
}
RLC_FINALLY {
+ bn_free(n);
+ bn_free(_k);
+ bn_free(_m);
for (i = 0; i < 5; i++) {
ep2_free(t[i]);
}
@@ -607,9 +516,8 @@ void ep2_mul_sim_joint(ep2_t r, ep2_t p, bn_t k, ep2_t q, bn_t m) {
#endif
void ep2_mul_sim_gen(ep2_t r, bn_t k, ep2_t q, bn_t m) {
- ep2_t gen;
-
- ep2_null(gen);
+ ep2_t g;
+ bn_t n, _k, _m;
if (bn_is_zero(k)) {
ep2_mul(r, q, m);
@@ -620,21 +528,55 @@ void ep2_mul_sim_gen(ep2_t r, bn_t k, ep2_t q, bn_t m) {
return;
}
+ ep2_null(g);
+ bn_null(n);
+ bn_null(_k);
+ bn_null(_m);
+
RLC_TRY {
- ep2_new(gen);
+ ep2_new(g);
+ bn_new(n);
+ bn_new(_k);
+ bn_new(_m);
+
+ ep2_curve_get_gen(g);
+ ep2_curve_get_ord(n);
+
+ bn_mod(_k, k, n);
+ bn_mod(_m, m, n);
- ep2_curve_get_gen(gen);
-#if EP_FIX == LWNAF && defined(EP_PRECO)
- ep2_mul_sim_plain(r, gen, k, q, m, ep2_curve_get_tab());
+#if defined(EP_ENDOM)
+#if EP_SIM == INTER && EP_FIX == LWNAF && defined(EP_PRECO)
+ if (ep_curve_is_endom()) {
+ ep2_mul_sim_endom(r, g, _k, q, _m, ep2_curve_get_tab());
+ }
#else
- ep2_mul_sim(r, gen, k, q, m);
+ if (ep_curve_is_endom()) {
+ ep2_mul_sim(r, g, _k, q, _m);
+ }
+#endif
+#endif
+
+#if defined(EP_PLAIN) || defined(EP_SUPER)
+#if EP_SIM == INTER && EP_FIX == LWNAF && defined(EP_PRECO)
+ if (!ep_curve_is_endom()) {
+ ep2_mul_sim_plain(r, g, _k, q, _m, ep2_curve_get_tab());
+ }
+#else
+ if (!ep_curve_is_endom()) {
+ ep2_mul_sim(r, g, _k, q, _m);
+ }
+#endif
#endif
}
RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
}
RLC_FINALLY {
- ep2_free(gen);
+ ep2_free(g);
+ bn_free(n);
+ bn_free(_k);
+ bn_free(_m);
}
}
@@ -674,14 +616,27 @@ void ep2_mul_sim_dig(ep2_t r, ep2_t p[], dig_t k[], int len) {
void ep2_mul_sim_lot(ep2_t r, ep2_t p[], const bn_t k[], int n) {
const int len = RLC_FP_BITS + 1;
- int i, j, m, l, *_l = RLC_ALLOCA(int, 4 * n);
- bn_t _k[4];
- int8_t *naf = RLC_ALLOCA(int8_t, 4 * n * len);
+ int i, j, m, l, _l[4];
+ bn_t _k[4], q, x;
+ int8_t ptr, *naf = RLC_ALLOCA(int8_t, 4 * n * len);
+
+ if (n == 0) {
+ ep2_set_infty(r);
+ return;
+ }
+
+ bn_null(q);
+ bn_null(x);
if (n <= 10) {
ep2_t *_p = RLC_ALLOCA(ep2_t, 4 * n);
RLC_TRY {
+ if (naf == NULL || _p == NULL) {
+ RLC_THROW(ERR_NO_MEMORY);
+ }
+ bn_new(q);
+ bn_new(x);
for (j = 0; j < 4; j++) {
bn_null(_k[j]);
bn_new(_k[j]);
@@ -691,31 +646,24 @@ void ep2_mul_sim_lot(ep2_t r, ep2_t p[], const bn_t k[], int n) {
}
}
- for (int i = 0; i < n; i++) {
+ l = 0;
+ ep2_curve_get_ord(q);
+ fp_prime_get_par(x);
+ for (i = 0; i < n; i++) {
ep2_norm(_p[4*i], p[i]);
ep2_frb(_p[4*i + 1], _p[4*i], 1);
ep2_frb(_p[4*i + 2], _p[4*i + 1], 1);
ep2_frb(_p[4*i + 3], _p[4*i + 2], 1);
- }
- l = 0;
- for (i = 0; i < n; i++) {
- ep2_glv(_k, k[i]);
+ bn_mod(_k[0], k[i], q);
+ bn_rec_frb(_k, 4, _k[0], x, q, ep_curve_is_pairf() == EP_B12);
for (j = 0; j < 4; j++) {
- _l[4*i + j] = len;
- bn_rec_naf(&naf[(4*i + j)*len], &_l[4*i + j], _k[j], 2);
+ _l[j] = len;
+ bn_rec_naf(&naf[(4*i + j)*len], &_l[j], _k[j], 2);
if (bn_sign(_k[j]) == RLC_NEG) {
ep2_neg(_p[4*i + j], _p[4*i + j]);
}
- l = RLC_MAX(l, _l[4*i + j]);
- }
- }
-
- for (i = 0; i < n; i++) {
- for (j = 0; j < 4; j++) {
- for (m = _l[4*i + j]; m < l; m++) {
- naf[(4*i + j)*len + m] = 0;
- }
+ l = RLC_MAX(l, _l[j]);
}
}
@@ -739,26 +687,32 @@ void ep2_mul_sim_lot(ep2_t r, ep2_t p[], const bn_t k[], int n) {
} RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
} RLC_FINALLY {
+ bn_free(q);
+ bn_free(x);
for (j = 0; j < 4; j++) {
bn_free(_k[j]);
for (i = 0; i < n; i++) {
ep2_free(_p[4*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));
ep2_t s, t, u, v, *_p = RLC_ALLOCA(ep2_t, 4 * c);
- int8_t ptr;
+
+ ep2_null(s);
+ ep2_null(t);
+ ep2_null(u);
+ ep2_null(v);
RLC_TRY {
- ep2_null(s);
- ep2_null(t);
- ep2_null(u);
- ep2_null(v);
+ if (naf == NULL || _p == NULL) {
+ RLC_THROW(ERR_NO_MEMORY);
+ }
+ bn_new(q);
+ bn_new(x);
ep2_new(s);
ep2_new(t);
ep2_new(u);
@@ -774,20 +728,20 @@ void ep2_mul_sim_lot(ep2_t r, ep2_t p[], const bn_t k[], int n) {
}
l = 0;
+ ep2_curve_get_ord(q);
+ fp_prime_get_par(x);
for (i = 0; i < n; i++) {
- ep2_glv(_k, k[i]);
+ bn_mod(_k[0], k[i], q);
+ bn_rec_frb(_k, 4, _k[0], x, q, ep_curve_is_pairf() == EP_B12);
for (j = 0; j < 4; j++) {
- _l[4*i + j] = len;
- bn_rec_naf(&naf[(4*i + j)*len], &_l[4*i + j], _k[j], w);
- l = RLC_MAX(l, _l[4*i + j]);
- }
- }
-
- for (i = 0; i < n; i++) {
- for (j = 0; j < 4; j++) {
- for (m = _l[4*i + j]; m < l; m++) {
- naf[(4*i + j)*len + m] = 0;
+ _l[j] = len;
+ bn_rec_naf(&naf[(4*i + j)*len], &_l[j], _k[j], w);
+ if (bn_sign(_k[j]) == RLC_NEG) {
+ for (m = 0; m < _l[j]; m++) {
+ naf[(4*i + j)*len + m] = -naf[(4*i + j)*len + m];
+ }
}
+ l = RLC_MAX(l, _l[j]);
}
}
@@ -802,9 +756,6 @@ void ep2_mul_sim_lot(ep2_t r, ep2_t p[], const bn_t k[], int n) {
ptr = -ptr;
ep2_neg(t, t);
}
- if (bn_sign(_k[m]) == RLC_NEG) {
- ep2_neg(t, t);
- }
ep2_add(_p[m*c + (ptr >> 1)], _p[m*c + (ptr >> 1)], t);
}
}
@@ -834,6 +785,8 @@ void ep2_mul_sim_lot(ep2_t r, ep2_t p[], const bn_t k[], int n) {
} RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
} RLC_FINALLY {
+ bn_free(q);
+ bn_free(x);
ep2_free(s);
ep2_free(t);
ep2_free(u);
@@ -844,7 +797,6 @@ void ep2_mul_sim_lot(ep2_t r, ep2_t p[], const bn_t k[], int n) {
ep2_free(_p[i*c + j]);
}
}
- RLC_FREE(_l);
RLC_FREE(_p);
RLC_FREE(naf);
}
diff --git a/contrib/relic/src/epx/relic_ep2_pck.c b/contrib/relic/src/epx/relic_ep2_pck.c
index 0aab817f3..09282756b 100644
--- a/contrib/relic/src/epx/relic_ep2_pck.c
+++ b/contrib/relic/src/epx/relic_ep2_pck.c
@@ -27,7 +27,7 @@
* Implementation of point compression on prime elliptic curves over quadratic
* extensions.
*
- * @ingroup ep
+ * @ingroup epx
*/
#include "relic_core.h"
diff --git a/contrib/relic/src/epx/relic_ep2_util.c b/contrib/relic/src/epx/relic_ep2_util.c
index 571b26a8b..8f1490b37 100644
--- a/contrib/relic/src/epx/relic_ep2_util.c
+++ b/contrib/relic/src/epx/relic_ep2_util.c
@@ -85,17 +85,17 @@ void ep2_blind(ep2_t r, ep2_t p) {
RLC_TRY {
fp2_new(rand);
+ fp2_rand(rand);
#if EP_ADD == BASIC
(void)rand;
ep2_copy(r, p);
-#elif EP_ADD == PROJC
- fp2_rand(rand);
+#else
fp2_mul(r->z, p->z, rand);
fp2_mul(r->y, p->y, rand);
fp2_sqr(rand, rand);
fp2_mul(r->x, r->x, rand);
fp2_mul(r->y, r->y, rand);
- r->coord = PROJC;
+ r->coord = EP_ADD;
#endif
} RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
@@ -260,8 +260,7 @@ void ep2_read_bin(ep2_t a, const uint8_t *bin, int len) {
}
a->coord = BASIC;
- fp_set_dig(a->z[0], 1);
- fp_zero(a->z[1]);
+ fp2_set_dig(a->z, 1);
fp2_read_bin(a->x, bin + 1, 2 * RLC_FP_BYTES);
if (len == 2 * RLC_FP_BYTES + 1) {
switch(bin[0]) {
@@ -288,6 +287,10 @@ void ep2_read_bin(ep2_t a, const uint8_t *bin, int len) {
return;
}
}
+
+ if (!ep2_on_curve(a)) {
+ RLC_THROW(ERR_NO_VALID);
+ }
}
void ep2_write_bin(uint8_t *bin, int len, ep2_t a, int pack) {
@@ -295,12 +298,13 @@ void ep2_write_bin(uint8_t *bin, int len, ep2_t a, int pack) {
ep2_null(t);
+ memset(bin, 0, len);
+
if (ep2_is_infty(a)) {
if (len < 1) {
RLC_THROW(ERR_NO_BUFFER);
return;
} else {
- bin[0] = 0;
return;
}
}
diff --git a/contrib/relic/src/epx/relic_ep4_add.c b/contrib/relic/src/epx/relic_ep4_add.c
new file mode 100644
index 000000000..af731a5ea
--- /dev/null
+++ b/contrib/relic/src/epx/relic_ep4_add.c
@@ -0,0 +1,434 @@
+/*
+ * RELIC is an Efficient LIbrary for Cryptography
+ * Copyright (c) 2021 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 ep4_add_basic_imp(ep4_t r, fp4_t s, ep4_t p, ep4_t q) {
+ fp4_t t0, t1, t2;
+
+ fp4_null(t0);
+ fp4_null(t1);
+ fp4_null(t2);
+
+ RLC_TRY {
+ fp4_new(t0);
+ fp4_new(t1);
+ fp4_new(t2);
+
+ /* t0 = x2 - x1. */
+ fp4_sub(t0, q->x, p->x);
+ /* t1 = y2 - y1. */
+ fp4_sub(t1, q->y, p->y);
+
+ /* If t0 is zero. */
+ if (fp4_is_zero(t0)) {
+ if (fp4_is_zero(t1)) {
+ /* If t1 is zero, q = p, should have doubled. */
+ ep4_dbl_slp_basic(r, s, p);
+ } else {
+ /* If t1 is not zero and t0 is zero, q = -p and r = infty. */
+ ep4_set_infty(r);
+ }
+ } else {
+ /* t2 = 1/(x2 - x1). */
+ fp4_inv(t2, t0);
+ /* t2 = lambda = (y2 - y1)/(x2 - x1). */
+ fp4_mul(t2, t1, t2);
+
+ /* x3 = lambda^2 - x2 - x1. */
+ fp4_sqr(t1, t2);
+ fp4_sub(t0, t1, p->x);
+ fp4_sub(t0, t0, q->x);
+
+ /* y3 = lambda * (x1 - x3) - y1. */
+ fp4_sub(t1, p->x, t0);
+ fp4_mul(t1, t2, t1);
+ fp4_sub(r->y, t1, p->y);
+
+ fp4_copy(r->x, t0);
+ fp4_copy(r->z, p->z);
+
+ if (s != NULL) {
+ fp4_copy(s, t2);
+ }
+
+ r->coord = BASIC;
+ }
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ fp4_free(t0);
+ fp4_free(t1);
+ fp4_free(t2);
+ }
+}
+
+#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 ep4_add_projc_mix(ep4_t r, ep4_t p, ep4_t q) {
+ fp4_t t0, t1, t2, t3, t4, t5, t6;
+
+ fp4_null(t0);
+ fp4_null(t1);
+ fp4_null(t2);
+ fp4_null(t3);
+ fp4_null(t4);
+ fp4_null(t5);
+ fp4_null(t6);
+
+ RLC_TRY {
+ fp4_new(t0);
+ fp4_new(t1);
+ fp4_new(t2);
+ fp4_new(t3);
+ fp4_new(t4);
+ fp4_new(t5);
+ fp4_new(t6);
+
+ if (p->coord != BASIC) {
+ /* t0 = z1^2. */
+ fp4_sqr(t0, p->z);
+
+ /* t3 = U2 = x2 * z1^2. */
+ fp4_mul(t3, q->x, t0);
+
+ /* t1 = S2 = y2 * z1^3. */
+ fp4_mul(t1, t0, p->z);
+ fp4_mul(t1, t1, q->y);
+
+ /* t3 = H = U2 - x1. */
+ fp4_sub(t3, t3, p->x);
+
+ /* t1 = R = 2 * (S2 - y1). */
+ fp4_sub(t1, t1, p->y);
+ } else {
+ /* H = x2 - x1. */
+ fp4_sub(t3, q->x, p->x);
+
+ /* t1 = R = 2 * (y2 - y1). */
+ fp4_sub(t1, q->y, p->y);
+ }
+
+ /* t2 = HH = H^2. */
+ fp4_sqr(t2, t3);
+
+ /* If E is zero. */
+ if (fp4_is_zero(t3)) {
+ if (fp4_is_zero(t1)) {
+ /* If I is zero, p = q, should have doubled. */
+ ep4_dbl_projc(r, p);
+ } else {
+ /* If I is not zero, q = -p, r = infinity. */
+ ep4_set_infty(r);
+ }
+ } else {
+ /* t5 = J = H * HH. */
+ fp4_mul(t5, t3, t2);
+
+ /* t4 = V = x1 * HH. */
+ fp4_mul(t4, p->x, t2);
+
+ /* x3 = R^2 - J - 2 * V. */
+ fp4_sqr(r->x, t1);
+ fp4_sub(r->x, r->x, t5);
+ fp4_dbl(t6, t4);
+ fp4_sub(r->x, r->x, t6);
+
+ /* y3 = R * (V - x3) - Y1 * J. */
+ fp4_sub(t4, t4, r->x);
+ fp4_mul(t4, t4, t1);
+ fp4_mul(t1, p->y, t5);
+ fp4_sub(r->y, t4, t1);
+
+ if (p->coord != BASIC) {
+ /* z3 = z1 * H. */
+ fp4_mul(r->z, p->z, t3);
+ } else {
+ /* z3 = H. */
+ fp4_copy(r->z, t3);
+ }
+ }
+ r->coord = PROJC;
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ fp4_free(t0);
+ fp4_free(t1);
+ fp4_free(t2);
+ fp4_free(t3);
+ fp4_free(t4);
+ fp4_free(t5);
+ fp4_free(t6);
+ }
+}
+
+#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 ep4_add_projc_imp(ep4_t r, ep4_t p, ep4_t q) {
+#if defined(EP_MIXED) && defined(STRIP)
+ ep4_add_projc_mix(r, p, q);
+#else /* General addition. */
+ fp4_t t0, t1, t2, t3, t4, t5, t6;
+
+ fp4_null(t0);
+ fp4_null(t1);
+ fp4_null(t2);
+ fp4_null(t3);
+ fp4_null(t4);
+ fp4_null(t5);
+ fp4_null(t6);
+
+ RLC_TRY {
+ fp4_new(t0);
+ fp4_new(t1);
+ fp4_new(t2);
+ fp4_new(t3);
+ fp4_new(t4);
+ fp4_new(t5);
+ fp4_new(t6);
+
+ if (q->coord == BASIC) {
+ ep4_add_projc_mix(r, p, q);
+ } else {
+ /* t0 = z1^2. */
+ fp4_sqr(t0, p->z);
+
+ /* t1 = z2^2. */
+ fp4_sqr(t1, q->z);
+
+ /* t2 = U1 = x1 * z2^2. */
+ fp4_mul(t2, p->x, t1);
+
+ /* t3 = U2 = x2 * z1^2. */
+ fp4_mul(t3, q->x, t0);
+
+ /* t6 = z1^2 + z2^2. */
+ fp4_add(t6, t0, t1);
+
+ /* t0 = S2 = y2 * z1^3. */
+ fp4_mul(t0, t0, p->z);
+ fp4_mul(t0, t0, q->y);
+
+ /* t1 = S1 = y1 * z2^3. */
+ fp4_mul(t1, t1, q->z);
+ fp4_mul(t1, t1, p->y);
+
+ /* t3 = H = U2 - U1. */
+ fp4_sub(t3, t3, t2);
+
+ /* t0 = R = 2 * (S2 - S1). */
+ fp4_sub(t0, t0, t1);
+
+ fp4_dbl(t0, t0);
+
+ /* If E is zero. */
+ if (fp4_is_zero(t3)) {
+ if (fp4_is_zero(t0)) {
+ /* If I is zero, p = q, should have doubled. */
+ ep4_dbl_projc(r, p);
+ } else {
+ /* If I is not zero, q = -p, r = infinity. */
+ ep4_set_infty(r);
+ }
+ } else {
+ /* t4 = I = (2*H)^2. */
+ fp4_dbl(t4, t3);
+ fp4_sqr(t4, t4);
+
+ /* t5 = J = H * I. */
+ fp4_mul(t5, t3, t4);
+
+ /* t4 = V = U1 * I. */
+ fp4_mul(t4, t2, t4);
+
+ /* x3 = R^2 - J - 2 * V. */
+ fp4_sqr(r->x, t0);
+ fp4_sub(r->x, r->x, t5);
+ fp4_dbl(t2, t4);
+ fp4_sub(r->x, r->x, t2);
+
+ /* y3 = R * (V - x3) - 2 * S1 * J. */
+ fp4_sub(t4, t4, r->x);
+ fp4_mul(t4, t4, t0);
+ fp4_mul(t1, t1, t5);
+ fp4_dbl(t1, t1);
+ fp4_sub(r->y, t4, t1);
+
+ /* z3 = ((z1 + z2)^2 - z1^2 - z2^2) * H. */
+ fp4_add(r->z, p->z, q->z);
+ fp4_sqr(r->z, r->z);
+ fp4_sub(r->z, r->z, t6);
+ fp4_mul(r->z, r->z, t3);
+ }
+ }
+ r->coord = PROJC;
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ fp4_free(t0);
+ fp4_free(t1);
+ fp4_free(t2);
+ fp4_free(t3);
+ fp4_free(t4);
+ fp4_free(t5);
+ fp4_free(t6);
+ }
+#endif
+}
+
+#endif /* EP_ADD == PROJC */
+
+/*============================================================================*/
+ /* Public definitions */
+/*============================================================================*/
+
+#if EP_ADD == BASIC || !defined(STRIP)
+
+void ep4_add_basic(ep4_t r, ep4_t p, ep4_t q) {
+ if (ep4_is_infty(p)) {
+ ep4_copy(r, q);
+ return;
+ }
+
+ if (ep4_is_infty(q)) {
+ ep4_copy(r, p);
+ return;
+ }
+
+ ep4_add_basic_imp(r, NULL, p, q);
+}
+
+void ep4_add_slp_basic(ep4_t r, fp4_t s, ep4_t p, ep4_t q) {
+ if (ep4_is_infty(p)) {
+ ep4_copy(r, q);
+ return;
+ }
+
+ if (ep4_is_infty(q)) {
+ ep4_copy(r, p);
+ return;
+ }
+
+ ep4_add_basic_imp(r, s, p, q);
+}
+
+#endif
+
+#if EP_ADD == PROJC || !defined(STRIP)
+
+void ep4_add_projc(ep4_t r, ep4_t p, ep4_t q) {
+ if (ep4_is_infty(p)) {
+ ep4_copy(r, q);
+ return;
+ }
+
+ if (ep4_is_infty(q)) {
+ ep4_copy(r, p);
+ return;
+ }
+
+ if (p == q) {
+ /* TODO: This is a quick hack. Should we fix this? */
+ ep4_dbl(r, p);
+ return;
+ }
+
+ ep4_add_projc_imp(r, p, q);
+}
+
+#endif
+
+void ep4_sub(ep4_t r, ep4_t p, ep4_t q) {
+ ep4_t t;
+
+ ep4_null(t);
+
+ if (p == q) {
+ ep4_set_infty(r);
+ return;
+ }
+
+ RLC_TRY {
+ ep4_new(t);
+
+ ep4_neg(t, q);
+ ep4_add(r, p, t);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ ep4_free(t);
+ }
+}
diff --git a/contrib/relic/src/epx/relic_ep4_cmp.c b/contrib/relic/src/epx/relic_ep4_cmp.c
new file mode 100644
index 000000000..3d12fc327
--- /dev/null
+++ b/contrib/relic/src/epx/relic_ep4_cmp.c
@@ -0,0 +1,82 @@
+/*
+ * RELIC is an Efficient LIbrary for Cryptography
+ * Copyright (c) 2021 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 ep4_cmp(ep4_t p, ep4_t q) {
+ ep4_t r, s;
+ int result = RLC_NE;
+
+ if (ep4_is_infty(p) && ep4_is_infty(q)) {
+ return RLC_EQ;
+ }
+
+ ep4_null(r);
+ ep4_null(s);
+
+ RLC_TRY {
+ ep4_new(r);
+ ep4_new(s);
+
+ if ((p->coord != BASIC) && (q->coord != BASIC)) {
+ /* If the two points are not normalized, it is faster to compare
+ * x1 * z2^2 == x2 * z1^2 and y1 * z2^3 == y2 * z1^3. */
+ fp4_sqr(r->z, p->z);
+ fp4_sqr(s->z, q->z);
+ fp4_mul(r->x, p->x, s->z);
+ fp4_mul(s->x, q->x, r->z);
+ fp4_mul(r->z, r->z, p->z);
+ fp4_mul(s->z, s->z, q->z);
+ fp4_mul(r->y, p->y, s->z);
+ fp4_mul(s->y, q->y, r->z);
+ } else {
+ ep4_norm(r, p);
+ ep4_norm(s, q);
+ }
+
+ if ((fp4_cmp(r->x, s->x) == RLC_EQ) &&
+ (fp4_cmp(r->y, s->y) == RLC_EQ)) {
+ result = RLC_EQ;
+ }
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ } RLC_FINALLY {
+ ep4_free(r);
+ ep4_free(s);
+ }
+
+ return result;
+}
diff --git a/contrib/relic/src/epx/relic_ep4_curve.c b/contrib/relic/src/epx/relic_ep4_curve.c
new file mode 100644
index 000000000..d70cc792a
--- /dev/null
+++ b/contrib/relic/src/epx/relic_ep4_curve.c
@@ -0,0 +1,377 @@
+/*
+ * RELIC is an Efficient LIbrary for Cryptography
+ * Copyright (c) 2021 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 quartic
+ * 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 == 509
+/** @{ */
+#define B24_P509_A0 "0"
+#define B24_P509_A1 "0"
+#define B24_P509_A2 "0"
+#define B24_P509_A3 "0"
+#define B24_P509_B0 "0"
+#define B24_P509_B1 "0"
+#define B24_P509_B2 "AAAAB7FFF9CE54DFE76F95A7CE0767B65C56424AE8C3F4619750081F008485DB13742DFBE0C507867E5AE3038DD69E97731DE83B746C980509E88C6DC5FE956"
+#define B24_P509_B3 "AAAAB7FFF9CE54DFE76F95A7CE0767B65C56424AE8C3F4619750081F008485DB13742DFBE0C507867E5AE3038DD69E97731DE83B746C980509E88C6DC5FE955"
+#define B24_P509_X0 "4D5AF70D2E605D1691DE7667FF1096AF4537749FD200277E1BC502847F63F4BC2F000FC81571F6E282FD46B96045CD611159ED554AFA95B2B1800A74F6A97C0"
+#define B24_P509_X1 "EA0D1E6A2105587ED20E9CA255A777AC78D0A24AEB118B1CE4D1F213BE42F7FFD3F3F5F60F06F902FEE405DF84143D533006D7383C25A7F7C26656440A80A0B"
+#define B24_P509_X2 "10E955FAFCA0C3C16D9DA9754859EAF918518C1A3FD0D14F427302CDE750224AD9E337CA12D3824B9E5E1668F94F56A4C2D935C6841C65FF4CA89E62C6A88D34"
+#define B24_P509_X3 "A9A981033A3844468D815A18B921C9F7C2B152372F240EAC4848A942FEAA4019B086104AE4F86C929F5B9064B4FE917A327279CEDCE02962FD3E971F9D00CCA"
+#define B24_P509_Y0 "C45C4179589584F8D1146550C117E3B452B7789170B7E7C0BEB1E417B5E32845CC1810760585AE0FE07762D94774A311932C100276C7A2EA4304EF7FBAA89F"
+#define B24_P509_Y1 "20315B1CE6AEE44F7ADCAE2F0B178DF7574F91380DB5E4A27281D02CC47A24618F995ACC29E611D7BBCE63E8A2CBD783256A1799FFA2A5D061D6872962CBAD"
+#define B24_P509_Y2 "20DEE7CA8DF5A616A014D78C0BCC69491116C715DDF5416C52B8A1833F8E4974255FBCCC5C6288DCA9B7CB2F4BB58525AB13D2225590A4A69955A859D36BF67"
+#define B24_P509_Y3 "5CD7D6B0C7890DC487A34BE4976767DE0C20BEB43A0EE741A5ED21021EBE5BDC42281008E19C44497E13A38165A36019235BDF7A48E76B6BA79D527024D227C"
+#define B24_P509_R "100000FFFF870FF91CE195DB5B6F3EBD1E08C94C9E193B724ED58B907FF7C311A80D7CABC647746AE3ECB627C943998457FE001"
+#define B24_P509_H "32916E9E0188E2252DA44F42F6DC0E90A66E8C7AFA49D50688A07F362BA18A01F6D9317009D55DAF8CFA9159E35E2736DA6417B31C8550DFC6CD766340D92AB85D629676E78E12D5E76AB9FAC536661EEA6615242264E5F6B46EBA0F95191CD226B0CB144CEC686A846DE323CBE0244A3B6E5FFE49BD01599F13AD869FF3DA2E5551FD9C2D885EF8FB95EB7FFD5460EC84FA36A569BCB5BBBC5A21B025CECEEAD08540C0ACCB87D9136ECB9C2CEDC2D465831D76AC3551EE87BCA06B751C18699A1424FF71E791EB953FA79"
+/** @} */
+#endif
+
+/**
+ * Assigns a set of ordinary elliptic curve parameters.
+ *
+ * @param[in] CURVE - the curve parameters to assign.
+ */
+#define ASSIGN(CURVE) \
+ RLC_GET(str, CURVE##_A0, sizeof(CURVE##_A0)); \
+ fp_read_str(a[0][0], str, strlen(str), 16); \
+ RLC_GET(str, CURVE##_A1, sizeof(CURVE##_A1)); \
+ fp_read_str(a[0][1], str, strlen(str), 16); \
+ RLC_GET(str, CURVE##_A2, sizeof(CURVE##_A2)); \
+ fp_read_str(a[1][0], str, strlen(str), 16); \
+ RLC_GET(str, CURVE##_A3, sizeof(CURVE##_A3)); \
+ fp_read_str(a[1][1], str, strlen(str), 16); \
+ RLC_GET(str, CURVE##_B0, sizeof(CURVE##_B0)); \
+ fp_read_str(b[0][0], str, strlen(str), 16); \
+ RLC_GET(str, CURVE##_B1, sizeof(CURVE##_B1)); \
+ fp_read_str(b[0][1], str, strlen(str), 16); \
+ RLC_GET(str, CURVE##_B2, sizeof(CURVE##_B2)); \
+ fp_read_str(b[1][0], str, strlen(str), 16); \
+ RLC_GET(str, CURVE##_B3, sizeof(CURVE##_B3)); \
+ fp_read_str(b[1][1], str, strlen(str), 16); \
+ RLC_GET(str, CURVE##_X0, sizeof(CURVE##_X0)); \
+ fp_read_str(g->x[0][0], str, strlen(str), 16); \
+ RLC_GET(str, CURVE##_X1, sizeof(CURVE##_X1)); \
+ fp_read_str(g->x[0][1], str, strlen(str), 16); \
+ RLC_GET(str, CURVE##_X2, sizeof(CURVE##_X2)); \
+ fp_read_str(g->x[1][0], str, strlen(str), 16); \
+ RLC_GET(str, CURVE##_X3, sizeof(CURVE##_X3)); \
+ fp_read_str(g->x[1][1], str, strlen(str), 16); \
+ RLC_GET(str, CURVE##_Y0, sizeof(CURVE##_Y0)); \
+ fp_read_str(g->y[0][0], str, strlen(str), 16); \
+ RLC_GET(str, CURVE##_Y1, sizeof(CURVE##_Y1)); \
+ fp_read_str(g->y[0][1], str, strlen(str), 16); \
+ RLC_GET(str, CURVE##_Y2, sizeof(CURVE##_Y2)); \
+ fp_read_str(g->y[1][0], str, strlen(str), 16); \
+ RLC_GET(str, CURVE##_Y3, sizeof(CURVE##_Y3)); \
+ fp_read_str(g->y[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, fp4_t a) {
+ fp4_t t;
+ fp4_null(t);
+
+ RLC_TRY {
+ fp4_new(t);
+ fp4_set_dig(t, 3);
+ fp4_neg(t, t);
+
+ if (fp4_cmp(a, t) == RLC_EQ) {
+ *opt = RLC_MIN3;
+ } else if (fp4_is_zero(a)) {
+ *opt = RLC_ZERO;
+ } else if (fp4_cmp_dig(a, 1) == RLC_EQ) {
+ *opt = RLC_ONE;
+ } else if (fp4_cmp_dig(a, 2) == RLC_EQ) {
+ *opt = RLC_TWO;
+ } else if ((fp_bits(a[0][0]) <= RLC_DIG) && fp_is_zero(a[0][1]) &&
+ fp2_is_zero(a[1])) {
+ *opt = RLC_TINY;
+ } else {
+ *opt = RLC_HUGE;
+ }
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ fp4_free(t);
+ }
+}
+
+/*============================================================================*/
+/* Public definitions */
+/*============================================================================*/
+
+void ep4_curve_init(void) {
+ ctx_t *ctx = core_get();
+
+#ifdef EP_PRECO
+ for (int i = 0; i < RLC_EP_TABLE; i++) {
+ ctx->ep4_ptr[i] = &(ctx->ep4_pre[i]);
+ }
+#endif
+
+#if ALLOC == DYNAMIC
+ ep4_new(ctx->ep4_g);
+ fp4_new(ctx->ep4_a);
+ fp4_new(ctx->ep4_b);
+#endif
+
+#ifdef EP_PRECO
+#if ALLOC == DYNAMIC
+ for (int i = 0; i < RLC_EP_TABLE; i++) {
+ fp4_new(ctx->ep4_pre[i].x);
+ fp4_new(ctx->ep4_pre[i].y);
+ fp4_new(ctx->ep4_pre[i].z);
+ }
+#endif
+#endif
+ ep4_set_infty(ctx->ep4_g);
+ bn_make(&(ctx->ep4_r), RLC_FP_DIGS);
+ bn_make(&(ctx->ep4_h), RLC_FP_DIGS);
+}
+
+void ep4_curve_clean(void) {
+ ctx_t *ctx = core_get();
+ if (ctx != NULL) {
+#ifdef EP_PRECO
+ for (int i = 0; i < RLC_EP_TABLE; i++) {
+ fp4_free(ctx->ep4_pre[i].x);
+ fp4_free(ctx->ep4_pre[i].y);
+ fp4_free(ctx->ep4_pre[i].z);
+ }
+#endif
+ bn_clean(&(ctx->ep4_r));
+ bn_clean(&(ctx->ep4_h));
+ ep4_free(ctx->ep4_g);
+ fp4_free(ctx->ep4_a);
+ fp4_free(ctx->ep4_b);
+ }
+}
+
+int ep4_curve_opt_a(void) {
+ return core_get()->ep4_opt_a;
+}
+
+int ep4_curve_opt_b(void) {
+ return core_get()->ep4_opt_b;
+}
+
+int ep4_curve_is_twist(void) {
+ return core_get()->ep4_is_twist;
+}
+
+void ep4_curve_get_gen(ep4_t g) {
+ ep4_copy(g, core_get()->ep4_g);
+}
+
+void ep4_curve_get_a(fp4_t a) {
+ fp4_copy(a, core_get()->ep4_a);
+}
+
+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) {
+ ep_curve_get_ord(n);
+ } else {
+ bn_copy(n, &(ctx->ep4_r));
+ }
+}
+
+void ep4_curve_get_cof(bn_t h) {
+ bn_copy(h, &(core_get()->ep4_h));
+}
+
+#if defined(EP_PRECO)
+
+ep4_t *ep4_curve_get_tab(void) {
+#if ALLOC == AUTO
+ return (ep4_t *)*(core_get()->ep4_ptr);
+#else
+ return core_get()->ep4_ptr;
+#endif
+}
+
+#endif
+
+void ep4_curve_set_twist(int type) {
+ char str[8 * RLC_FP_BYTES + 1];
+ ctx_t *ctx = core_get();
+ ep4_t g;
+ fp4_t a, b;
+ bn_t r, h;
+
+ ep4_null(g);
+ fp4_null(a);
+ fp4_null(b);
+ bn_null(r);
+ bn_null(h);
+
+ ctx->ep4_is_twist = 0;
+ if (type == RLC_EP_MTYPE || type == RLC_EP_DTYPE) {
+ ctx->ep4_is_twist = type;
+ } else {
+ return;
+ }
+
+ RLC_TRY {
+ ep4_new(g);
+ fp4_new(a);
+ fp4_new(b);
+ bn_new(r);
+ bn_new(h);
+
+ switch (ep_param_get()) {
+#if FP_PRIME == 509
+ case B24_P509:
+ ASSIGN(B24_P509);
+ break;
+#endif
+ default:
+ (void)str;
+ RLC_THROW(ERR_NO_VALID);
+ break;
+ }
+
+ fp4_zero(g->z);
+ fp4_set_dig(g->z, 1);
+ g->coord = BASIC;
+
+ ep4_copy(ctx->ep4_g, g);
+ fp4_copy(ctx->ep4_a, a);
+ fp4_copy(ctx->ep4_b, b);
+
+ detect_opt(&(ctx->ep4_opt_a), ctx->ep4_a);
+ detect_opt(&(ctx->ep4_opt_b), ctx->ep4_b);
+
+ bn_copy(&(ctx->ep4_r), r);
+ bn_copy(&(ctx->ep4_h), h);
+
+#if defined(WITH_PC)
+ /* Compute pairing generator. */
+ pc_core_calc();
+#endif
+
+#if defined(EP_PRECO)
+ ep4_mul_pre((ep4_t *)ep4_curve_get_tab(), ctx->ep4_g);
+#endif
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ ep4_free(g);
+ fp4_free(a);
+ fp4_free(b);
+ bn_free(r);
+ bn_free(h);
+ }
+}
+
+void ep4_curve_set(fp4_t a, fp4_t b, ep4_t g, bn_t r, bn_t h) {
+ ctx_t *ctx = core_get();
+ ctx->ep4_is_twist = 0;
+
+ fp4_copy(ctx->ep4_a, a);
+ fp4_copy(ctx->ep4_b, b);
+
+ ep4_norm(ctx->ep4_g, g);
+ bn_copy(&(ctx->ep4_r), r);
+ bn_copy(&(ctx->ep4_h), h);
+
+#if defined(EP_PRECO)
+ ep4_mul_pre((ep4_t *)ep4_curve_get_tab(), ctx->ep4_g);
+#endif
+}
diff --git a/contrib/relic/src/epx/relic_ep4_dbl.c b/contrib/relic/src/epx/relic_ep4_dbl.c
new file mode 100644
index 000000000..11d0bb047
--- /dev/null
+++ b/contrib/relic/src/epx/relic_ep4_dbl.c
@@ -0,0 +1,276 @@
+/*
+ * RELIC is an Efficient LIbrary for Cryptography
+ * Copyright (c) 2021 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 ep4_dbl_basic_imp(ep4_t r, fp4_t s, ep4_t p) {
+ fp4_t t0, t1, t2;
+
+ fp4_null(t0);
+ fp4_null(t1);
+ fp4_null(t2);
+
+ RLC_TRY {
+ fp4_new(t0);
+ fp4_new(t1);
+ fp4_new(t2);
+
+ /* t0 = 1/(2 * y1). */
+ fp4_dbl(t0, p->y);
+ fp4_inv(t0, t0);
+
+ /* t1 = 3 * x1^2 + a. */
+ fp4_sqr(t1, p->x);
+ fp4_copy(t2, t1);
+ fp4_dbl(t1, t1);
+ fp4_add(t1, t1, t2);
+
+ ep4_curve_get_a(t2);
+ fp4_add(t1, t1, t2);
+
+ /* t1 = (3 * x1^2 + a)/(2 * y1). */
+ fp4_mul(t1, t1, t0);
+
+ if (s != NULL) {
+ fp4_copy(s, t1);
+ }
+
+ /* t2 = t1^2. */
+ fp4_sqr(t2, t1);
+
+ /* x3 = t1^2 - 2 * x1. */
+ fp4_dbl(t0, p->x);
+ fp4_sub(t0, t2, t0);
+
+ /* y3 = t1 * (x1 - x3) - y1. */
+ fp4_sub(t2, p->x, t0);
+ fp4_mul(t1, t1, t2);
+
+ fp4_sub(r->y, t1, p->y);
+
+ fp4_copy(r->x, t0);
+ fp4_copy(r->z, p->z);
+
+ r->coord = BASIC;
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ fp4_free(t0);
+ fp4_free(t1);
+ fp4_free(t2);
+ }
+}
+
+#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 ep4_dbl_projc_imp(ep4_t r, ep4_t p) {
+ fp4_t t0, t1, t2, t3, t4, t5;
+
+ fp4_null(t0);
+ fp4_null(t1);
+ fp4_null(t2);
+ fp4_null(t3);
+ fp4_null(t4);
+ fp4_null(t5);
+
+ RLC_TRY {
+ if (ep_curve_opt_a() == RLC_ZERO) {
+ fp4_new(t0);
+ fp4_new(t1);
+ fp4_new(t2);
+ fp4_new(t3);
+ fp4_new(t4);
+ fp4_new(t5);
+
+ fp4_sqr(t0, p->x);
+ fp4_add(t2, t0, t0);
+ fp4_add(t0, t2, t0);
+
+ fp4_sqr(t3, p->y);
+ fp4_mul(t1, t3, p->x);
+ fp4_add(t1, t1, t1);
+ fp4_add(t1, t1, t1);
+ fp4_sqr(r->x, t0);
+ fp4_add(t2, t1, t1);
+ fp4_sub(r->x, r->x, t2);
+ fp4_mul(r->z, p->z, p->y);
+ fp4_add(r->z, r->z, r->z);
+ fp4_add(t3, t3, t3);
+
+ fp4_sqr(t3, t3);
+ fp4_add(t3, t3, t3);
+ fp4_sub(t1, t1, r->x);
+ fp4_mul(r->y, t0, t1);
+ fp4_sub(r->y, r->y, t3);
+ } else {
+ /* dbl-2007-bl formulas: 1M + 8S + 1*a + 10add + 1*8 + 2*2 + 1*3 */
+ /* http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-2007-bl */
+
+ /* t0 = x1^2, t1 = y1^2, t2 = y1^4. */
+ fp4_sqr(t0, p->x);
+ fp4_sqr(t1, p->y);
+ fp4_sqr(t2, t1);
+
+ if (p->coord != BASIC) {
+ /* t3 = z1^2. */
+ fp4_sqr(t3, p->z);
+
+ if (ep_curve_get_a() == RLC_ZERO) {
+ /* z3 = 2 * y1 * z1. */
+ fp4_mul(r->z, p->y, p->z);
+ fp4_dbl(r->z, r->z);
+ } else {
+ /* z3 = (y1 + z1)^2 - y1^2 - z1^2. */
+ fp4_add(r->z, p->y, p->z);
+ fp4_sqr(r->z, r->z);
+ fp4_sub(r->z, r->z, t1);
+ fp4_sub(r->z, r->z, t3);
+ }
+ } else {
+ /* z3 = 2 * y1. */
+ fp4_dbl(r->z, p->y);
+ }
+
+ /* t4 = S = 2*((x1 + y1^2)^2 - x1^2 - y1^4). */
+ fp4_add(t4, p->x, t1);
+ fp4_sqr(t4, t4);
+ fp4_sub(t4, t4, t0);
+ fp4_sub(t4, t4, t2);
+ fp4_dbl(t4, t4);
+
+ /* t5 = M = 3 * x1^2 + a * z1^4. */
+ fp4_dbl(t5, t0);
+ fp4_add(t5, t5, t0);
+ if (p->coord != BASIC) {
+ fp4_sqr(t3, t3);
+ ep4_curve_get_a(t1);
+ fp4_mul(t1, t3, t1);
+ fp4_add(t5, t5, t1);
+ } else {
+ ep4_curve_get_a(t1);
+ fp4_add(t5, t5, t1);
+ }
+
+ /* x3 = T = M^2 - 2 * S. */
+ fp4_sqr(r->x, t5);
+ fp4_dbl(t1, t4);
+ fp4_sub(r->x, r->x, t1);
+
+ /* y3 = M * (S - T) - 8 * y1^4. */
+ fp4_dbl(t2, t2);
+ fp4_dbl(t2, t2);
+ fp4_dbl(t2, t2);
+ fp4_sub(t4, t4, r->x);
+ fp4_mul(t5, t5, t4);
+ fp4_sub(r->y, t5, t2);
+ }
+
+ 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 /* EP_ADD == PROJC */
+
+/*============================================================================*/
+ /* Public definitions */
+/*============================================================================*/
+
+#if EP_ADD == BASIC || !defined(STRIP)
+
+void ep4_dbl_basic(ep4_t r, ep4_t p) {
+ if (ep4_is_infty(p)) {
+ ep4_set_infty(r);
+ return;
+ }
+
+ ep4_dbl_basic_imp(r, NULL, p);
+}
+
+void ep4_dbl_slp_basic(ep4_t r, fp4_t s, ep4_t p) {
+ if (ep4_is_infty(p)) {
+ ep4_set_infty(r);
+ return;
+ }
+
+ ep4_dbl_basic_imp(r, s, p);
+}
+
+#endif
+
+#if EP_ADD == PROJC || !defined(STRIP)
+
+void ep4_dbl_projc(ep4_t r, ep4_t p) {
+ if (ep4_is_infty(p)) {
+ ep4_set_infty(r);
+ return;
+ }
+
+ ep4_dbl_projc_imp(r, p);
+}
+
+#endif
diff --git a/contrib/relic/src/epx/relic_ep4_frb.c b/contrib/relic/src/epx/relic_ep4_frb.c
new file mode 100644
index 000000000..fa216d53e
--- /dev/null
+++ b/contrib/relic/src/epx/relic_ep4_frb.c
@@ -0,0 +1,48 @@
+/*
+ * RELIC is an Efficient LIbrary for Cryptography
+ * Copyright (c) 2021 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 ep4_frb(ep4_t r, ep4_t p, int i) {
+ ep4_copy(r, p);
+ for (; i > 0; i--) {
+ fp4_frb(r->x, r->x, 1);
+ fp4_frb(r->y, r->y, 1);
+ fp4_frb(r->z, r->z, 1);
+ fp4_mul_frb(r->x, r->x, 1, 2);
+ fp4_mul_frb(r->y, r->y, 1, 3);
+ }
+}
diff --git a/contrib/relic/src/epx/relic_ep4_map.c b/contrib/relic/src/epx/relic_ep4_map.c
new file mode 100644
index 000000000..be73b8d1e
--- /dev/null
+++ b/contrib/relic/src/epx/relic_ep4_map.c
@@ -0,0 +1,79 @@
+/*
+ * RELIC is an Efficient LIbrary for Cryptography
+ * Copyright (c) 2012 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 ep4_map(ep4_t p, const uint8_t *msg, int len) {
+ bn_t x;
+ fp4_t t0;
+ uint8_t digest[RLC_MD_LEN];
+
+ bn_null(x);
+ fp4_null(t0);
+
+ RLC_TRY {
+ bn_new(x);
+ fp4_new(t0);
+
+ md_map(digest, msg, len);
+ bn_read_bin(x, digest, RLC_MIN(RLC_FP_BYTES, RLC_MD_LEN));
+
+ fp4_zero(p->x);
+ fp_prime_conv(p->x[0][0], x);
+ fp4_set_dig(p->z, 1);
+
+ while (1) {
+ ep4_rhs(t0, p);
+
+ if (fp4_srt(p->y, t0)) {
+ p->coord = BASIC;
+ break;
+ }
+
+ fp_add_dig(p->x[0][0], p->x[0][0], 1);
+ }
+
+ ep4_mul_cof(p, p);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ bn_free(x);
+ fp4_free(t0);
+ }
+}
diff --git a/contrib/relic/src/epx/relic_ep4_mul.c b/contrib/relic/src/epx/relic_ep4_mul.c
new file mode 100644
index 000000000..c02f41b90
--- /dev/null
+++ b/contrib/relic/src/epx/relic_ep4_mul.c
@@ -0,0 +1,449 @@
+/*
+ * RELIC is an Efficient LIbrary for Cryptography
+ * Copyright (c) 2012 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 ep4_mul_glv_imp(ep4_t r, ep4_t p, const bn_t k) {
+ int sign, i, j, l, _l[8];
+ bn_t n, _k[8], u, v;
+ int8_t naf[8][RLC_FP_BITS + 1];
+ ep4_t q[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++) {
+ 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);
+
+ 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);
+ }
+ }
+
+ l = 0;
+ for (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]);
+ }
+
+ ep4_set_infty(r);
+ for (j = l - 1; j >= 0; j--) {
+ ep4_dbl(r, r);
+
+ for (i = 0; i < 8; i++) {
+ if (naf[i][j] > 0) {
+ ep4_add(r, r, q[i]);
+ }
+ if (naf[i][j] < 0) {
+ ep4_sub(r, r, q[i]);
+ }
+ }
+ }
+
+ /* Convert r to affine coordinates. */
+ ep4_norm(r, r);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ bn_free(u);
+ bn_free(v);
+ for (i = 0; i < 8; i++) {
+ bn_free(_k[i]);
+ ep4_free(q[i]);
+ }
+
+ }
+}
+
+#endif /* EP_ENDOM */
+
+static void ep4_mul_naf_imp(ep4_t r, ep4_t p, const bn_t k) {
+ int l, i, n;
+ int8_t naf[RLC_FP_BITS + 1];
+ ep4_t t[1 << (EP_WIDTH - 2)];
+
+ RLC_TRY {
+ /* Prepare the precomputation table. */
+ for (i = 0; i < (1 << (EP_WIDTH - 2)); i++) {
+ ep4_null(t[i]);
+ ep4_new(t[i]);
+ }
+ /* Compute the precomputation table. */
+ ep4_tab(t, p, EP_WIDTH);
+
+ /* Compute the w-NAF representation of k. */
+ l = sizeof(naf);
+ bn_rec_naf(naf, &l, k, EP_WIDTH);
+
+ ep4_set_infty(r);
+ for (i = l - 1; i >= 0; i--) {
+ ep4_dbl(r, r);
+
+ n = naf[i];
+ if (n > 0) {
+ ep4_add(r, r, t[n / 2]);
+ }
+ if (n < 0) {
+ ep4_sub(r, r, t[-n / 2]);
+ }
+ }
+ /* Convert r to affine coordinates. */
+ ep4_norm(r, r);
+ if (bn_sign(k) == RLC_NEG) {
+ ep4_neg(r, r);
+ }
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ /* Free the precomputation table. */
+ for (i = 0; i < (1 << (EP_WIDTH - 2)); i++) {
+ ep4_free(t[i]);
+ }
+ }
+}
+
+#endif /* EP_MUL == LWNAF */
+
+/*============================================================================*/
+/* Public definitions */
+/*============================================================================*/
+
+void ep4_mul_basic(ep4_t r, ep4_t p, const bn_t k) {
+ int i, l;
+ ep4_t t;
+
+ ep4_null(t);
+
+ if (bn_is_zero(k) || ep4_is_infty(p)) {
+ 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);
+ }
+
+ for (i = l - 2; i >= 0; i--) {
+ ep4_dbl(t, t);
+ if (bn_get_bit(k, i)) {
+ ep4_add(t, t, p);
+ }
+ }
+
+ ep4_copy(r, t);
+ ep4_norm(r, r);
+ if (bn_sign(k) == RLC_NEG) {
+ ep4_neg(r, r);
+ }
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ ep4_free(t);
+ }
+}
+
+#if EP_MUL == SLIDE || !defined(STRIP)
+
+void ep4_mul_slide(ep4_t r, ep4_t p, const bn_t k) {
+ ep4_t t[1 << (EP_WIDTH - 1)], q;
+ int i, j, l;
+ uint8_t win[RLC_FP_BITS + 1];
+
+ ep4_null(q);
+
+ if (bn_is_zero(k) || ep4_is_infty(p)) {
+ ep4_set_infty(r);
+ return;
+ }
+
+ RLC_TRY {
+ for (i = 0; i < (1 << (EP_WIDTH - 1)); i ++) {
+ ep4_null(t[i]);
+ ep4_new(t[i]);
+ }
+
+ ep4_new(q);
+
+ ep4_copy(t[0], p);
+ ep4_dbl(q, p);
+
+#if defined(EP_MIXED)
+ ep4_norm(q, q);
+#endif
+
+ /* Create table. */
+ for (i = 1; i < (1 << (EP_WIDTH - 1)); i++) {
+ ep4_add(t[i], t[i - 1], q);
+ }
+
+#if defined(EP_MIXED)
+ ep4_norm_sim(t + 1, t + 1, (1 << (EP_WIDTH - 1)) - 1);
+#endif
+
+ ep4_set_infty(q);
+ l = RLC_FP_BITS + 1;
+ bn_rec_slw(win, &l, k, EP_WIDTH);
+ for (i = 0; i < l; i++) {
+ if (win[i] == 0) {
+ ep4_dbl(q, q);
+ } else {
+ for (j = 0; j < util_bits_dig(win[i]); j++) {
+ ep4_dbl(q, q);
+ }
+ ep4_add(q, q, t[win[i] >> 1]);
+ }
+ }
+
+ ep4_norm(r, q);
+ if (bn_sign(k) == RLC_NEG) {
+ ep4_neg(r, r);
+ }
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ for (i = 0; i < (1 << (EP_WIDTH - 1)); i++) {
+ ep4_free(t[i]);
+ }
+ ep4_free(q);
+ }
+}
+
+#endif
+
+#if EP_MUL == MONTY || !defined(STRIP)
+
+void ep4_mul_monty(ep4_t r, ep4_t p, const bn_t k) {
+ ep4_t t[2];
+
+ ep4_null(t[0]);
+ ep4_null(t[1]);
+
+ if (bn_is_zero(k) || ep4_is_infty(p)) {
+ ep4_set_infty(r);
+ return;
+ }
+
+ RLC_TRY {
+ ep4_new(t[0]);
+ ep4_new(t[1]);
+
+ ep4_set_infty(t[0]);
+ ep4_copy(t[1], p);
+
+ for (int i = bn_bits(k) - 1; i >= 0; i--) {
+ int j = bn_get_bit(k, i);
+ dv_swap_cond(t[0]->x[0][0], t[1]->x[0][0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_cond(t[0]->x[0][1], t[1]->x[0][1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_cond(t[0]->x[1][0], t[1]->x[1][0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_cond(t[0]->x[1][1], t[1]->x[1][1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_cond(t[0]->y[0][0], t[1]->y[0][0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_cond(t[0]->y[0][1], t[1]->y[0][1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_cond(t[0]->y[1][0], t[1]->y[1][0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_cond(t[0]->y[1][1], t[1]->y[1][1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_cond(t[0]->z[0][0], t[1]->z[0][0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_cond(t[0]->z[0][1], t[1]->z[0][1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_cond(t[0]->z[1][0], t[1]->z[1][0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_cond(t[0]->z[1][1], t[1]->z[1][1], RLC_FP_DIGS, j ^ 1);
+ ep4_add(t[0], t[0], t[1]);
+ ep4_dbl(t[1], t[1]);
+ dv_swap_cond(t[0]->x[0][0], t[1]->x[0][0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_cond(t[0]->x[0][1], t[1]->x[0][1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_cond(t[0]->x[1][0], t[1]->x[1][0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_cond(t[0]->x[1][1], t[1]->x[1][1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_cond(t[0]->y[0][0], t[1]->y[0][0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_cond(t[0]->y[0][1], t[1]->y[0][1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_cond(t[0]->y[1][0], t[1]->y[1][0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_cond(t[0]->y[1][1], t[1]->y[1][1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_cond(t[0]->z[0][0], t[1]->z[0][0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_cond(t[0]->z[0][1], t[1]->z[0][1], RLC_FP_DIGS, j ^ 1);
+ dv_swap_cond(t[0]->z[1][0], t[1]->z[1][0], RLC_FP_DIGS, j ^ 1);
+ dv_swap_cond(t[0]->z[1][1], t[1]->z[1][1], RLC_FP_DIGS, j ^ 1);
+ }
+
+ ep4_norm(r, t[0]);
+ if (bn_sign(k) == RLC_NEG) {
+ ep4_neg(r, r);
+ }
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ ep4_free(t[1]);
+ ep4_free(t[0]);
+ }
+}
+
+#endif
+
+#if EP_MUL == LWNAF || !defined(STRIP)
+
+void ep4_mul_lwnaf(ep4_t r, ep4_t p, const bn_t k) {
+ if (bn_is_zero(k) || ep4_is_infty(p)) {
+ ep4_set_infty(r);
+ return;
+ }
+
+#if defined(EP_ENDOM)
+ if (ep_curve_is_endom()) {
+ if (ep_curve_opt_a() == RLC_ZERO) {
+ ep4_mul_glv_imp(r, p, k);
+ } else {
+ ep4_mul_naf_imp(r, p, k);
+ }
+ return;
+ }
+#endif
+
+#if defined(EP_PLAIN) || defined(EP_SUPER)
+ ep4_mul_naf_imp(r, p, k);
+#endif
+}
+
+#endif
+
+void ep4_mul_gen(ep4_t r, bn_t k) {
+ if (bn_is_zero(k)) {
+ ep4_set_infty(r);
+ return;
+ }
+
+#ifdef EP_PRECO
+ ep4_mul_fix(r, ep4_curve_get_tab(), k);
+#else
+ ep4_t g;
+
+ ep4_null(g);
+
+ RLC_TRY {
+ ep4_new(g);
+ ep4_curve_get_gen(g);
+ ep4_mul(r, g, k);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ ep4_free(g);
+ }
+#endif
+}
+
+void ep4_mul_dig(ep4_t r, ep4_t p, dig_t k) {
+ int i, l;
+ ep4_t t;
+
+ ep4_null(t);
+
+ if (k == 0 || ep4_is_infty(p)) {
+ ep4_set_infty(r);
+ return;
+ }
+
+ RLC_TRY {
+ ep4_new(t);
+
+ l = util_bits_dig(k);
+
+ ep4_copy(t, p);
+
+ for (i = l - 2; i >= 0; i--) {
+ ep4_dbl(t, t);
+ if (k & ((dig_t)1 << i)) {
+ ep4_add(t, t, p);
+ }
+ }
+
+ ep4_norm(r, t);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ ep4_free(t);
+ }
+}
diff --git a/contrib/relic/src/epx/relic_ep4_mul_cof.c b/contrib/relic/src/epx/relic_ep4_mul_cof.c
new file mode 100644
index 000000000..14f9973f2
--- /dev/null
+++ b/contrib/relic/src/epx/relic_ep4_mul_cof.c
@@ -0,0 +1,93 @@
+/*
+ * RELIC is an Efficient LIbrary for Cryptography
+ * Copyright (c) 2021 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 a
+ * quadratic extension by the curve cofactor.
+ *
+ * @ingroup epx
+ */
+
+#include "relic_core.h"
+#include "relic_md.h"
+#include "relic_tmpl_map.h"
+
+/*============================================================================*/
+/* Public definitions */
+/*============================================================================*/
+
+void ep4_mul_cof(ep4_t r, ep4_t p) {
+ bn_t z;
+ ep4_t t0, t1, t2, t3;
+
+ ep4_null(t0);
+ ep4_null(t1);
+ ep4_null(t2);
+ ep4_null(t3);
+ bn_null(z);
+
+ RLC_TRY {
+ ep4_new(t0);
+ ep4_new(t1);
+ ep4_new(t2);
+ ep4_new(t3);
+
+ fp_prime_get_par(z);
+
+ ep4_mul_basic(t0, p, z);
+ 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);
+ ep4_frb(t2, t2, 1);
+
+ ep4_sub(t1, t1, t0);
+ ep4_frb(t1, t1, 2);
+
+ ep4_sub(t0, t0, p);
+ ep4_frb(t0, t0, 3);
+
+ ep4_dbl(r, p);
+ ep4_frb(r, r, 4);
+ ep4_add(r, r, t0);
+ ep4_add(r, r, t1);
+ ep4_add(r, r, t2);
+ ep4_add(r, r, t3);
+
+ ep4_norm(r, r);
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ } RLC_FINALLY {
+ ep4_free(t0);
+ ep4_free(t1);
+ ep4_free(t2);
+ ep4_free(t3);
+ bn_free(z);
+
+ }
+}
diff --git a/contrib/relic/src/epx/relic_ep4_mul_fix.c b/contrib/relic/src/epx/relic_ep4_mul_fix.c
new file mode 100644
index 000000000..8709e702b
--- /dev/null
+++ b/contrib/relic/src/epx/relic_ep4_mul_fix.c
@@ -0,0 +1,393 @@
+/*
+ * RELIC is an Efficient LIbrary for Cryptography
+ * Copyright (c) 2012 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 ep4_mul_pre_ordin(ep4_t *t, ep4_t p) {
+ int i;
+
+ ep4_dbl(t[0], p);
+#if defined(EP_MIXED)
+ ep4_norm(t[0], t[0]);
+#endif
+
+#if EP_DEPTH > 2
+ ep4_add(t[1], t[0], p);
+ for (i = 2; i < (1 << (EP_DEPTH - 2)); i++) {
+ ep4_add(t[i], t[i - 1], t[0]);
+ }
+
+#if defined(EP_MIXED)
+ for (i = 1; i < (1 << (EP_DEPTH - 2)); i++) {
+ ep4_norm(t[i], t[i]);
+ }
+#endif
+
+#endif
+ ep4_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 ep4_mul_fix_ordin(ep4_t r, ep4_t *table, bn_t k) {
+ int len, i, n;
+ int8_t naf[2 * RLC_FP_BITS + 1], *t;
+
+ if (bn_is_zero(k)) {
+ ep4_set_infty(r);
+ return;
+ }
+
+ /* Compute the w-TNAF representation of k. */
+ len = 2 * RLC_FP_BITS + 1;
+ bn_rec_naf(naf, &len, k, EP_DEPTH);
+
+ t = naf + len - 1;
+ ep4_set_infty(r);
+ for (i = len - 1; i >= 0; i--, t--) {
+ ep4_dbl(r, r);
+
+ n = *t;
+ if (n > 0) {
+ ep4_add(r, r, table[n / 2]);
+ }
+ if (n < 0) {
+ ep4_sub(r, r, table[-n / 2]);
+ }
+ }
+ /* Convert r to affine coordinates. */
+ ep4_norm(r, r);
+ if (bn_sign(k) == RLC_NEG) {
+ ep4_neg(r, r);
+ }
+}
+
+#endif /* EP_FIX == LWNAF */
+
+/*============================================================================*/
+/* Public definitions */
+/*============================================================================*/
+
+#if EP_FIX == BASIC || !defined(STRIP)
+
+void ep4_mul_pre_basic(ep4_t *t, ep4_t p) {
+ bn_t n;
+
+ bn_null(n);
+
+ RLC_TRY {
+ bn_new(n);
+
+ ep4_curve_get_ord(n);
+
+ ep4_copy(t[0], p);
+ for (int i = 1; i < bn_bits(n); i++) {
+ ep4_dbl(t[i], t[i - 1]);
+ }
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ }
+}
+
+void ep4_mul_fix_basic(ep4_t r, ep4_t *t, bn_t k) {
+ if (bn_is_zero(k)) {
+ ep4_set_infty(r);
+ return;
+ }
+
+ 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);
+ }
+}
+
+#endif
+
+#if EP_FIX == COMBS || !defined(STRIP)
+
+void ep4_mul_pre_combs(ep4_t *t, ep4_t p) {
+ int i, j, l;
+ bn_t n;
+
+ bn_null(n);
+
+ RLC_TRY {
+ bn_new(n);
+
+ ep4_curve_get_ord(n);
+ l = bn_bits(n);
+ l = ((l % EP_DEPTH) == 0 ? (l / EP_DEPTH) : (l / EP_DEPTH) + 1);
+
+ ep4_set_infty(t[0]);
+
+ ep4_copy(t[1], p);
+ for (j = 1; j < EP_DEPTH; j++) {
+ ep4_dbl(t[1 << j], t[1 << (j - 1)]);
+ for (i = 1; i < l; i++) {
+ ep4_dbl(t[1 << j], t[1 << j]);
+ }
+#if defined(EP_MIXED)
+ ep4_norm(t[1 << j], t[1 << j]);
+#endif
+ for (i = 1; i < (1 << j); i++) {
+ ep4_add(t[(1 << j) + i], t[i], t[1 << j]);
+ }
+ }
+#if defined(EP_MIXED)
+ for (i = 1; i < RLC_EP_TABLE_COMBS; i++) {
+ ep4_norm(t[i], t[i]);
+ }
+#endif
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ }
+}
+
+void ep4_mul_fix_combs(ep4_t r, ep4_t *t, bn_t k) {
+ int i, j, l, w, n0, p0, p1;
+ bn_t n;
+
+ if (bn_is_zero(k)) {
+ ep4_set_infty(r);
+ return;
+ }
+
+ bn_null(n);
+
+ RLC_TRY {
+ bn_new(n);
+
+ ep4_curve_get_ord(n);
+ l = bn_bits(n);
+ l = ((l % EP_DEPTH) == 0 ? (l / EP_DEPTH) : (l / EP_DEPTH) + 1);
+
+ n0 = bn_bits(k);
+
+ p0 = (EP_DEPTH) * l - 1;
+
+ w = 0;
+ p1 = p0--;
+ for (j = EP_DEPTH - 1; j >= 0; j--, p1 -= l) {
+ w = w << 1;
+ if (p1 < n0 && bn_get_bit(k, p1)) {
+ w = w | 1;
+ }
+ }
+ ep4_copy(r, t[w]);
+
+ for (i = l - 2; i >= 0; i--) {
+ ep4_dbl(r, r);
+
+ w = 0;
+ p1 = p0--;
+ for (j = EP_DEPTH - 1; j >= 0; j--, p1 -= l) {
+ w = w << 1;
+ if (p1 < n0 && bn_get_bit(k, p1)) {
+ w = w | 1;
+ }
+ }
+ if (w > 0) {
+ ep4_add(r, r, t[w]);
+ }
+ }
+ 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);
+ }
+}
+
+#endif
+
+#if EP_FIX == COMBD || !defined(STRIP)
+
+void ep4_mul_pre_combd(ep4_t *t, ep4_t p) {
+ int i, j, d, e;
+ bn_t n;
+
+ bn_null(n);
+
+ RLC_TRY {
+ bn_new(n);
+
+ ep4_curve_get_ord(n);
+ d = bn_bits(n);
+ d = ((d % EP_DEPTH) == 0 ? (d / EP_DEPTH) : (d / EP_DEPTH) + 1);
+ e = (d % 2 == 0 ? (d / 2) : (d / 2) + 1);
+
+ ep4_set_infty(t[0]);
+ ep4_copy(t[1], p);
+ for (j = 1; j < EP_DEPTH; j++) {
+ ep4_dbl(t[1 << j], t[1 << (j - 1)]);
+ for (i = 1; i < d; i++) {
+ ep4_dbl(t[1 << j], t[1 << j]);
+ }
+#if defined(EP_MIXED)
+ ep4_norm(t[1 << j], t[1 << j]);
+#endif
+ for (i = 1; i < (1 << j); i++) {
+ ep4_add(t[(1 << j) + i], t[i], t[1 << j]);
+ }
+ }
+ ep4_set_infty(t[1 << EP_DEPTH]);
+ for (j = 1; j < (1 << EP_DEPTH); j++) {
+ ep4_dbl(t[(1 << EP_DEPTH) + j], t[j]);
+ for (i = 1; i < e; i++) {
+ ep4_dbl(t[(1 << EP_DEPTH) + j], t[(1 << EP_DEPTH) + j]);
+ }
+ }
+#if defined(EP_MIXED)
+ for (i = 1; i < RLC_EP_TABLE_COMBD; i++) {
+ ep4_norm(t[i], t[i]);
+ }
+#endif
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ }
+}
+
+void ep4_mul_fix_combd(ep4_t r, ep4_t *t, bn_t k) {
+ int i, j, d, e, w0, w1, n0, p0, p1;
+ bn_t n;
+
+ if (bn_is_zero(k)) {
+ ep4_set_infty(r);
+ return;
+ }
+
+ bn_null(n);
+
+ RLC_TRY {
+ bn_new(n);
+
+ ep4_curve_get_ord(n);
+ d = bn_bits(n);
+ d = ((d % EP_DEPTH) == 0 ? (d / EP_DEPTH) : (d / EP_DEPTH) + 1);
+ e = (d % 2 == 0 ? (d / 2) : (d / 2) + 1);
+
+ ep4_set_infty(r);
+ n0 = bn_bits(k);
+
+ p1 = (e - 1) + (EP_DEPTH - 1) * d;
+ for (i = e - 1; i >= 0; i--) {
+ ep4_dbl(r, r);
+
+ w0 = 0;
+ p0 = p1;
+ for (j = EP_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 = EP_DEPTH - 1; j >= 0; j--, p0 -= d) {
+ w1 = w1 << 1;
+ if (i + e < d && p0 < n0 && bn_get_bit(k, p0)) {
+ w1 = w1 | 1;
+ }
+ }
+
+ ep4_add(r, r, t[w0]);
+ ep4_add(r, r, t[(1 << EP_DEPTH) + w1]);
+ }
+ 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);
+ }
+}
+
+#endif
+
+#if EP_FIX == LWNAF || !defined(STRIP)
+
+void ep4_mul_pre_lwnaf(ep4_t *t, ep4_t p) {
+ ep4_mul_pre_ordin(t, p);
+}
+
+void ep4_mul_fix_lwnaf(ep4_t r, ep4_t *t, bn_t k) {
+ ep4_mul_fix_ordin(r, t, k);
+}
+
+#endif
diff --git a/contrib/relic/src/epx/relic_ep4_mul_sim.c b/contrib/relic/src/epx/relic_ep4_mul_sim.c
new file mode 100644
index 000000000..faff8f0c3
--- /dev/null
+++ b/contrib/relic/src/epx/relic_ep4_mul_sim.c
@@ -0,0 +1,628 @@
+/*
+ * RELIC is an Efficient LIbrary for Cryptography
+ * Copyright (c) 2012 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 ep4_mul_sim_plain(ep4_t r, ep4_t p, bn_t k, ep4_t q, bn_t m,
+ ep4_t *t) {
+ int i, l, l0, l1, n0, n1, w, gen;
+ int8_t naf0[2 * RLC_FP_BITS + 1], naf1[2 * RLC_FP_BITS + 1], *_k, *_m;
+ ep4_t t0[1 << (EP_WIDTH - 2)];
+ ep4_t t1[1 << (EP_WIDTH - 2)];
+
+ RLC_TRY {
+ gen = (t == NULL ? 0 : 1);
+ if (!gen) {
+ for (i = 0; i < (1 << (EP_WIDTH - 2)); i++) {
+ ep4_null(t0[i]);
+ ep4_new(t0[i]);
+ }
+ ep4_tab(t0, p, EP_WIDTH);
+ t = (ep4_t *)t0;
+ }
+
+ /* Prepare the precomputation table. */
+ for (i = 0; i < (1 << (EP_WIDTH - 2)); i++) {
+ ep4_null(t1[i]);
+ ep4_new(t1[i]);
+ }
+ /* Compute the precomputation table. */
+ ep4_tab(t1, q, EP_WIDTH);
+
+ /* Compute the w-TNAF representation of k. */
+ if (gen) {
+ w = EP_DEPTH;
+ } else {
+ w = EP_WIDTH;
+ }
+ l0 = l1 = 2 * RLC_FP_BITS + 1;
+ bn_rec_naf(naf0, &l0, k, w);
+ bn_rec_naf(naf1, &l1, m, EP_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];
+ }
+ }
+
+ ep4_set_infty(r);
+ for (i = l - 1; i >= 0; i--, _k--, _m--) {
+ ep4_dbl(r, r);
+
+ n0 = *_k;
+ n1 = *_m;
+ if (n0 > 0) {
+ ep4_add(r, r, t[n0 / 2]);
+ }
+ if (n0 < 0) {
+ ep4_sub(r, r, t[-n0 / 2]);
+ }
+ if (n1 > 0) {
+ ep4_add(r, r, t1[n1 / 2]);
+ }
+ if (n1 < 0) {
+ ep4_sub(r, r, t1[-n1 / 2]);
+ }
+ }
+ /* Convert r to affine coordinates. */
+ ep4_norm(r, r);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ /* Free the precomputation tables. */
+ if (!gen) {
+ for (i = 0; i < (1 << (EP_WIDTH - 2)); i++) {
+ ep4_free(t0[i]);
+ }
+ }
+ for (i = 0; i < (1 << (EP_WIDTH - 2)); i++) {
+ ep4_free(t1[i]);
+ }
+ }
+}
+
+#endif /* EP_SIM == INTER */
+
+/*============================================================================*/
+/* Public definitions */
+/*============================================================================*/
+
+#if EP_SIM == BASIC || !defined(STRIP)
+
+void ep4_mul_sim_basic(ep4_t r, ep4_t p, bn_t k, ep4_t q, bn_t l) {
+ ep4_t t;
+
+ ep4_null(t);
+
+ RLC_TRY {
+ ep4_new(t);
+ ep4_mul(t, q, l);
+ ep4_mul(r, p, k);
+ ep4_add(t, t, r);
+ ep4_norm(r, t);
+
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ ep4_free(t);
+ }
+}
+
+#endif
+
+#if EP_SIM == TRICK || !defined(STRIP)
+
+void ep4_mul_sim_trick(ep4_t r, ep4_t p, bn_t k, ep4_t q, bn_t m) {
+ ep4_t t0[1 << (EP_WIDTH / 2)];
+ ep4_t t1[1 << (EP_WIDTH / 2)];
+ ep4_t t[1 << EP_WIDTH];
+ bn_t n;
+ int l0, l1, w = EP_WIDTH / 2;
+ uint8_t w0[2 * RLC_FP_BITS], w1[2 * RLC_FP_BITS];
+
+ bn_null(n);
+
+ if (bn_is_zero(k) || ep4_is_infty(p)) {
+ ep4_mul(r, q, m);
+ return;
+ }
+ if (bn_is_zero(m) || ep4_is_infty(q)) {
+ ep4_mul(r, p, k);
+ return;
+ }
+
+ RLC_TRY {
+ bn_new(n);
+
+ ep4_curve_get_ord(n);
+
+ for (int i = 0; i < (1 << w); i++) {
+ ep4_null(t0[i]);
+ ep4_null(t1[i]);
+ ep4_new(t0[i]);
+ ep4_new(t1[i]);
+ }
+ for (int i = 0; i < (1 << EP_WIDTH); i++) {
+ ep4_null(t[i]);
+ ep4_new(t[i]);
+ }
+
+ ep4_set_infty(t0[0]);
+ ep4_copy(t0[1], p);
+ if (bn_sign(k) == RLC_NEG) {
+ ep4_neg(t0[1], t0[1]);
+ }
+ for (int i = 2; i < (1 << w); i++) {
+ ep4_add(t0[i], t0[i - 1], t0[1]);
+ }
+
+ ep4_set_infty(t1[0]);
+ ep4_copy(t1[1], q);
+ if (bn_sign(m) == RLC_NEG) {
+ ep4_neg(t1[1], t1[1]);
+ }
+ for (int i = 1; i < (1 << w); i++) {
+ ep4_add(t1[i], t1[i - 1], t1[1]);
+ }
+
+ for (int i = 0; i < (1 << w); i++) {
+ for (int j = 0; j < (1 << w); j++) {
+ ep4_add(t[(i << w) + j], t0[i], t1[j]);
+ }
+ }
+
+#if defined(EP_MIXED)
+ ep4_norm_sim(t + 1, t + 1, (1 << (EP_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);
+
+ 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++) {
+ ep4_dbl(r, r);
+ }
+ ep4_add(r, r, t[(w0[i] << w) + w1[i]]);
+ }
+ ep4_norm(r, r);
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ for (int i = 0; i < (1 << w); i++) {
+ ep4_free(t0[i]);
+ ep4_free(t1[i]);
+ }
+ for (int i = 0; i < (1 << EP_WIDTH); i++) {
+ ep4_free(t[i]);
+ }
+ }
+}
+#endif
+
+#if EP_SIM == INTER || !defined(STRIP)
+
+void ep4_mul_sim_inter(ep4_t r, ep4_t p, bn_t k, ep4_t q, bn_t m) {
+ if (bn_is_zero(k) || ep4_is_infty(p)) {
+ ep4_mul(r, q, m);
+ return;
+ }
+ if (bn_is_zero(m) || ep4_is_infty(q)) {
+ ep4_mul(r, p, k);
+ return;
+ }
+
+ ep4_mul_sim_plain(r, p, k, q, m, NULL);
+}
+
+#endif
+
+#if EP_SIM == JOINT || !defined(STRIP)
+
+void ep4_mul_sim_joint(ep4_t r, ep4_t p, bn_t k, ep4_t q, bn_t m) {
+ ep4_t t[5];
+ int i, l, u_i, offset;
+ int8_t jsf[4 * (RLC_FP_BITS + 1)];
+
+ if (bn_is_zero(k) || ep4_is_infty(p)) {
+ ep4_mul(r, q, m);
+ return;
+ }
+ if (bn_is_zero(m) || ep4_is_infty(q)) {
+ ep4_mul(r, p, k);
+ return;
+ }
+
+ RLC_TRY {
+ for (i = 0; i < 5; i++) {
+ ep4_null(t[i]);
+ ep4_new(t[i]);
+ }
+
+ ep4_set_infty(t[0]);
+ ep4_copy(t[1], q);
+ if (bn_sign(m) == RLC_NEG) {
+ ep4_neg(t[1], t[1]);
+ }
+ ep4_copy(t[2], p);
+ if (bn_sign(k) == RLC_NEG) {
+ ep4_neg(t[2], t[2]);
+ }
+ ep4_add(t[3], t[2], t[1]);
+ ep4_sub(t[4], t[2], t[1]);
+#if defined(EP_MIXED)
+ ep4_norm_sim(t + 3, t + 3, 2);
+#endif
+
+ l = 4 * (RLC_FP_BITS + 1);
+ bn_rec_jsf(jsf, &l, k, m);
+
+ ep4_set_infty(r);
+
+ offset = RLC_MAX(bn_bits(k), bn_bits(m)) + 1;
+ for (i = l - 1; i >= 0; i--) {
+ ep4_dbl(r, r);
+ if (jsf[i] != 0 && jsf[i] == -jsf[i + offset]) {
+ u_i = jsf[i] * 2 + jsf[i + offset];
+ if (u_i < 0) {
+ ep4_sub(r, r, t[4]);
+ } else {
+ ep4_add(r, r, t[4]);
+ }
+ } else {
+ u_i = jsf[i] * 2 + jsf[i + offset];
+ if (u_i < 0) {
+ ep4_sub(r, r, t[-u_i]);
+ } else {
+ ep4_add(r, r, t[u_i]);
+ }
+ }
+ }
+ ep4_norm(r, r);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ for (i = 0; i < 5; i++) {
+ ep4_free(t[i]);
+ }
+ }
+}
+
+#endif
+
+void ep4_mul_sim_gen(ep4_t r, bn_t k, ep4_t q, bn_t m) {
+ ep4_t gen;
+
+ ep4_null(gen);
+
+ if (bn_is_zero(k)) {
+ ep4_mul(r, q, m);
+ return;
+ }
+ if (bn_is_zero(m) || ep4_is_infty(q)) {
+ ep4_mul_gen(r, k);
+ return;
+ }
+
+ RLC_TRY {
+ ep4_new(gen);
+
+ ep4_curve_get_gen(gen);
+#if EP_FIX == LWNAF && defined(EP_PRECO)
+ ep4_mul_sim_plain(r, gen, k, q, m, ep4_curve_get_tab());
+#else
+ ep4_mul_sim(r, gen, k, q, m);
+#endif
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ ep4_free(gen);
+ }
+}
+
+void ep4_mul_sim_dig(ep4_t r, ep4_t p[], dig_t k[], int len) {
+ ep4_t t;
+ int max;
+
+ ep4_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 {
+ ep4_new(t);
+
+ ep4_set_infty(t);
+ for (int i = max - 1; i >= 0; i--) {
+ ep4_dbl(t, t);
+ for (int j = 0; j < len; j++) {
+ if (k[j] & ((dig_t)1 << i)) {
+ ep4_add(t, t, p[j]);
+ }
+ }
+ }
+
+ ep4_norm(r, t);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ ep4_free(t);
+ }
+}
+
+void ep4_mul_sim_lot(ep4_t r, ep4_t p[], const bn_t k[], int n) {
+ const int len = RLC_FP_BITS + 1;
+ int i, j, m, l, *_l = RLC_ALLOCA(int, 8 * n);
+ bn_t _k[8], q, x;
+ int8_t *naf = RLC_ALLOCA(int8_t, 8 * n * len);
+
+ bn_null(q);
+ bn_null(x);
+
+ if (n <= 10) {
+ ep4_t *_p = RLC_ALLOCA(ep4_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++) {
+ ep4_null(_p[8*i + j]);
+ ep4_new(_p[8*i + j]);
+ }
+ }
+
+ for (int i = 0; i < n; i++) {
+ ep4_norm(_p[8*i], p[i]);
+ ep4_frb(_p[8*i + 1], _p[8*i], 1);
+ ep4_frb(_p[8*i + 2], _p[8*i + 1], 1);
+ ep4_frb(_p[8*i + 3], _p[8*i + 2], 1);
+ ep4_frb(_p[8*i + 4], _p[8*i + 3], 1);
+ ep4_frb(_p[8*i + 5], _p[8*i + 4], 1);
+ ep4_frb(_p[8*i + 6], _p[8*i + 5], 1);
+ ep4_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());
+ 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) {
+ ep4_neg(_p[8*i + j], _p[8*i + j]);
+ }
+ 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;
+ }
+ }
+ }
+
+ ep4_set_infty(r);
+ for (i = l - 1; i >= 0; i--) {
+ ep4_dbl(r, r);
+ for (j = 0; j < n; j++) {
+ for (m = 0; m < 8; m++) {
+ if (naf[(8*j + m)*len + i] > 0) {
+ ep4_add(r, r, _p[8*j + m]);
+ }
+ if (naf[(8*j + m)*len + i] < 0) {
+ ep4_sub(r, r, _p[8*j + m]);
+ }
+ }
+ }
+ }
+
+ /* Convert r to affine coordinates. */
+ ep4_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++) {
+ ep4_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));
+ ep4_t s, t, u, v, *_p = RLC_ALLOCA(ep4_t, 8 * c);
+ int8_t ptr;
+
+ ep4_null(s);
+ ep4_null(t);
+ ep4_null(u);
+ ep4_null(v);
+
+ RLC_TRY {
+ bn_new(q);
+ bn_new(x);
+ ep4_new(s);
+ ep4_new(t);
+ ep4_new(u);
+ ep4_new(v);
+ for (i = 0; i < 8; i++) {
+ bn_null(_k[i]);
+ bn_new(_k[i]);
+ for (j = 0; j < c; j++) {
+ ep4_null(_p[i*c + j]);
+ ep4_new(_p[i*c + j]);
+ ep4_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());
+ 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;
+ }
+ }
+ }
+
+ ep4_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) {
+ ep4_copy(t, p[j]);
+ if (ptr < 0) {
+ ptr = -ptr;
+ ep4_neg(t, t);
+ }
+ if (bn_sign(_k[m]) == RLC_NEG) {
+ ep4_neg(t, t);
+ }
+ ep4_add(_p[m*c + (ptr >> 1)], _p[m*c + (ptr >> 1)], t);
+ }
+ }
+ }
+
+ ep4_set_infty(t);
+ for (m = 3; m >= 0; m--) {
+ ep4_frb(t, t, 1);
+ ep4_set_infty(u);
+ ep4_set_infty(v);
+ for (j = c - 1; j >= 0; j--) {
+ ep4_add(u, u, _p[m*c + j]);
+ if (j == 0) {
+ ep4_dbl(v, v);
+ }
+ ep4_add(v, v, u);
+ ep4_set_infty(_p[m*c + j]);
+ }
+ ep4_add(t, t, v);
+ }
+ ep4_dbl(s, s);
+ ep4_add(s, s, t);
+ }
+
+ /* Convert r to affine coordinates. */
+ ep4_norm(r, s);
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ } RLC_FINALLY {
+ bn_free(q);
+ bn_free(x);
+ ep4_free(s);
+ ep4_free(t);
+ ep4_free(u);
+ ep4_free(v);
+ for (i = 0; i < 8; i++) {
+ bn_free(_k[i]);
+ for (j = 0; j < c; j++) {
+ ep4_free(_p[i*c + j]);
+ }
+ }
+ RLC_FREE(_l);
+ RLC_FREE(_p);
+ RLC_FREE(naf);
+ }
+ }
+}
diff --git a/contrib/relic/src/epx/relic_ep4_neg.c b/contrib/relic/src/epx/relic_ep4_neg.c
new file mode 100644
index 000000000..4351c809c
--- /dev/null
+++ b/contrib/relic/src/epx/relic_ep4_neg.c
@@ -0,0 +1,53 @@
+/*
+ * RELIC is an Efficient LIbrary for Cryptography
+ * Copyright (c) 2021 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 ep4_neg(ep4_t r, ep4_t p) {
+ if (ep4_is_infty(p)) {
+ ep4_set_infty(r);
+ return;
+ }
+
+ if (r != p) {
+ fp4_copy(r->x, p->x);
+ fp4_copy(r->z, p->z);
+ }
+
+ fp4_neg(r->y, p->y);
+
+ r->coord = p->coord;
+}
diff --git a/contrib/relic/src/epx/relic_ep4_norm.c b/contrib/relic/src/epx/relic_ep4_norm.c
new file mode 100644
index 000000000..8ad02259c
--- /dev/null
+++ b/contrib/relic/src/epx/relic_ep4_norm.c
@@ -0,0 +1,138 @@
+/*
+ * RELIC is an Efficient LIbrary for Cryptography
+ * Copyright (c) 2021 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 quartic
+ * 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 ep4_norm_imp(ep4_t r, ep4_t p, int inverted) {
+ if (p->coord != BASIC) {
+ fp4_t t0, t1;
+
+ fp4_null(t0);
+ fp4_null(t1);
+
+ RLC_TRY {
+
+ fp4_new(t0);
+ fp4_new(t1);
+
+ if (inverted) {
+ fp4_copy(t1, p->z);
+ } else {
+ fp4_inv(t1, p->z);
+ }
+ fp4_sqr(t0, t1);
+ fp4_mul(r->x, p->x, t0);
+ fp4_mul(t0, t0, t1);
+ fp4_mul(r->y, p->y, t0);
+ fp4_set_dig(r->z, 1);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ fp4_free(t0);
+ fp4_free(t1);
+ }
+ }
+
+ r->coord = BASIC;
+}
+
+#endif /* EP_ADD == PROJC */
+
+/*============================================================================*/
+/* Public definitions */
+/*============================================================================*/
+
+void ep4_norm(ep4_t r, 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)
+ ep4_norm_imp(r, p, 0);
+#endif
+}
+
+void ep4_norm_sim(ep4_t *r, ep4_t *t, int n) {
+ int i;
+ fp4_t *a = RLC_ALLOCA(fp4_t, n);
+
+ RLC_TRY {
+ if (a == NULL) {
+ RLC_THROW(ERR_NO_MEMORY);
+ }
+ for (i = 0; i < n; i++) {
+ fp4_null(a[i]);
+ fp4_new(a[i]);
+ fp4_copy(a[i], t[i]->z);
+ }
+
+ fp4_inv_sim(a, a, n);
+
+ for (i = 0; i < n; i++) {
+ fp4_copy(r[i]->x, t[i]->x);
+ fp4_copy(r[i]->y, t[i]->y);
+ fp4_copy(r[i]->z, a[i]);
+ }
+
+ for (i = 0; i < n; i++) {
+ ep4_norm_imp(r[i], r[i], 1);
+ }
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ for (i = 0; i < n; i++) {
+ fp4_free(a[i]);
+ }
+ RLC_FREE(a);
+ }
+}
diff --git a/contrib/relic/src/epx/relic_ep4_util.c b/contrib/relic/src/epx/relic_ep4_util.c
new file mode 100644
index 000000000..1bba16f2b
--- /dev/null
+++ b/contrib/relic/src/epx/relic_ep4_util.c
@@ -0,0 +1,318 @@
+/*
+ * RELIC is an Efficient LIbrary for Cryptography
+ * Copyright (c) 2021 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 ep4_is_infty(ep4_t p) {
+ return (fp4_is_zero(p->z) == 1);
+}
+
+void ep4_set_infty(ep4_t p) {
+ fp4_zero(p->x);
+ fp4_zero(p->y);
+ fp4_zero(p->z);
+ p->coord = BASIC;
+}
+
+void ep4_copy(ep4_t r, ep4_t p) {
+ fp4_copy(r->x, p->x);
+ fp4_copy(r->y, p->y);
+ fp4_copy(r->z, p->z);
+ r->coord = p->coord;
+}
+
+void ep4_rand(ep4_t p) {
+ bn_t n, k;
+
+ bn_null(k);
+ bn_null(n);
+
+ RLC_TRY {
+ bn_new(k);
+ bn_new(n);
+
+ ep4_curve_get_ord(n);
+ bn_rand_mod(k, n);
+
+ ep4_mul_gen(p, k);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ bn_free(k);
+ bn_free(n);
+ }
+}
+
+void ep4_blind(ep4_t r, ep4_t p) {
+ fp4_t rand;
+
+ fp4_null(rand);
+
+ RLC_TRY {
+ fp4_new(rand);
+ fp4_rand(rand);
+#if EP_ADD == BASIC
+ (void)rand;
+ ep4_copy(r, p);
+#else
+ fp4_mul(r->z, p->z, rand);
+ fp4_mul(r->y, p->y, rand);
+ fp4_sqr(rand, rand);
+ fp4_mul(r->x, r->x, rand);
+ fp4_mul(r->y, r->y, rand);
+ r->coord = EP_ADD;
+#endif
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ } RLC_FINALLY {
+ fp4_free(rand);
+ }
+}
+
+void ep4_rhs(fp4_t rhs, ep4_t p) {
+ fp4_t t0, t1;
+
+ fp4_null(t0);
+ fp4_null(t1);
+
+ RLC_TRY {
+ fp4_new(t0);
+ fp4_new(t1);
+
+ fp4_sqr(t0, p->x); /* x1^2 */
+
+ switch (ep4_curve_opt_a()) {
+ case RLC_ZERO:
+ break;
+#if FP_RDC != MONTY
+ case RLC_MIN3:
+ fp4_sub_dig(t0, t0, 3);
+ break;
+ case RLC_ONE:
+ fp4_add_dig(t0, t0, 1);
+ break;
+ case RLC_TWO:
+ fp4_add_dig(t0, t0, 2);
+ break;
+ case RLC_TINY:
+ ep4_curve_get_a(t1);
+ fp4_mul_dig(t0, t0, t1[0][0]);
+ break;
+#endif
+ default:
+ ep4_curve_get_a(t1);
+ fp4_add(t0, t0, t1);
+ break;
+ }
+
+ fp4_mul(t0, t0, p->x); /* x1^3 + a * x */
+
+ switch (ep4_curve_opt_b()) {
+ case RLC_ZERO:
+ break;
+#if FP_RDC != MONTY
+ case RLC_MIN3:
+ fp4_sub_dig(t0, t0, 3);
+ break;
+ case RLC_ONE:
+ fp4_add_dig(t0, t0, 1);
+ break;
+ case RLC_TWO:
+ fp4_add_dig(t0, t0, 2);
+ break;
+ case RLC_TINY:
+ ep4_curve_get_b(t1);
+ fp4_mul_dig(t0, t0, t1[0][0]);
+ break;
+#endif
+ default:
+ ep4_curve_get_b(t1);
+ fp4_add(t0, t0, t1);
+ break;
+ }
+
+ fp4_copy(rhs, t0);
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ } RLC_FINALLY {
+ fp4_free(t0);
+ fp4_free(t1);
+ }
+}
+
+
+int ep4_on_curve(ep4_t p) {
+ ep4_t t;
+ int r = 0;
+
+ ep4_null(t);
+
+ RLC_TRY {
+ ep4_new(t);
+
+ ep4_norm(t, p);
+
+ ep4_rhs(t->x, t);
+ fp4_sqr(t->y, t->y);
+
+ r = (fp4_cmp(t->x, t->y) == RLC_EQ) || ep4_is_infty(p);
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ } RLC_FINALLY {
+ ep4_free(t);
+ }
+ return r;
+}
+
+void ep4_tab(ep4_t *t, ep4_t p, int w) {
+ if (w > 2) {
+ ep4_dbl(t[0], p);
+#if defined(EP_MIXED)
+ ep4_norm(t[0], t[0]);
+#endif
+ ep4_add(t[1], t[0], p);
+ for (int i = 2; i < (1 << (w - 2)); i++) {
+ ep4_add(t[i], t[i - 1], t[0]);
+ }
+#if defined(EP_MIXED)
+ ep4_norm_sim(t + 1, t + 1, (1 << (w - 2)) - 1);
+#endif
+ }
+ ep4_copy(t[0], p);
+}
+
+void ep4_print(ep4_t p) {
+ fp4_print(p->x);
+ fp4_print(p->y);
+ fp4_print(p->z);
+}
+
+int ep4_size_bin(ep4_t a, int pack) {
+ ep4_t t;
+ int size = 0;
+
+ ep4_null(t);
+
+ if (ep4_is_infty(a)) {
+ return 1;
+ }
+
+ RLC_TRY {
+ ep4_new(t);
+
+ ep4_norm(t, a);
+
+ size = 1 + 8 * RLC_FP_BYTES;
+ //TODO: Implement compression.
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ } RLC_FINALLY {
+ ep4_free(t);
+ }
+
+ return size;
+}
+
+void ep4_read_bin(ep4_t a, const uint8_t *bin, int len) {
+ if (len == 1) {
+ if (bin[0] == 0) {
+ ep4_set_infty(a);
+ return;
+ } else {
+ RLC_THROW(ERR_NO_BUFFER);
+ return;
+ }
+ }
+
+ if (len != (8 * RLC_FP_BYTES + 1)) {
+ RLC_THROW(ERR_NO_BUFFER);
+ return;
+ }
+
+ a->coord = BASIC;
+ fp4_set_dig(a->z, 1);
+ fp4_read_bin(a->x, bin + 1, 4 * RLC_FP_BYTES);
+
+ if (len == 8 * RLC_FP_BYTES + 1) {
+ if (bin[0] == 4) {
+ fp4_read_bin(a->y, bin + 4 * RLC_FP_BYTES + 1, 4 * RLC_FP_BYTES);
+ } else {
+ RLC_THROW(ERR_NO_VALID);
+ return;
+ }
+ }
+
+ if (!ep4_on_curve(a)) {
+ RLC_THROW(ERR_NO_VALID);
+ }
+}
+
+void ep4_write_bin(uint8_t *bin, int len, ep4_t a, int pack) {
+ ep4_t t;
+
+ ep4_null(t);
+
+ memset(bin, 0, len);
+
+ if (ep4_is_infty(a)) {
+ if (len < 1) {
+ RLC_THROW(ERR_NO_BUFFER);
+ return;
+ } else {
+ return;
+ }
+ }
+
+ RLC_TRY {
+ ep4_new(t);
+
+ ep4_norm(t, a);
+
+ if (len < 8 * RLC_FP_BYTES + 1) {
+ RLC_THROW(ERR_NO_BUFFER);
+ } else {
+ bin[0] = 4;
+ fp4_write_bin(bin + 1, 4 * RLC_FP_BYTES, t->x);
+ fp4_write_bin(bin + 4 * RLC_FP_BYTES + 1, 4 * RLC_FP_BYTES, t->y);
+ }
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ } RLC_FINALLY {
+ ep4_free(t);
+ }
+}
diff --git a/contrib/relic/src/fb/relic_fb_itr.c b/contrib/relic/src/fb/relic_fb_itr.c
index 95e81eafb..7ad4dd761 100644
--- a/contrib/relic/src/fb/relic_fb_itr.c
+++ b/contrib/relic/src/fb/relic_fb_itr.c
@@ -56,7 +56,7 @@ void fb_itr_basic(fb_t c, const fb_t a, int b) {
}
}
-void fb_itr_pre_quick(fb_t *t, int b) {
+void fb_itr_pre_quick(fb_st *t, int b) {
int i, j, k;
fb_t r;
@@ -80,11 +80,7 @@ void fb_itr_pre_quick(fb_t *t, int b) {
}
}
-#if ALLOC == AUTO
fb_copy((dig_t *)t + (4 * i + j) * RLC_FB_DIGS, r);
-#else
- fb_copy(t[4 * i + j], r);
-#endif
}
}
} RLC_CATCH_ANY {
@@ -94,6 +90,6 @@ void fb_itr_pre_quick(fb_t *t, int b) {
}
}
-void fb_itr_quick(fb_t c, const fb_t a, const fb_t *t) {
+void fb_itr_quick(fb_t c, const fb_t a, const fb_st *t) {
fb_itrn_low(c, a, (dig_t *)t);
}
diff --git a/contrib/relic/src/fb/relic_fb_poly.c b/contrib/relic/src/fb/relic_fb_poly.c
index 7fd38a8e0..0e67cf073 100644
--- a/contrib/relic/src/fb/relic_fb_poly.c
+++ b/contrib/relic/src/fb/relic_fb_poly.c
@@ -267,12 +267,6 @@ static void find_chain(void) {
break;
}
- for (i = 0; i < RLC_TERMS; i++) {
- for (j = 0; j < RLC_FB_TABLE; j++) {
- ctx->fb_tab_ptr[i][j] = &(ctx->fb_tab_sqr[i][j]);
- }
- }
-
u[0] = 1;
u[1] = 2;
for (i = 2; i <= ctx->chain_len; i++) {
@@ -286,7 +280,7 @@ static void find_chain(void) {
}
for (i = 0; i <= ctx->chain_len; i++) {
- fb_itr_pre((fb_t *)fb_poly_tab_sqr(i), u[i]);
+ fb_itr_pre((fb_st *)fb_poly_tab_sqr(i), u[i]);
}
}
@@ -436,15 +430,10 @@ dig_t *fb_poly_get_srz(void) {
#endif
}
-const fb_t *fb_poly_tab_sqr(int i) {
+const fb_st *fb_poly_tab_sqr(int i) {
#if FB_INV == ITOHT || !defined(STRIP)
/* If ITOHT inversion is used and tables are precomputed, return them. */
-#if ALLOC == AUTO
- return (const fb_t *)*core_get()->fb_tab_ptr[i];
-#else
- return (const fb_t *)core_get()->fb_tab_ptr[i];
-#endif
-
+ return (const fb_st *)core_get()->fb_tab_sqr[i];
#else
return NULL;
#endif
diff --git a/contrib/relic/src/fp/relic_fp_inv.c b/contrib/relic/src/fp/relic_fp_inv.c
index 1ff56e27c..1805ab4bd 100644
--- a/contrib/relic/src/fp/relic_fp_inv.c
+++ b/contrib/relic/src/fp/relic_fp_inv.c
@@ -399,31 +399,27 @@ void fp_inv_exgcd(fp_t c, const fp_t a) {
#endif
-#include "assert.h"
-
#if FP_INV == DIVST || !defined(STRIP)
void fp_inv_divst(fp_t c, const fp_t a) {
- /* Compute number of iteratios based on modulus size. */
+ /* Compute number of iterations based on modulus size. */
#if FP_PRIME < 46
- int d = (49 * FP_PRIME + 80)/17;
+ int d = (49 * FP_PRIME + 80) / 17;
#else
- int d = (49 * FP_PRIME + 57)/17;
+ int d = (49 * FP_PRIME + 57) / 17;
#endif
int g0, d0;
dig_t fs, gs, delta = 1;
bn_t _t;
- dv_t f, g, t, u;
- fp_t precomp, v, r;
+ fp_t f, g, t, u, v, r;
bn_null(_t);
- dv_null(f);
- dv_null(g);
- dv_null(t);
- dv_null(u);
+ fp_null(f);
+ fp_null(g);
+ fp_null(t);
+ fp_null(u);
fp_null(v);
fp_null(r);
- fp_null(precomp);
if (fp_is_zero(a)) {
RLC_THROW(ERR_NO_VALID);
@@ -432,19 +428,12 @@ void fp_inv_divst(fp_t c, const fp_t a) {
RLC_TRY {
bn_new(_t);
- dv_new(f);
- dv_new(g);
- dv_new(t);
- dv_new(u);
+ fp_new(f);
+ fp_new(g);
+ fp_new(t);
+ fp_new(u);
fp_new(v);
fp_new(r);
- fp_new(precomp);
-
- bn_set_dig(_t, d);
- dv_copy(precomp, fp_prime_get(), RLC_FP_DIGS);
- fp_add_dig(precomp, precomp, 1);
- fp_hlv(precomp, precomp);
- fp_exp(precomp, precomp, _t);
fp_zero(v);
fp_set_dig(r, 1);
@@ -491,18 +480,317 @@ void fp_inv_divst(fp_t c, const fp_t a) {
}
fp_neg(t, v);
dv_copy_cond(v, t, RLC_FP_DIGS, fs);
- fp_mul(c, v, precomp);
+
+ dv_copy(t, fp_prime_get(), RLC_FP_DIGS);
+ fp_add_dig(t, t, 1);
+ fp_hlv(t, t);
+#if WSIZE == 8
+ bn_set_dig(_t, d >> 8);
+ bn_lsh(_t, _t, 8);
+ bn_add_dig(_t, _t, d & 0xFF);
+#else
+ bn_set_dig(_t, d);
+#endif
+ fp_exp(t, t, _t);
+
+ fp_mul(c, v, t);
} RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT)
} RLC_FINALLY {
bn_free(_t);
- dv_free(f);
- dv_free(g);
- dv_free(t);
- dv_free(u);
+ fp_free(f);
+ fp_free(g);
+ fp_free(t);
+ fp_free(u);
fp_free(v);
fp_free(r);
- fp_free(precomp);
+ }
+}
+
+#endif
+
+#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];
+ /* 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;
+ dv_t f, g, t, p, t0, t1, u0, u1, v0, v1, p01, p11;
+ fp_t pre;
+
+ 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);
+ fp_null(pre);
+
+ RLC_TRY {
+ dv_new(t0);
+ dv_new(f);
+ dv_new(t);
+ dv_new(p);
+ dv_new(g);
+ dv_new(t1);
+ dv_new(u0);
+ dv_new(u1);
+ dv_new(v0);
+ dv_new(v1);
+ dv_new(p01);
+ dv_new(p11);
+ fp_new(pre);
+
+#if (FP_PRIME % WSIZE) != 0
+ int j = 0;
+ fp_copy(pre, core_get()->inv.dp);
+#else
+ fp_copy(pre, core_get()->conv.dp);
+ 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);
+ 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(f, fp_prime_get(), RLC_FP_DIGS);
+ dv_copy(p + 1, fp_prime_get(), RLC_FP_DIGS);
+#if FP_RDC == MONTY
+ /* Convert a from Montgomery form. */
+ fp_copy(t, a);
+ fp_rdcn_low(g, t);
+#else
+ fp_copy(g, a);
+#endif
+ 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_POS, m[0], RLC_FP_DIGS);
+ t1[RLC_FP_DIGS] = bn_muls_low(t1, g, RLC_POS, 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_POS, m[2], RLC_FP_DIGS);
+ t1[RLC_FP_DIGS] = bn_muls_low(t1, g, RLC_POS, m[3], RLC_FP_DIGS);
+ bn_addn_low(t1, t1, f, RLC_FP_DIGS + 1);
+
+ /* Update f and g. */
+ bn_rshs_low(f, t0, RLC_FP_DIGS + 1, s);
+ bn_rshs_low(g, t1, RLC_FP_DIGS + 1, s);
+
+ /* Update column vector below. */
+ v1[0] = RLC_SEL(m[1], -m[1], RLC_SIGN(m[1]));
+ fp_negm_low(t, v1);
+ dv_copy_cond(v1, t, RLC_FP_DIGS, RLC_SIGN(m[1]));
+ u1[0] = RLC_SEL(m[3], -m[3], RLC_SIGN(m[3]));
+ fp_negm_low(t, u1);
+ dv_copy_cond(u1, t, RLC_FP_DIGS, RLC_SIGN(m[3]));
+
+ dv_copy(p01, v1, 2 * RLC_FP_DIGS);
+ dv_copy(p11, u1, 2 * RLC_FP_DIGS);
+
+ int 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);
+
+ /* Update f and g. */
+ bn_rshs_low(f, t0, RLC_FP_DIGS + 1, s);
+ bn_rshs_low(g, t1, RLC_FP_DIGS + 1, s);
+
+#if (FP_PRIME % WSIZE) != 0
+ p[j] = 0;
+ dv_copy(p + j + 1, fp_prime_get(), RLC_FP_DIGS);
+
+ /* Update column vector below. */
+ bn_mul2_low(v0, p01, m[0], RLC_FP_DIGS + j);
+ fp_subd_low(t, p, v0);
+ dv_copy_cond(v0, t, RLC_FP_DIGS + j + 1, RLC_SIGN(m[0]));
+
+ bn_mul2_low(v1, p11, m[1], RLC_FP_DIGS + j);
+ fp_subd_low(t, p, v1);
+ dv_copy_cond(v1, t, RLC_FP_DIGS + j + 1, RLC_SIGN(m[1]));
+
+ bn_mul2_low(u0, p01, m[2], RLC_FP_DIGS + j);
+ fp_subd_low(t, p, u0);
+ dv_copy_cond(u0, t, RLC_FP_DIGS + j + 1, RLC_SIGN(m[2]));
+
+ bn_mul2_low(u1, p11, m[3], RLC_FP_DIGS + j);
+ fp_subd_low(t, p, u1);
+ dv_copy_cond(u1, t, RLC_FP_DIGS + j + 1, RLC_SIGN(m[3]));
+
+ j = i % RLC_FP_DIGS;
+ if (j == 0) {
+ fp_addd_low(t, u0, u1);
+ fp_rdcn_low(p11, t);
+ fp_addd_low(t, v0, v1);
+ fp_rdcn_low(p01, t);
+ dv_zero(v0, 2 * RLC_FP_DIGS);
+ dv_zero(v1, 2 * RLC_FP_DIGS);
+ } else {
+ fp_addd_low(p11, u0, u1);
+ fp_addd_low(p01, v0, v1);
+ }
+#else
+ fp_zero(p);
+ dv_copy(p + RLC_FP_DIGS, fp_prime_get(), RLC_FP_DIGS);
+
+ /* Update column vector below. */
+ bn_mul2_low(v0, p01, m[0], 2 * RLC_FP_DIGS);
+ fp_subd_low(t, p, v0);
+ dv_copy_cond(v0, t, 2 * RLC_FP_DIGS, RLC_SIGN(m[0]));
+
+ bn_mul2_low(v1, p11, m[1], 2 * RLC_FP_DIGS);
+ fp_subd_low(t, p, v1);
+ dv_copy_cond(v1, t, 2 * RLC_FP_DIGS, RLC_SIGN(m[1]));
+
+ bn_mul2_low(u0, p01, m[2], 2 * RLC_FP_DIGS);
+ fp_subd_low(t, p, u0);
+ dv_copy_cond(u0, t, 2 * RLC_FP_DIGS, RLC_SIGN(m[2]));
+
+ bn_mul2_low(u1, p11, m[3], 2 * RLC_FP_DIGS);
+ fp_subd_low(t, p, u1);
+ dv_copy_cond(u1, t, 2 * RLC_FP_DIGS, RLC_SIGN(m[3]));
+
+ fp_addc_low(t, u0, u1);
+ fp_rdcn_low(p11, t);
+ fp_addc_low(t, v0, v1);
+ fp_rdcn_low(p01, t);
+ fp_mulm_low(pre, pre, core_get()->conv.dp);
+#endif
+ }
+
+ 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);
+
+ /* Update f and g. */
+ bn_rshs_low(f, t0, RLC_FP_DIGS + 1, s);
+ bn_rshs_low(g, t1, RLC_FP_DIGS + 1, s);
+
+#if (FP_PRIME % WSIZE) != 0
+ 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);
+ dv_copy_cond(v0, t, RLC_FP_DIGS + j + 1, RLC_SIGN(m[0]));
+
+ bn_mul2_low(v1, p11, m[1], RLC_FP_DIGS + j);
+ fp_subd_low(t, p, v1);
+ dv_copy_cond(v1, t, RLC_FP_DIGS + j + 1, RLC_SIGN(m[1]));
+
+ fp_addd_low(t, v0, v1);
+ fp_rdcn_low(p01, t);
+#else
+ fp_zero(p);
+ dv_copy(p + RLC_FP_DIGS, fp_prime_get(), RLC_FP_DIGS);
+
+ /* Update column vector below. */
+ bn_mul2_low(v0, p01, m[0], 2 * RLC_FP_DIGS);
+ fp_subd_low(t, p, v0);
+ dv_copy_cond(v0, t, 2 * RLC_FP_DIGS, RLC_SIGN(m[0]));
+
+ bn_mul2_low(v1, p11, m[1], 2 * RLC_FP_DIGS);
+ fp_subd_low(t, p, v1);
+ dv_copy_cond(v1, t, 2 * RLC_FP_DIGS, RLC_SIGN(m[1]));
+
+ fp_addc_low(t, v0, v1);
+ fp_rdcn_low(p01, t);
+#endif
+
+ /* Negate based on sign of f at the end. */
+ fp_negm_low(t, p01);
+ dv_copy_cond(p01, t, RLC_FP_DIGS, f[RLC_FP_DIGS] >> (RLC_DIG - 1));
+ /* Multiply by (precomp * R^j) % p, one for each iteration of the loop,
+ * one for the constant, one more to be removed by reduction. */
+ fp_mul(c, p01, pre);
+ }
+ 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(t1);
+ dv_free(u0);
+ dv_free(u1);
+ dv_free(v0);
+ dv_free(v1);
+ dv_free(p01);
+ dv_free(p11);
+ fp_free(pre);
}
}
diff --git a/contrib/relic/src/fp/relic_fp_mul.c b/contrib/relic/src/fp/relic_fp_mul.c
index bdfbe43cd..a9cf0aa67 100644
--- a/contrib/relic/src/fp/relic_fp_mul.c
+++ b/contrib/relic/src/fp/relic_fp_mul.c
@@ -137,7 +137,9 @@ static void fp_mul_karat_imp(dv_t c, const fp_t a, const fp_t b, int size,
c += h;
carry = bn_addn_low(c, c, t, 2 * (h1 + 1));
c += 2 * (h1 + 1);
- bn_add1_low(c, c, carry, 2 * size - h - 2 * (h1 + 1));
+ if (2 * size > h + 2 * (h1 + 1)) {
+ bn_add1_low(c, c, carry, 2 * size - h - 2 * (h1 + 1));
+ }
}
RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
@@ -216,7 +218,7 @@ void fp_mul_comba(fp_t c, const fp_t a, const fp_t b) {
dv_new(t);
fp_muln_low(t, a, b);
- fp_rdcn_low(c, t);
+ fp_rdc(c, t);
dv_free(t);
} RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
diff --git a/contrib/relic/src/fp/relic_fp_param.c b/contrib/relic/src/fp/relic_fp_param.c
index b20aca22d..ffc8b55f6 100644
--- a/contrib/relic/src/fp/relic_fp_param.c
+++ b/contrib/relic/src/fp/relic_fp_param.c
@@ -247,6 +247,18 @@ void fp_param_set(int param) {
bn_neg(t0, t0);
fp_prime_set_pairf(t0, EP_BN);
break;
+ case SM9_256:
+ /* x = 0x600000000058F98A */
+ bn_set_2b(t0, 62);
+ bn_set_bit(t0, 61, 1);
+ bn_set_dig(t1, 0x58);
+ bn_lsh(t1, t1, 8);
+ bn_add_dig(t1, t1, 0xF9);
+ bn_lsh(t1, t1, 8);
+ bn_add(t0, t0, t1);
+ bn_add_dig(t0, t0, 0x8A);
+ fp_prime_set_pairf(t0, EP_BN);
+ break;
#elif FP_PRIME == 381
case B12_381:
/* x = -(2^63 + 2^62 + 2^60 + 2^57 + 2^48 + 2^16). */
@@ -282,6 +294,15 @@ void fp_param_set(int param) {
bn_sub_dig(p, p, 187);
fp_prime_set_dense(p);
break;
+ case B12_383:
+ /* x = 2^64 + 2^51 + 2^24 + 2^12 + 2^9 */
+ bn_set_2b(t0, 64);
+ bn_set_bit(t0, 51, 1);
+ bn_set_bit(t0, 24, 1);
+ bn_set_bit(t0, 12, 1);
+ bn_set_bit(t0, 9, 1);
+ fp_prime_set_pairf(t0, EP_B12);
+ break;
#elif FP_PRIME == 384
case NIST_384:
/* p = 2^384 - 2^128 - 2^96 + 2^32 - 1. */
@@ -313,6 +334,14 @@ void fp_param_set(int param) {
bn_neg(t0, t0);
fp_prime_set_pairf(t0, EP_B12);
break;
+#elif FP_PRIME == 448
+ case PRIME_448:
+ /* p = 2^448 - 2^224 + 1. */
+ f[0] = -1;
+ f[1] = -224;
+ f[2] = 448;
+ fp_prime_set_pmers(f, 3);
+ break;
#elif FP_PRIME == 455
case B12_455:
/* x = 2^76 + 2^53 + 2^31 + 2^11. */
@@ -322,30 +351,6 @@ void fp_param_set(int param) {
bn_set_bit(t0, 11, 1);
fp_prime_set_pairf(t0, EP_B12);
break;
-#elif FP_PRIME == 477
- case B24_477:
- /* x = -2^48 + 2^45 + 2^31 - 2^7. */
- bn_set_2b(t0, 48);
- bn_set_2b(t1, 45);
- bn_sub(t0, t0, t1);
- bn_set_2b(t1, 31);
- bn_sub(t0, t0, t1);
- bn_set_2b(t1, 7);
- bn_add(t0, t0, t1);
- bn_neg(t0, t0);
- /* p = (u - 1)^2 * (u^8 - u^4 + 1) div 3 + u. */
- bn_sub_dig(p, t0, 1);
- bn_sqr(p, p);
- bn_sqr(t1, t0);
- bn_sqr(t1, t1);
- bn_sqr(t2, t1);
- bn_sub(t2, t2, t1);
- bn_add_dig(t2, t2, 1);
- bn_mul(p, p, t2);
- bn_div_dig(p, p, 3);
- bn_add(p, p, t0);
- fp_prime_set_dense(p);
- break;
#elif FP_PRIME == 508
case KSS_508:
/* x = -(2^64 + 2^51 - 2^46 - 2^12). */
@@ -386,6 +391,18 @@ void fp_param_set(int param) {
bn_sub_dig(p, p, 1);
fp_prime_set_dense(p);
break;
+#elif FP_PRIME == 509
+ case B24_509:
+ /* x = -2^51 - 2^28 + 2^11 - 1. */
+ bn_set_2b(t0, 51);
+ bn_set_2b(t1, 28);
+ bn_add(t0, t0, t1);
+ bn_set_2b(t1, 11);
+ bn_sub(t0, t0, t1);
+ bn_add_dig(t0, t0, 1);
+ bn_neg(t0, t0);
+ fp_prime_set_pairf(t0, EP_B24);
+ break;
#elif FP_PRIME == 511
case OT_511:
bn_set_2b(t0, 52);
@@ -406,7 +423,7 @@ void fp_param_set(int param) {
fp_prime_set_pmers(f, 2);
break;
#elif FP_PRIME == 544
- case CP8_544:
+ case GMT8_544:
bn_read_str(p, STR_P544, strlen(STR_P544), 16);
/* T = 2^64 - 2^54 + 2^37 + 2^32 - 4 */
bn_set_2b(t0, 64);
@@ -417,7 +434,7 @@ void fp_param_set(int param) {
bn_set_2b(t1, 32);
bn_add(t0, t0, t1);
bn_sub_dig(t0, t0, 4);
- fp_prime_set_pairf(t0, EP_CP8);
+ fp_prime_set_pairf(t0, EP_GMT8);
fp_prime_set_dense(p);
break;
#elif FP_PRIME == 569
@@ -572,6 +589,8 @@ int fp_param_set_any_pmers(void) {
fp_param_set(NIST_256);
#elif FP_PRIME == 384
fp_param_set(NIST_384);
+#elif FP_PRIME == 448
+ fp_param_set(PRIME_448);
#elif FP_PRIME == 521
fp_param_set(NIST_521);
#else
@@ -600,6 +619,8 @@ int fp_param_set_any_tower(void) {
fp_param_set(B12_381);
#elif FP_PRIME == 382
fp_param_set(BN_382);
+#elif FP_PRIME == 383
+ fp_param_set(B12_383);
#elif FP_PRIME == 446
#ifdef FP_QNRES
fp_param_set(B12_446);
@@ -608,14 +629,14 @@ int fp_param_set_any_tower(void) {
#endif
#elif FP_PRIME == 455
fp_param_set(B12_455);
-#elif FP_PRIME == 477
- fp_param_set(B24_477);
#elif FP_PRIME == 508
fp_param_set(KSS_508);
+#elif FP_PRIME == 509
+ fp_param_set(B24_509);
#elif FP_PRIME == 511
fp_param_set(OT_511);
#elif FP_PRIME == 544
- fp_param_set(CP8_544);
+ fp_param_set(GMT8_544);
#elif FP_PRIME == 569
fp_param_set(K54_569);
#elif FP_PRIME == 575
diff --git a/contrib/relic/src/fp/relic_fp_prime.c b/contrib/relic/src/fp/relic_fp_prime.c
index 6b8c60843..7cbdbcb29 100644
--- a/contrib/relic/src/fp/relic_fp_prime.c
+++ b/contrib/relic/src/fp/relic_fp_prime.c
@@ -63,24 +63,60 @@ static void fp_prime_set(const bn_t p) {
bn_copy(&(ctx->prime), p);
- #if FP_RDC == MONTY || !defined(STRIP)
+#if FP_RDC == MONTY || !defined(STRIP)
bn_mod_pre_monty(t, &(ctx->prime));
ctx->u = t->dp[0];
/* compute R mod p */
bn_set_dig(&(ctx->one), 1);
- bn_lsh(&(ctx->one), &(ctx->one), ctx->prime.used * RLC_DIG);
+ bn_lsh(&(ctx->one), &(ctx->one), RLC_FP_DIGS * RLC_DIG);
bn_mod(&(ctx->one), &(ctx->one), &(ctx->prime));
/* compute the R^2 mod p */
fp_add(r, ctx->one.dp, ctx->one.dp);
- bn_set_dig(t, RLC_FP_DIGS * RLC_DIG);
- fp_exp(ctx->conv.dp, r, t );
+ bn_set_dig(t, RLC_FP_DIGS);
+ bn_lsh(t, t, RLC_DIG_LOG);
+ fp_exp(ctx->conv.dp, r, t);
ctx->conv.used = RLC_FP_DIGS;
bn_trim(&(ctx->conv));
- #endif /* FP_RDC == MONTY */
+#endif /* FP_RDC == MONTY */
+
+#if FP_INV == JUMPDS || !defined(STRIP)
+
+ int d = (45907 * FP_PRIME + 26313) / 19929;
+
+#if WSIZE == 8
+ bn_set_dig(t, d >> 8);
+ bn_lsh(t, t, 8);
+ bn_add_dig(t, t, d & 0xFF);
+#else
+ bn_set_dig(t, d);
+#endif
+ ctx->inv.used = RLC_FP_DIGS;
+ dv_copy(ctx->inv.dp, fp_prime_get(), RLC_FP_DIGS);
+ fp_add_dig(ctx->inv.dp, ctx->inv.dp, 1);
+ fp_hlv(ctx->inv.dp, ctx->inv.dp);
+ fp_exp(ctx->inv.dp, ctx->inv.dp, t);
+
+#if FP_RDC == MONTY
+
+#if (FP_PRIME % WSIZE) != 0
+ fp_mul(ctx->inv.dp, ctx->inv.dp, ctx->conv.dp);
+ fp_mul(ctx->inv.dp, ctx->inv.dp, ctx->conv.dp);
+
+ for (int i = 1, j = 0; i < d / (RLC_DIG - 2); i++) {
+ j = i % RLC_FP_DIGS;
+ if (j == 0) {
+ fp_mulm_low(ctx->inv.dp, ctx->inv.dp, ctx->conv.dp);
+ }
+ }
+#endif
+
+#endif /* FP_RDC == MONTY */
+
+#endif /* FP_INV */
/* Now look for proper quadratic/cubic non-residues. */
ctx->qnr = ctx->cnr = 0;
@@ -146,16 +182,19 @@ static void fp_prime_set(const bn_t p) {
void fp_prime_init(void) {
ctx_t *ctx = core_get();
ctx->fp_id = 0;
- bn_init(&(ctx->prime), RLC_FP_DIGS);
- bn_init(&(ctx->par), RLC_FP_DIGS);
+ bn_make(&(ctx->prime), RLC_FP_DIGS);
+ bn_make(&(ctx->par), RLC_FP_DIGS);
#if FP_RDC == QUICK || !defined(STRIP)
ctx->sps_len = 0;
memset(ctx->sps, 0, sizeof(ctx->sps));
#endif
#if FP_RDC == MONTY || !defined(STRIP)
- bn_init(&(ctx->conv), RLC_FP_DIGS);
- bn_init(&(ctx->one), RLC_FP_DIGS);
+ bn_make(&(ctx->conv), RLC_FP_DIGS);
+ bn_make(&(ctx->one), RLC_FP_DIGS);
#endif
+#if FP_INV == JUMPDS || !defined(STRIP)
+ bn_make(&(ctx->inv), RLC_FP_DIGS);
+#endif /* FP_INV */
}
void fp_prime_clean(void) {
@@ -170,6 +209,9 @@ void fp_prime_clean(void) {
bn_clean(&(ctx->one));
bn_clean(&(ctx->conv));
#endif
+#if FP_INV == JUMPDS || !defined(STRIP)
+ bn_clean(&(ctx->inv));
+#endif /* FP_INV */
bn_clean(&(ctx->prime));
bn_clean(&(ctx->par));
}
@@ -322,6 +364,20 @@ void fp_prime_set_pairf(const bn_t x, int pairf) {
bn_div_dig(p, p, 4);
fp_prime_set_dense(p);
break;
+ case EP_B24:
+ /* p = (x - 1)^2 * (x^8 - x^4 + 1)/3 + x. */
+ bn_sqr(t1, t0);
+ bn_sqr(t1, t1);
+ bn_sqr(p, t1);
+ bn_sub(p, p, t1);
+ bn_add_dig(p, p, 1);
+ bn_sub_dig(t1, t0, 1);
+ bn_sqr(t1, t1);
+ bn_mul(p, p, t1);
+ bn_div_dig(p, p, 3);
+ bn_add(p, p, t0);
+ fp_prime_set_dense(p);
+ break;
case EP_B48:
/* p = (x - 1)^2*(x^16 - x^8 + 1) / 3 + x. */
bn_sqr(t1, t0);
@@ -458,6 +514,7 @@ void fp_prime_calc(void) {
#ifdef WITH_FPX
if (fp_prime_get_qnr() != 0) {
fp2_field_init();
+ fp4_field_init();
}
if (fp_prime_get_cnr() != 0) {
fp3_field_init();
diff --git a/contrib/relic/src/fp/relic_fp_smb.c b/contrib/relic/src/fp/relic_fp_smb.c
new file mode 100644
index 000000000..ee42147a5
--- /dev/null
+++ b/contrib/relic/src/fp/relic_fp_smb.c
@@ -0,0 +1,326 @@
+/*
+ * RELIC is an Efficient LIbrary for Cryptography
+ * Copyright (c) 2021 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 Legendre and Jacobi symbols for prime fields.
+ *
+ * @ingroup fp
+ */
+
+#include "relic_core.h"
+#include "relic_bn_low.h"
+#include "relic_fp_low.h"
+
+/*============================================================================*/
+/* Public definitions */
+/*============================================================================*/
+
+#if FP_SMB == BASIC || !defined(STRIP)
+
+int fp_smb_basic(const fp_t a) {
+ bn_t t;
+ int r = 0;
+
+ bn_null(t);
+
+ RLC_TRY {
+ bn_new(t);
+
+ /* t = (b - 1)/2. */
+ 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_hlv(t, t);
+
+ fp_exp(t->dp, a, t);
+ r = (fp_cmp_dig(t->dp, 1) == RLC_EQ);
+ fp_neg(t->dp, t->dp);
+ r = RLC_SEL(r, -(fp_cmp_dig(t->dp, 1) == RLC_EQ), !r);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ bn_free(t);
+ }
+ return r;
+}
+
+#endif
+
+#if FP_SMB == DIVST || !defined(STRIP)
+
+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;
+#else
+ int r, 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;
+
+ bn_null(_t);
+ dv_null(f);
+ dv_null(g);
+ dv_null(t);
+
+ RLC_TRY {
+ bn_new(_t);
+ dv_new(f);
+ dv_new(g);
+ dv_new(t);
+
+#if WSIZE == 8
+ bn_set_dig(_t, d >> 8);
+ bn_lsh(_t, _t, 8);
+ bn_add_dig(_t, _t, d & 0xFF);
+#else
+ bn_set_dig(_t, d);
+#endif
+
+ k = 0;
+ fp_prime_back(_t, a);
+ dv_zero(g, RLC_FP_DIGS);
+ dv_copy(g, _t->dp, _t->used);
+ dv_copy(f, fp_prime_get(), RLC_FP_DIGS);
+ fs = gs = RLC_POS;
+
+ for (int i = 0; i < d; i++) {
+ 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;
+ fs ^= s;
+ gs ^= s ^ d0;
+ for (int j = 0; j < RLC_FP_DIGS; j++) {
+ s = (f[j] ^ g[j]) & mask;
+ f[j] ^= s;
+ g[j] ^= s ^ (-d0);
+ }
+ fp_add1_low(g, g, d0);
+
+ k ^= (f[0] >> 1) ^ (f[0] >> 2);
+ k &= 1;
+
+ delta++;
+ g0 = g[0] & 1;
+ for (int j = 0; j < RLC_FP_DIGS; j++) {
+ t[j] = f[j] & (-g0);
+ }
+
+ /* Compute g = (g + g0*f) div 2 by conditionally copying f to u and
+ * updating the sign of g. */
+ gs ^= g0 & (fs ^ bn_addn_low(g, g, t, RLC_FP_DIGS));
+ /* Shift and restore the sign. */
+ fp_rsh1_low(g, g);
+ g[RLC_FP_DIGS - 1] |= (dig_t)gs << (RLC_DIG - 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));
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT)
+ } RLC_FINALLY {
+ bn_free(_t);
+ dv_free(f);
+ dv_free(g);
+ dv_free(t);
+ }
+ return r;
+}
+
+#endif
+
+#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);
+
+ 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(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);
+#if FP_RDC == MONTY
+ /* Convert a from Montgomery form. */
+ fp_copy(t, a);
+ fp_rdcn_low(f, t);
+#else
+ fp_copy(f, a);
+#endif
+
+ 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);
+
+ 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);
+
+ /* Update f and g. */
+ bn_rshs_low(f, t0, RLC_FP_DIGS + 1, s);
+ bn_rshs_low(g, t1, RLC_FP_DIGS + 1, s);
+
+ j = (j + k) % 4;
+ j = (j + ((j & 1) ^ (g[RLC_FP_DIGS] >> (RLC_DIG - 1)))) % 4;
+ }
+
+ r = 0;
+ j = (j + (j & 1)) % 4;
+
+ fp_zero(t0);
+ 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));
+ }
+ 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(t1);
+ dv_free(u0);
+ dv_free(u1);
+ dv_free(v0);
+ dv_free(v1);
+ dv_free(p01);
+ dv_free(p11);
+ }
+
+ return r;
+}
+
+#endif
+
+#if FP_SMB == LOWER || !defined(STRIP)
+
+int fp_smb_lower(const fp_t a) {
+ return fp_smbm_low(a);
+}
+
+#endif
diff --git a/contrib/relic/src/fp/relic_fp_sqr.c b/contrib/relic/src/fp/relic_fp_sqr.c
index b79717a6d..2d2f83be0 100644
--- a/contrib/relic/src/fp/relic_fp_sqr.c
+++ b/contrib/relic/src/fp/relic_fp_sqr.c
@@ -140,7 +140,9 @@ static void fp_sqr_karat_imp(dv_t c, const fp_t a, int size, int level) {
c += h;
carry = bn_addn_low(c, c, t1, 2 * (h1 + 1));
c += 2 * (h1 + 1);
- carry = bn_add1_low(c, c, carry, 2 * size - h - 2 * (h1 + 1));
+ if (2 * size > h + 2 * (h1 + 1)) {
+ carry = bn_add1_low(c, c, carry, 2 * size - h - 2 * (h1 + 1));
+ }
}
RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
diff --git a/contrib/relic/src/fp/relic_fp_util.c b/contrib/relic/src/fp/relic_fp_util.c
index 10ce01401..84d2c50ac 100644
--- a/contrib/relic/src/fp/relic_fp_util.c
+++ b/contrib/relic/src/fp/relic_fp_util.c
@@ -240,14 +240,20 @@ void fp_read_bin(fp_t a, const uint8_t *bin, int len) {
RLC_TRY {
bn_new(t);
bn_read_bin(t, bin, len);
- if (bn_is_zero(t)) {
- fp_zero(a);
+
+ /* Reject values out of bounds. */
+ if (bn_sign(t) == RLC_NEG || bn_cmp(t, &core_get()->prime) != RLC_LT) {
+ RLC_THROW(ERR_NO_VALID);
} else {
- if (t->used == 1) {
- fp_prime_conv_dig(a, t->dp[0]);
+ if (bn_is_zero(t)) {
+ fp_zero(a);
} else {
- fp_prime_conv(a, t);
- }
+ if (t->used == 1) {
+ fp_prime_conv_dig(a, t->dp[0]);
+ } else {
+ fp_prime_conv(a, t);
+ }
+ }
}
}
RLC_CATCH_ANY {
diff --git a/contrib/relic/src/fpx/relic_fp24_sqr.c b/contrib/relic/src/fpx/relic_fp24_sqr.c
index e6e800367..0e45d998c 100644
--- a/contrib/relic/src/fpx/relic_fp24_sqr.c
+++ b/contrib/relic/src/fpx/relic_fp24_sqr.c
@@ -111,6 +111,164 @@ void fp24_sqr_basic(fp24_t c, fp24_t a) {
}
}
+void fp24_sqr_cyc_basic(fp24_t c, fp24_t a) {
+ fp4_t t0, t1, t2, t3, t4, t5, t6;
+
+ fp4_null(t0);
+ fp4_null(t1);
+ fp4_null(t2);
+ fp4_null(t3);
+ fp4_null(t4);
+ fp4_null(t5);
+ fp4_null(t6);
+
+ RLC_TRY {
+ fp4_new(t0);
+ fp4_new(t1);
+ fp4_new(t2);
+ fp4_new(t3);
+ fp4_new(t4);
+ fp4_new(t5);
+ fp4_new(t6);
+
+ fp4_sqr(t2, a[0][0]);
+ fp4_sqr(t3, a[0][1]);
+ fp4_add(t1, a[0][0], a[0][1]);
+
+ fp4_mul_art(t0, t3);
+ fp4_add(t0, t0, t2);
+
+ fp4_sqr(t1, t1);
+ fp4_sub(t1, t1, t2);
+ fp4_sub(t1, t1, t3);
+
+ 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(t0, a[2][0]);
+ fp4_sqr(t1, a[2][1]);
+ fp4_add(t5, a[2][0], a[2][1]);
+ fp4_sqr(t2, t5);
+
+ fp4_add(t3, t0, t1);
+ fp4_sub(t5, t2, t3);
+
+ fp4_add(t6, a[1][0], a[1][1]);
+ fp4_sqr(t3, t6);
+ fp4_sqr(t2, a[1][0]);
+
+ fp4_mul_art(t6, t5);
+ fp4_add(t5, t6, a[1][0]);
+ fp4_dbl(t5, t5);
+ fp4_add(c[1][0], t5, t6);
+
+ fp4_mul_art(t4, t1);
+ fp4_add(t5, t0, t4);
+ fp4_sub(t6, t5, a[1][1]);
+
+ fp4_sqr(t1, a[1][1]);
+
+ fp4_dbl(t6, t6);
+ fp4_add(c[1][1], t6, t5);
+
+ fp4_mul_art(t4, t1);
+ fp4_add(t5, t2, t4);
+ fp4_sub(t6, t5, a[2][0]);
+ fp4_dbl(t6, t6);
+ fp4_add(c[2][0], t6, t5);
+
+ fp4_add(t0, t2, t1);
+ fp4_sub(t5, t3, t0);
+ fp4_add(t6, t5, a[2][1]);
+ fp4_dbl(t6, t6);
+ fp4_add(c[2][1], t5, t6);
+ } 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);
+ }
+}
+
+void fp24_sqr_pck_basic(fp24_t c, fp24_t a) {
+ fp4_t t0, t1, t2, t3, t4, t5, t6;
+
+ fp4_null(t0);
+ fp4_null(t1);
+ fp4_null(t2);
+ fp4_null(t3);
+ fp4_null(t4);
+ fp4_null(t5);
+ fp4_null(t6);
+
+ RLC_TRY {
+ fp4_new(t0);
+ fp4_new(t1);
+ fp4_new(t2);
+ fp4_new(t3);
+ fp4_new(t4);
+ fp4_new(t5);
+ fp4_new(t6);
+
+ fp4_sqr(t0, a[2][0]);
+ fp4_sqr(t1, a[2][1]);
+ fp4_add(t5, a[2][0], a[2][1]);
+ fp4_sqr(t2, t5);
+
+ fp4_add(t3, t0, t1);
+ fp4_sub(t5, t2, t3);
+
+ fp4_add(t6, a[1][0], a[1][1]);
+ fp4_sqr(t3, t6);
+ fp4_sqr(t2, a[1][0]);
+
+ fp4_mul_art(t6, t5);
+ fp4_add(t5, t6, a[1][0]);
+ fp4_dbl(t5, t5);
+ fp4_add(c[1][0], t5, t6);
+
+ fp4_mul_art(t4, t1);
+ fp4_add(t5, t0, t4);
+ fp4_sub(t6, t5, a[1][1]);
+
+ fp4_sqr(t1, a[1][1]);
+
+ fp4_dbl(t6, t6);
+ fp4_add(c[1][1], t6, t5);
+
+ fp4_mul_art(t4, t1);
+ fp4_add(t5, t2, t4);
+ fp4_sub(t6, t5, a[2][0]);
+ fp4_dbl(t6, t6);
+ fp4_add(c[2][0], t6, t5);
+
+ fp4_add(t0, t2, t1);
+ fp4_sub(t5, t3, t0);
+ fp4_add(t6, t5, a[2][1]);
+ fp4_dbl(t6, t6);
+ fp4_add(c[2][1], t5, t6);
+ } 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
@@ -239,4 +397,14 @@ void fp24_sqr_lazyr(fp24_t c, fp24_t a) {
}
}
+void fp24_sqr_cyc_lazyr(fp24_t c, fp24_t a) {
+ /* TODO: implement lazy reduction. */
+ fp24_sqr_cyc_basic(c, a);
+}
+
+void fp24_sqr_pck_lazyr(fp24_t c, fp24_t a) {
+ /* TODO: implement lazy reduction. */
+ fp24_sqr_pck_basic(c, a);
+}
+
#endif
diff --git a/contrib/relic/src/fpx/relic_fp4_mul.c b/contrib/relic/src/fpx/relic_fp4_mul.c
index f44f1ef15..1ab92ea9e 100644
--- a/contrib/relic/src/fpx/relic_fp4_mul.c
+++ b/contrib/relic/src/fpx/relic_fp4_mul.c
@@ -166,3 +166,29 @@ void fp4_mul_art(fp4_t c, fp4_t a) {
fp2_free(t0);
}
}
+
+void fp4_mul_frb(fp4_t c, fp4_t a, int i, int j) {
+ fp2_t t;
+
+ fp2_null(t);
+
+ RLC_TRY {
+ fp2_new(t);
+
+ fp_copy(t[0], core_get()->fp4_p1[0]);
+ fp_copy(t[1], core_get()->fp4_p1[1]);
+ if (i == 1) {
+ for (int k = 0; k < j; k++) {
+ fp2_mul(c[0], a[0], t);
+ fp2_mul(c[1], a[1], t);
+ fp4_mul_art(c, c);
+ }
+ } else {
+ RLC_THROW(ERR_NO_VALID);
+ }
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ } RLC_FINALLY {
+ fp2_free(t);
+ }
+}
diff --git a/contrib/relic/src/fpx/relic_fpx_add.c b/contrib/relic/src/fpx/relic_fpx_add.c
index 5607c9c96..ca1fbf8ce 100644
--- a/contrib/relic/src/fpx/relic_fpx_add.c
+++ b/contrib/relic/src/fpx/relic_fpx_add.c
@@ -89,19 +89,19 @@ void fp2_neg(fp2_t c, fp2_t a) {
#if FPX_CBC == BASIC || !defined(STRIP)
-void fp3_add_basic(fp2_t c, fp2_t a, fp2_t b) {
+void fp3_add_basic(fp3_t c, fp3_t a, fp3_t b) {
fp_add(c[0], a[0], b[0]);
fp_add(c[1], a[1], b[1]);
fp_add(c[2], a[2], b[2]);
}
-void fp3_sub_basic(fp2_t c, fp2_t a, fp2_t b) {
+void fp3_sub_basic(fp3_t c, fp3_t a, fp3_t b) {
fp_sub(c[0], a[0], b[0]);
fp_sub(c[1], a[1], b[1]);
fp_sub(c[2], a[2], b[2]);
}
-void fp3_dbl_basic(fp2_t c, fp2_t a) {
+void fp3_dbl_basic(fp3_t c, fp3_t a) {
/* 2 * (a_0 + a_1 * u) = 2 * a_0 + 2 * a_1 * u. */
fp_dbl(c[0], a[0]);
fp_dbl(c[1], a[1]);
@@ -118,15 +118,15 @@ void fp3_neg(fp3_t c, fp3_t a) {
#if FPX_CBC == INTEG || !defined(STRIP)
-void fp3_add_integ(fp2_t c, fp2_t a, fp2_t b) {
+void fp3_add_integ(fp3_t c, fp3_t a, fp3_t b) {
fp3_addm_low(c, a, b);
}
-void fp3_sub_integ(fp2_t c, fp2_t a, fp2_t b) {
+void fp3_sub_integ(fp3_t c, fp3_t a, fp3_t b) {
fp3_subm_low(c, a, b);
}
-void fp3_dbl_integ(fp2_t c, fp2_t a) {
+void fp3_dbl_integ(fp3_t c, fp3_t a) {
fp3_dblm_low(c, a);
}
diff --git a/contrib/relic/src/fpx/relic_fpx_cyc.c b/contrib/relic/src/fpx/relic_fpx_cyc.c
index 8bbb68f74..5f8e0310f 100644
--- a/contrib/relic/src/fpx/relic_fpx_cyc.c
+++ b/contrib/relic/src/fpx/relic_fpx_cyc.c
@@ -32,138 +32,6 @@
#include "relic_core.h"
-/*============================================================================*/
-/* Private definitions */
-/*============================================================================*/
-
-void fp12_glv(bn_t _b[4], bn_t b) {
- int i, l;
- bn_t n, u[4], v[4];
-
- bn_null(n);
-
- RLC_TRY {
- bn_new(n);
- for (i = 0; i < 4; i++) {
- bn_null(u[i]);
- bn_null(v[i]);
- bn_new(u[i]);
- bn_new(v[i]);
- }
-
- ep_curve_get_ord(n);
-
- switch (ep_curve_is_pairf()) {
- case EP_BN:
- ep2_curve_get_vs(v);
-
- for (i = 0; i < 4; i++) {
- bn_mul(v[i], v[i], b);
- bn_div(v[i], v[i], n);
- if (bn_sign(v[i]) == RLC_NEG) {
- bn_add_dig(v[i], v[i], 1);
- }
- bn_zero(_b[i]);
- }
-
- fp_prime_get_par(u[0]);
- bn_dbl(u[2], u[0]);
- bn_add_dig(u[1], u[2], 1);
- bn_sub_dig(u[3], u[0], 1);
- bn_add_dig(u[0], u[0], 1);
- bn_copy(_b[0], b);
- for (i = 0; i < 4; i++) {
- bn_mul(u[i], u[i], v[i]);
- bn_mod(u[i], u[i], n);
- bn_add(_b[0], _b[0], n);
- bn_sub(_b[0], _b[0], u[i]);
- bn_mod(_b[0], _b[0], n);
- }
-
- fp_prime_get_par(u[0]);
- bn_neg(u[1], u[0]);
- bn_dbl(u[2], u[0]);
- bn_add_dig(u[2], u[2], 1);
- bn_dbl(u[3], u[2]);
- for (i = 0; i < 4; i++) {
- bn_mul(u[i], u[i], v[i]);
- bn_mod(u[i], u[i], n);
- bn_add(_b[1], _b[1], n);
- bn_sub(_b[1], _b[1], u[i]);
- bn_mod(_b[1], _b[1], n);
- }
-
- fp_prime_get_par(u[0]);
- bn_add_dig(u[1], u[0], 1);
- bn_neg(u[1], u[1]);
- bn_dbl(u[2], u[0]);
- bn_add_dig(u[2], u[2], 1);
- bn_sub_dig(u[3], u[2], 2);
- bn_neg(u[3], u[3]);
- for (i = 0; i < 4; i++) {
- bn_mul(u[i], u[i], v[i]);
- bn_mod(u[i], u[i], n);
- bn_add(_b[2], _b[2], n);
- bn_sub(_b[2], _b[2], u[i]);
- bn_mod(_b[2], _b[2], n);
- }
-
- fp_prime_get_par(u[1]);
- bn_dbl(u[0], u[1]);
- bn_neg(u[0], u[0]);
- bn_dbl(u[2], u[1]);
- bn_add_dig(u[2], u[2], 1);
- bn_sub_dig(u[3], u[1], 1);
- bn_neg(u[1], u[1]);
- for (i = 0; i < 4; i++) {
- bn_mul(u[i], u[i], v[i]);
- bn_mod(u[i], u[i], n);
- bn_add(_b[3], _b[3], n);
- bn_sub(_b[3], _b[3], u[i]);
- bn_mod(_b[3], _b[3], n);
- }
-
- for (i = 0; i < 4; i++) {
- l = bn_bits(_b[i]);
- bn_sub(_b[i], n, _b[i]);
- if (bn_bits(_b[i]) > l) {
- bn_sub(_b[i], _b[i], n);
- _b[i]->sign = RLC_POS;
- } else {
- _b[i]->sign = RLC_NEG;
- }
- }
- break;
- case EP_B12:
- bn_abs(v[0], b);
- fp_prime_get_par(u[0]);
-
- bn_copy(u[1], u[0]);
- bn_abs(u[0], u[0]);
-
- for (i = 0; i < 4; i++) {
- bn_mod(_b[i], v[0], u[0]);
- bn_div(v[0], v[0], u[0]);
- if ((bn_sign(u[1]) == RLC_NEG) && (i % 2 != 0)) {
- bn_neg(_b[i], _b[i]);
- }
- if (bn_sign(b) == RLC_NEG) {
- bn_neg(_b[i], _b[i]);
- }
- }
- break;
- }
- } RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- } RLC_FINALLY {
- bn_free(n);
- for (i = 0; i < 4; i++) {
- bn_free(u[i]);
- bn_free(v[i]);
- }
- }
-}
-
/*============================================================================*/
/* Public definitions */
/*============================================================================*/
@@ -216,11 +84,10 @@ int fp2_test_cyc(fp2_t a) {
void fp2_exp_cyc(fp2_t c, fp2_t a, bn_t b) {
fp2_t r, s, t[1 << (FP_WIDTH - 2)];
int i, l;
- signed char naf[RLC_FP_BITS + 1], *k;
+ int8_t naf[RLC_FP_BITS + 1], *k;
if (bn_is_zero(b)) {
- fp2_set_dig(c, 1);
- return;
+ return fp2_set_dig(c, 1);
}
fp2_null(r);
@@ -327,11 +194,10 @@ int fp8_test_cyc(fp8_t a) {
void fp8_exp_cyc(fp8_t c, fp8_t a, bn_t b) {
fp8_t r, s, t[1 << (FP_WIDTH - 2)];
int i, l;
- signed char naf[RLC_FP_BITS + 1], *k;
+ int8_t naf[RLC_FP_BITS + 1], *k;
if (bn_is_zero(b)) {
- fp8_set_dig(c, 1);
- return;
+ return fp8_set_dig(c, 1);
}
fp8_null(r);
@@ -516,6 +382,7 @@ void fp12_back_cyc_sim(fp12_t c[], fp12_t a[], int n) {
*t2 = t + 2 * n;
if (n == 0) {
+ RLC_FREE(t);
return;
}
@@ -588,17 +455,23 @@ void fp12_back_cyc_sim(fp12_t c[], fp12_t a[], int n) {
void fp12_exp_cyc(fp12_t c, fp12_t a, bn_t b) {
int i, j, k, l, w = bn_ham(b);
- bn_t _b[4];
if (bn_is_zero(b)) {
- fp12_set_dig(c, 1);
- return;
+ return fp12_set_dig(c, 1);
}
if ((bn_bits(b) > RLC_DIG) && ((w << 3) > bn_bits(b))) {
+ int _l[4];
+ int8_t naf[4][RLC_FP_BITS + 1];
fp12_t t[4];
+ bn_t _b[4], n, u;
+
+ bn_null(n);
+ bn_null(u);
RLC_TRY {
+ bn_new(n);
+ bn_new(u);
for (i = 0; i < 4; i++) {
bn_null(_b[i]);
bn_new(_b[i]);
@@ -606,24 +479,38 @@ void fp12_exp_cyc(fp12_t c, fp12_t a, bn_t b) {
fp12_new(t[i]);
}
- fp12_glv(_b, b);
+ ep_curve_get_ord(n);
+ fp_prime_get_par(u);
+ bn_rec_frb(_b, 4, b, u, n, ep_curve_is_pairf() == EP_B12 ||
+ ep_curve_is_pairf() == EP_B24 || ep_curve_is_pairf() == EP_B48);
if (ep_curve_is_pairf()) {
+ fp12_copy(t[0], a);
+ fp12_frb(t[1], t[0], 1);
+ fp12_frb(t[2], t[1], 1);
+ fp12_frb(t[3], t[2], 1);
+
+ l = 0;
for (i = 0; i < 4; i++) {
- fp12_frb(t[i], a, i);
if (bn_sign(_b[i]) == RLC_NEG) {
fp12_inv_cyc(t[i], t[i]);
}
+ _l[i] = RLC_FP_BITS + 1;
+ bn_rec_naf(naf[i], &_l[i], _b[i], 2);
+ l = RLC_MAX(l, _l[i]);
}
- l = RLC_MAX(bn_bits(_b[0]), bn_bits(_b[1]));
- l = RLC_MAX(l, RLC_MAX(bn_bits(_b[2]), bn_bits(_b[3])));
fp12_set_dig(c, 1);
for (i = l - 1; i >= 0; i--) {
fp12_sqr_cyc(c, c);
for (j = 0; j < 4; j++) {
- if (bn_get_bit(_b[j], i)) {
+ if (naf[j][i] > 0) {
+ fp12_mul(c, c, t[j]);
+ }
+ if (naf[j][i] < 0) {
+ fp12_inv_cyc(t[j], t[j]);
fp12_mul(c, c, t[j]);
+ fp12_inv_cyc(t[j], t[j]);
}
}
}
@@ -647,6 +534,8 @@ void fp12_exp_cyc(fp12_t c, fp12_t a, bn_t b) {
RLC_THROW(ERR_CAUGHT);
}
RLC_FINALLY {
+ bn_free(n);
+ bn_free(u);
for (i = 0; i < 4; i++) {
bn_free(_b[i]);
fp12_free(t[i]);
@@ -761,13 +650,6 @@ void fp2_exp_cyc_sim(fp2_t e, fp2_t a, bn_t b, fp2_t c, bn_t d) {
bn_rec_naf(naf1, &l1, d, FP_WIDTH);
l = RLC_MAX(l0, l1);
- for (i = l0; i < l; i++) {
- naf0[i] = 0;
- }
- for (i = l1; i < l; i++) {
- naf1[i] = 0;
- }
-
if (bn_sign(b) == RLC_NEG) {
for (i = 0; i < l0; i++) {
naf0[i] = -naf0[i];
@@ -823,20 +705,23 @@ void fp2_exp_cyc_sim(fp2_t e, fp2_t a, bn_t b, fp2_t c, bn_t d) {
void fp12_exp_cyc_sim(fp12_t e, fp12_t a, bn_t b, fp12_t c, bn_t d) {
int i, j, l;
- bn_t _b[4], _d[4];
+ bn_t _b[4], _d[4], n, x;
fp12_t t[4], u[4];
if (bn_is_zero(b)) {
return fp12_exp_cyc(e, c, d);
- return;
}
if (bn_is_zero(d)) {
return fp12_exp_cyc(e, a, b);
- return;
}
+ bn_null(n);
+ bn_null(x);
+
RLC_TRY {
+ bn_new(n);
+ bn_new(x);
for (i = 0; i < 4; i++) {
bn_null(_b[i]);
bn_null(_d[i]);
@@ -848,8 +733,10 @@ void fp12_exp_cyc_sim(fp12_t e, fp12_t a, bn_t b, fp12_t c, bn_t d) {
fp12_new(u[i]);
}
- fp12_glv(_b, b);
- fp12_glv(_d, d);
+ ep_curve_get_ord(n);
+ fp_prime_get_par(x);
+ bn_rec_frb(_b, 4, b, x, n, ep_curve_is_pairf() == EP_B12);
+ bn_rec_frb(_d, 4, d, x, n, ep_curve_is_pairf() == EP_B12);
if (ep_curve_is_pairf()) {
for (i = 0; i < 4; i++) {
@@ -907,6 +794,8 @@ void fp12_exp_cyc_sim(fp12_t e, fp12_t a, bn_t b, fp12_t c, bn_t d) {
} RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
} RLC_FINALLY {
+ bn_free(n);
+ bn_free(x);
for (i = 0; i < 4; i++) {
bn_free(_b[i]);
bn_free(_d[i]);
@@ -916,12 +805,12 @@ void fp12_exp_cyc_sim(fp12_t e, fp12_t a, bn_t b, fp12_t c, bn_t d) {
}
}
-
void fp12_exp_cyc_sps(fp12_t c, fp12_t a, const int *b, int len, int sign) {
int i, j, k, w = len;
fp12_t t, *u = RLC_ALLOCA(fp12_t, w);
if (len == 0) {
+ RLC_FREE(u);
fp12_set_dig(c, 1);
return;
}
@@ -995,6 +884,534 @@ void fp12_exp_cyc_sps(fp12_t c, fp12_t a, const int *b, int len, int sign) {
}
}
+void fp24_conv_cyc(fp24_t c, fp24_t a) {
+ fp24_t t;
+
+ fp24_null(t);
+
+ RLC_TRY {
+ fp24_new(t);
+
+ /* First, compute c = a^(p^12 - 1). */
+ /* t = a^{-1}. */
+ fp24_inv(t, a);
+ /* c = a^(p^12). */
+ fp24_inv_cyc(c, a);
+ /* c = a^(p^12 - 1). */
+ fp24_mul(c, c, t);
+
+ /* Second, compute c^(p^4 + 1). */
+ /* t = c^(p^4). */
+ fp24_frb(t, c, 4);
+
+ /* c = c^(p^4 + 1). */
+ fp24_mul(c, c, t);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ fp24_free(t);
+ }
+}
+
+int fp24_test_cyc(fp24_t a) {
+ fp24_t t0, t1;
+ int result = 0;
+
+ fp24_null(t0);
+ fp24_null(t1);
+
+ RLC_TRY {
+ fp24_new(t0);
+ fp24_new(t1);
+
+ /* Check if a^(p^8 - p^4 + 1) == 1. */
+ fp24_frb(t0, a, 8);
+ fp24_mul(t0, t0, a);
+ fp24_frb(t1, a, 4);
+
+ result = ((fp24_cmp(t0, t1) == RLC_EQ) ? 1 : 0);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ fp24_free(t0);
+ fp24_free(t1);
+ }
+
+ return result;
+}
+
+void fp24_back_cyc(fp24_t c, fp24_t a) {
+ fp4_t t0, t1, t2;
+
+ fp4_null(t0);
+ fp4_null(t1);
+ fp4_null(t2);
+
+ RLC_TRY {
+ fp4_new(t0);
+ fp4_new(t1);
+ fp4_new(t2);
+
+ /* t0 = 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);
+ fp4_inv(t1, t1);
+ /* c_1 = g1. */
+ fp4_mul(c[0][1], t0, t1);
+
+ /* t1 = g3 * g4. */
+ fp4_mul(t1, a[1][1], a[2][0]);
+ /* t2 = 2 * g1^2 - 3 * g3 * g4. */
+ fp4_sqr(t2, c[0][1]);
+ fp4_sub(t2, t2, t1);
+ fp4_dbl(t2, t2);
+ fp4_sub(t2, t2, t1);
+ /* t1 = g2 * g5. */
+ fp4_mul(t1, a[1][0], a[2][1]);
+ /* c_0 = E * (2 * g1^2 + g2 * g5 - 3 * g3 * g4) + 1. */
+ fp4_add(t2, t2, t1);
+ fp4_mul_art(c[0][0], t2);
+ fp_add_dig(c[0][0][0][0], c[0][0][0][0], 1);
+
+ fp4_copy(c[1][0], a[1][0]);
+ fp4_copy(c[1][1], a[1][1]);
+ fp4_copy(c[2][0], a[2][0]);
+ fp4_copy(c[2][1], a[2][1]);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ fp4_free(t0);
+ fp4_free(t1);
+ fp4_free(t2);
+ }
+}
+
+void fp24_back_cyc_sim(fp24_t c[], fp24_t a[], int n) {
+ fp4_t *t = RLC_ALLOCA(fp4_t, n * 3);
+ fp4_t
+ *t0 = t + 0 * n,
+ *t1 = t + 1 * n,
+ *t2 = t + 2 * n;
+
+ if (n == 0) {
+ RLC_FREE(t);
+ return;
+ }
+
+ RLC_TRY {
+ if (t == NULL) {
+ RLC_THROW(ERR_NO_MEMORY);
+ }
+ for (int i = 0; i < n; i++) {
+ fp4_null(t0[i]);
+ fp4_null(t1[i]);
+ fp4_null(t2[i]);
+ fp4_new(t0[i]);
+ fp4_new(t1[i]);
+ fp4_new(t2[i]);
+ }
+
+ for (int i = 0; i < n; i++) {
+ /* 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]);
+ }
+
+ /* t1 = 1 / t1. */
+ fp4_inv_sim(t1, t1, n);
+
+ for (int i = 0; i < n; i++) {
+ /* t0 = g1. */
+ fp4_mul(c[i][0][1], t0[i], t1[i]);
+
+ /* t1 = g3 * g4. */
+ fp4_mul(t1[i], a[i][1][1], a[i][2][0]);
+ /* t2 = 2 * g1^2 - 3 * g3 * g4. */
+ fp4_sqr(t2[i], c[i][0][1]);
+ fp4_sub(t2[i], t2[i], t1[i]);
+ fp4_dbl(t2[i], t2[i]);
+ fp4_sub(t2[i], t2[i], t1[i]);
+ /* t1 = g2 * g5. */
+ fp4_mul(t1[i], a[i][1][0], a[i][2][1]);
+ /* t2 = E * (2 * g1^2 + g2 * g5 - 3 * g3 * g4) + 1. */
+ fp4_add(t2[i], t2[i], t1[i]);
+ fp4_mul_art(c[i][0][0], t2[i]);
+ fp_add_dig(c[i][0][0][0][0], c[i][0][0][0][0], 1);
+
+ fp4_copy(c[i][1][0], a[i][1][0]);
+ fp4_copy(c[i][1][1], a[i][1][1]);
+ fp4_copy(c[i][2][0], a[i][2][0]);
+ fp4_copy(c[i][2][1], a[i][2][1]);
+ }
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ } RLC_FINALLY {
+ for (int i = 0; i < n; i++) {
+ fp4_free(t0[i]);
+ fp4_free(t1[i]);
+ fp4_free(t2[i]);
+ }
+ RLC_FREE(t);
+ }
+}
+
+void fp24_exp_cyc(fp24_t c, fp24_t a, bn_t b) {
+ int i, j, k, w = bn_ham(b);
+
+ if (bn_is_zero(b)) {
+ fp24_set_dig(c, 1);
+ return;
+ }
+
+ if ((bn_bits(b) > RLC_DIG) && ((w << 3) > bn_bits(b))) {
+ int l, _l[8];
+ int8_t naf[8][RLC_FP_BITS + 1];
+ fp24_t t[8];
+ bn_t _b[8], n, x;
+
+ bn_null(n);
+ bn_null(x);
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(x);
+ for (i = 0; i < 8; i++) {
+ bn_null(_b[i]);
+ bn_new(_b[i]);
+ fp24_null(t[i]);
+ fp24_new(t[i]);
+ }
+
+ ep_curve_get_ord(n);
+ fp_prime_get_par(x);
+ bn_rec_frb(_b, 8, b, x, n, ep_curve_is_pairf());
+
+ if (ep_curve_is_pairf()) {
+ l = 0;
+
+ fp24_copy(t[0], a);
+ for (i = 0; i < 8; 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) {
+ fp24_frb(t[i], t[i - 1], 1);
+ }
+ }
+
+ for (i = 0; i < 8; i++) {
+ if (bn_sign(_b[i]) == RLC_NEG) {
+ fp24_inv_cyc(t[i], t[i]);
+ }
+ }
+
+ fp24_set_dig(c, 1);
+ for (i = l - 1; i >= 0; i--) {
+ fp24_sqr_cyc(c, c);
+ for (j = 0; j < 8; j++) {
+ if (naf[j][i] > 0) {
+ fp24_mul(c, c, t[j]);
+ }
+ if (naf[j][i] < 0) {
+ fp24_inv_cyc(t[j], t[j]);
+ fp24_mul(c, c, t[j]);
+ fp24_inv_cyc(t[j], t[j]);
+ }
+ }
+ }
+ } else {
+ fp24_copy(t[0], a);
+
+ for (i = bn_bits(b) - 2; i >= 0; i--) {
+ fp24_sqr_cyc(t[0], t[0]);
+ if (bn_get_bit(b, i)) {
+ fp24_mul(t[0], t[0], a);
+ }
+ }
+
+ fp24_copy(c, t[0]);
+ if (bn_sign(b) == RLC_NEG) {
+ fp24_inv_cyc(c, c);
+ }
+ }
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ bn_free(n);
+ bn_free(x);
+ for (i = 0; i < 8; i++) {
+ bn_free(_b[i]);
+ fp24_free(t[i]);
+ }
+ }
+ } else {
+ fp24_t t, *u = RLC_ALLOCA(fp24_t, w);
+
+ fp24_null(t);
+
+ RLC_TRY {
+ if (u == NULL) {
+ RLC_THROW(ERR_NO_MEMORY);
+ }
+ for (i = 0; i < w; i++) {
+ fp24_null(u[i]);
+ fp24_new(u[i]);
+ }
+ fp24_new(t);
+
+ j = 0;
+ fp24_copy(t, a);
+ for (i = 1; i < bn_bits(b); i++) {
+ fp24_sqr_pck(t, t);
+ if (bn_get_bit(b, i)) {
+ fp24_copy(u[j++], t);
+ }
+ }
+
+ if (!bn_is_even(b)) {
+ j = 0;
+ k = w - 1;
+ } else {
+ j = 1;
+ k = w;
+ }
+
+ fp24_back_cyc_sim(u, u, k);
+
+ if (!bn_is_even(b)) {
+ fp24_copy(c, a);
+ } else {
+ fp24_copy(c, u[0]);
+ }
+
+ for (i = j; i < k; i++) {
+ fp24_mul(c, c, u[i]);
+ }
+
+ if (bn_sign(b) == RLC_NEG) {
+ fp24_inv_cyc(c, c);
+ }
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ for (i = 0; i < w; i++) {
+ fp24_free(u[i]);
+ }
+ fp24_free(t);
+ RLC_FREE(u);
+ }
+ }
+}
+
+void fp24_exp_cyc_sim(fp24_t e, fp24_t a, bn_t b, fp24_t c, bn_t d) {
+ int i, l, n0, n1, l0, l1;
+ int8_t naf0[RLC_FP_BITS + 1], naf1[RLC_FP_BITS + 1], *_k, *_m;
+ fp24_t r, t0[1 << (EP_WIDTH - 2)];
+ fp24_t s, t1[1 << (EP_WIDTH - 2)];
+
+ if (bn_is_zero(b)) {
+ return fp24_exp_cyc(e, c, d);
+ }
+
+ if (bn_is_zero(d)) {
+ return fp24_exp_cyc(e, a, b);
+ }
+
+ fp24_null(r);
+ fp24_null(s);
+
+ RLC_TRY {
+ fp24_new(r);
+ fp24_new(s);
+ for (i = 0; i < (1 << (FP_WIDTH - 2)); i ++) {
+ fp24_null(t0[i]);
+ fp24_null(t1[i]);
+ fp24_new(t0[i]);
+ fp24_new(t1[i]);
+ }
+
+#if FP_WIDTH > 2
+ fp24_sqr(t0[0], a);
+ fp24_mul(t0[1], t0[0], a);
+ for (int i = 2; i < (1 << (FP_WIDTH - 2)); i++) {
+ fp24_mul(t0[i], t0[i - 1], t0[0]);
+ }
+
+ fp24_sqr(t1[0], c);
+ fp24_mul(t1[1], t1[0], c);
+ for (int i = 2; i < (1 << (FP_WIDTH - 2)); i++) {
+ fp24_mul(t1[i], t1[i - 1], t1[0]);
+ }
+#endif
+ fp24_copy(t0[0], a);
+ fp24_copy(t1[0], c);
+
+ l0 = l1 = RLC_FP_BITS + 1;
+ bn_rec_naf(naf0, &l0, b, FP_WIDTH);
+ bn_rec_naf(naf1, &l1, d, FP_WIDTH);
+
+ l = RLC_MAX(l0, l1);
+ if (bn_sign(b) == RLC_NEG) {
+ for (i = 0; i < l0; i++) {
+ naf0[i] = -naf0[i];
+ }
+ }
+ if (bn_sign(d) == RLC_NEG) {
+ for (i = 0; i < l1; i++) {
+ naf1[i] = -naf1[i];
+ }
+ }
+
+ _k = naf0 + l - 1;
+ _m = naf1 + l - 1;
+
+ fp24_set_dig(r, 1);
+ for (i = l - 1; i >= 0; i--, _k--, _m--) {
+ fp24_sqr(r, r);
+
+ n0 = *_k;
+ n1 = *_m;
+
+ if (n0 > 0) {
+ fp24_mul(r, r, t0[n0 / 2]);
+ }
+ if (n0 < 0) {
+ fp24_inv_cyc(s, t0[-n0 / 2]);
+ fp24_mul(r, r, s);
+ }
+ if (n1 > 0) {
+ fp24_mul(r, r, t1[n1 / 2]);
+ }
+ if (n1 < 0) {
+ fp24_inv_cyc(s, t1[-n1 / 2]);
+ fp24_mul(r, r, s);
+ }
+ }
+
+ fp24_copy(e, r);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ fp24_free(r);
+ fp24_free(s);
+ for (i = 0; i < (1 << (FP_WIDTH - 2)); i++) {
+ fp24_free(t0[i]);
+ fp24_free(t1[i]);
+ }
+ }
+}
+
+void fp24_exp_cyc_sps(fp24_t c, fp24_t a, const int *b, int len, int sign) {
+ int i, j, k, w = len;
+ fp24_t t, *u = RLC_ALLOCA(fp24_t, w);
+
+ if (len == 0) {
+ RLC_FREE(u);
+ fp24_set_dig(c, 1);
+ return;
+ }
+
+ fp24_null(t);
+
+ RLC_TRY {
+ if (u == NULL) {
+ RLC_THROW(ERR_NO_MEMORY);
+ }
+ for (i = 0; i < w; i++) {
+ fp24_null(u[i]);
+ fp24_new(u[i]);
+ }
+ fp24_new(t);
+
+ fp24_copy(t, a);
+ if (b[0] == 0) {
+ for (j = 0, i = 1; i < len; i++) {
+ k = (b[i] < 0 ? -b[i] : b[i]);
+ for (; j < k; j++) {
+ fp24_sqr_pck(t, t);
+ }
+ if (b[i] < 0) {
+ fp24_inv_cyc(u[i - 1], t);
+ } else {
+ fp24_copy(u[i - 1], t);
+ }
+ }
+
+ fp24_back_cyc_sim(u, u, w - 1);
+
+ fp24_copy(c, a);
+ for (i = 0; i < w - 1; i++) {
+ fp24_mul(c, c, u[i]);
+ }
+ } else {
+ for (j = 0, i = 0; i < len; i++) {
+ k = (b[i] < 0 ? -b[i] : b[i]);
+ for (; j < k; j++) {
+ fp24_sqr_pck(t, t);
+ }
+ if (b[i] < 0) {
+ fp24_inv_cyc(u[i], t);
+ } else {
+ fp24_copy(u[i], t);
+ }
+ }
+
+ fp24_back_cyc_sim(u, u, w);
+
+ fp24_copy(c, u[0]);
+ for (i = 1; i < w; i++) {
+ fp24_mul(c, c, u[i]);
+ }
+ }
+
+ if (sign == RLC_NEG) {
+ fp24_inv_cyc(c, c);
+ }
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ for (i = 0; i < w; i++) {
+ fp24_free(u[i]);
+ }
+ fp24_free(t);
+ RLC_FREE(u);
+ }
+}
+
void fp48_conv_cyc(fp48_t c, fp48_t a) {
fp48_t t;
@@ -1121,6 +1538,7 @@ void fp48_back_cyc_sim(fp48_t c[], fp48_t a[], int n) {
*t2 = t + 2 * n;
if (n == 0) {
+ RLC_FREE(t);
return;
}
@@ -1195,8 +1613,7 @@ void fp48_exp_cyc(fp48_t c, fp48_t a, bn_t b) {
int i, j, k, w = bn_ham(b);
if (bn_is_zero(b)) {
- fp48_set_dig(c, 1);
- return;
+ return fp48_set_dig(c, 1);
}
if ((bn_bits(b) > RLC_DIG) && ((w << 3) > bn_bits(b))) {
@@ -1292,6 +1709,7 @@ void fp48_exp_cyc_sps(fp48_t c, fp48_t a, const int *b, int len, int sign) {
fp48_t t, *u = RLC_ALLOCA(fp48_t, w);
if (len == 0) {
+ RLC_FREE(u);
fp48_set_dig(c, 1);
return;
}
@@ -1490,6 +1908,7 @@ void fp54_back_cyc_sim(fp54_t c[], fp54_t a[], int n) {
*t2 = t + 2 * n;
if (n == 0) {
+ RLC_FREE(t);
return;
}
@@ -1564,8 +1983,7 @@ void fp54_exp_cyc(fp54_t c, fp54_t a, bn_t b) {
int i, j, k, w = bn_ham(b);
if (bn_is_zero(b)) {
- fp54_set_dig(c, 1);
- return;
+ return fp54_set_dig(c, 1);
}
if ((bn_bits(b) > RLC_DIG) && ((w << 3) > bn_bits(b))) {
@@ -1662,6 +2080,7 @@ void fp54_exp_cyc_sps(fp54_t c, fp54_t a, const int *b, int len, int sign) {
fp54_t t, *u = RLC_ALLOCA(fp54_t, w);
if (len == 0) {
+ RLC_FREE(u);
fp54_set_dig(c, 1);
return;
}
diff --git a/contrib/relic/src/fpx/relic_fpx_exp.c b/contrib/relic/src/fpx/relic_fpx_exp.c
index b6341feaf..e559e7ffe 100644
--- a/contrib/relic/src/fpx/relic_fpx_exp.c
+++ b/contrib/relic/src/fpx/relic_fpx_exp.c
@@ -326,25 +326,42 @@ void fp12_exp(fp12_t c, fp12_t a, bn_t b) {
}
void fp12_exp_dig(fp12_t c, fp12_t a, dig_t b) {
- fp12_t t;
+ bn_t _b;
+ fp12_t t, v;
+ int8_t u, naf[RLC_DIG + 1];
+ int l;
if (b == 0) {
fp12_set_dig(c, 1);
return;
}
+ bn_null(_b);
fp12_null(t);
+ fp12_null(v);
RLC_TRY {
+ bn_new(_b);
fp12_new(t);
+ fp12_new(v);
fp12_copy(t, a);
if (fp12_test_cyc(a)) {
- for (int i = util_bits_dig(b) - 2; i >= 0; i--) {
+ fp12_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--) {
fp12_sqr_cyc(t, t);
- if (b & ((dig_t)1 << i)) {
+
+ u = naf[i];
+ if (u > 0) {
fp12_mul(t, t, a);
+ } else if (u < 0) {
+ fp12_mul(t, t, v);
}
}
} else {
@@ -362,7 +379,9 @@ void fp12_exp_dig(fp12_t c, fp12_t a, dig_t b) {
RLC_THROW(ERR_CAUGHT);
}
RLC_FINALLY {
+ bn_free(_b);
fp12_free(t);
+ fp12_free(v);
}
}
@@ -438,6 +457,66 @@ void fp24_exp(fp24_t c, fp24_t a, bn_t b) {
}
}
+void fp24_exp_dig(fp24_t c, fp24_t a, dig_t b) {
+ bn_t _b;
+ fp24_t t, v;
+ int8_t u, naf[RLC_DIG + 1];
+ int l;
+
+ if (b == 0) {
+ fp24_set_dig(c, 1);
+ return;
+ }
+
+ bn_null(_b);
+ fp24_null(t);
+ fp24_null(v);
+
+ RLC_TRY {
+ bn_new(_b);
+ fp24_new(t);
+ fp24_new(v);
+
+ fp24_copy(t, a);
+
+ if (fp24_test_cyc(a)) {
+ fp24_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--) {
+ fp24_sqr_cyc(t, t);
+
+ u = naf[i];
+ if (u > 0) {
+ fp24_mul(t, t, a);
+ } else if (u < 0) {
+ fp24_mul(t, t, v);
+ }
+ }
+ } else {
+ for (int i = util_bits_dig(b) - 2; i >= 0; i--) {
+ fp24_sqr(t, t);
+ if (b & ((dig_t)1 << i)) {
+ fp24_mul(t, t, a);
+ }
+ }
+ }
+
+ fp24_copy(c, t);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ bn_free(_b);
+ fp24_free(t);
+ fp24_free(v);
+ }
+}
+
void fp48_exp(fp48_t c, fp48_t a, bn_t b) {
fp48_t t;
@@ -479,25 +558,42 @@ void fp48_exp(fp48_t c, fp48_t a, bn_t b) {
}
void fp48_exp_dig(fp48_t c, fp48_t a, dig_t b) {
- fp48_t t;
+ bn_t _b;
+ fp48_t t, v;
+ int8_t u, naf[RLC_DIG + 1];
+ int l;
if (b == 0) {
fp48_set_dig(c, 1);
return;
}
+ bn_null(_b);
fp48_null(t);
+ fp48_null(v);
RLC_TRY {
+ bn_new(_b);
fp48_new(t);
+ fp48_new(v);
fp48_copy(t, a);
if (fp48_test_cyc(a)) {
- for (int i = util_bits_dig(b) - 2; i >= 0; i--) {
+ fp48_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--) {
fp48_sqr_cyc(t, t);
- if (b & ((dig_t)1 << i)) {
+
+ u = naf[i];
+ if (u > 0) {
fp48_mul(t, t, a);
+ } else if (u < 0) {
+ fp48_mul(t, t, v);
}
}
} else {
@@ -515,7 +611,9 @@ void fp48_exp_dig(fp48_t c, fp48_t a, dig_t b) {
RLC_THROW(ERR_CAUGHT);
}
RLC_FINALLY {
+ bn_free(_b);
fp48_free(t);
+ fp48_free(v);
}
}
@@ -556,25 +654,42 @@ void fp54_exp(fp54_t c, fp54_t a, bn_t b) {
}
void fp54_exp_dig(fp54_t c, fp54_t a, dig_t b) {
- fp54_t t;
+ bn_t _b;
+ fp54_t t, v;
+ int8_t u, naf[RLC_DIG + 1];
+ int l;
if (b == 0) {
fp54_set_dig(c, 1);
return;
}
+ bn_null(_b);
fp54_null(t);
+ fp54_null(v);
RLC_TRY {
+ bn_new(_b);
fp54_new(t);
+ fp54_new(v);
fp54_copy(t, a);
if (fp54_test_cyc(a)) {
- for (int i = util_bits_dig(b) - 2; i >= 0; i--) {
+ fp54_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--) {
fp54_sqr_cyc(t, t);
- if (b & ((dig_t)1 << i)) {
+
+ u = naf[i];
+ if (u > 0) {
fp54_mul(t, t, a);
+ } else if (u < 0) {
+ fp54_mul(t, t, v);
}
}
} else {
@@ -592,6 +707,8 @@ void fp54_exp_dig(fp54_t c, fp54_t a, dig_t b) {
RLC_THROW(ERR_CAUGHT);
}
RLC_FINALLY {
+ bn_free(_b);
fp54_free(t);
+ fp54_free(v);
}
}
diff --git a/contrib/relic/src/fpx/relic_fpx_field.c b/contrib/relic/src/fpx/relic_fpx_field.c
index 7799fe4c9..92d9557e3 100644
--- a/contrib/relic/src/fpx/relic_fpx_field.c
+++ b/contrib/relic/src/fpx/relic_fpx_field.c
@@ -222,3 +222,32 @@ void fp3_field_init(void) {
fp3_free(t2);
}
}
+
+void fp4_field_init() {
+ bn_t e;
+ fp4_t t0;
+ ctx_t *ctx = core_get();
+
+ bn_null(e);
+ fp4_null(t0);
+
+ RLC_TRY {
+ bn_new(e);
+ fp4_new(t0);
+
+ fp4_set_dig(t0, 1);
+ fp4_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);
+ fp4_exp(t0, t0, e);
+ fp_copy(ctx->fp4_p1[0], t0[1][0]);
+ fp_copy(ctx->fp4_p1[1], t0[1][1]);
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ } RLC_FINALLY {
+ bn_free(e);
+ fp4_free(t0);
+ }
+}
diff --git a/contrib/relic/src/fpx/relic_fpx_inv.c b/contrib/relic/src/fpx/relic_fpx_inv.c
index e4fa3355b..b279f879c 100644
--- a/contrib/relic/src/fpx/relic_fpx_inv.c
+++ b/contrib/relic/src/fpx/relic_fpx_inv.c
@@ -296,6 +296,49 @@ void fp4_inv(fp4_t c, fp4_t a) {
}
}
+void fp4_inv_sim(fp4_t * c, fp4_t * a, int n) {
+ int i;
+ fp4_t u, *t = RLC_ALLOCA(fp4_t, n);
+
+ for (i = 0; i < n; i++) {
+ fp4_null(t[i]);
+ }
+ fp4_null(u);
+
+ RLC_TRY {
+ for (i = 0; i < n; i++) {
+ fp4_new(t[i]);
+ }
+ fp4_new(u);
+
+ fp4_copy(c[0], a[0]);
+ fp4_copy(t[0], a[0]);
+
+ for (i = 1; i < n; i++) {
+ fp4_copy(t[i], a[i]);
+ fp4_mul(c[i], c[i - 1], t[i]);
+ }
+
+ fp4_inv(u, c[n - 1]);
+
+ for (i = n - 1; i > 0; i--) {
+ fp4_mul(c[i], c[i - 1], u);
+ fp4_mul(u, u, t[i]);
+ }
+ fp4_copy(c[0], u);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ for (i = 0; i < n; i++) {
+ fp4_free(t[i]);
+ }
+ fp4_free(u);
+ RLC_FREE(t);
+ }
+}
+
void fp6_inv(fp6_t c, fp6_t a) {
fp2_t v0;
fp2_t v1;
@@ -658,6 +701,13 @@ void fp24_inv(fp24_t c, fp24_t a) {
}
}
+void fp24_inv_cyc(fp24_t c, fp24_t a) {
+ fp8_inv_cyc(c[0], a[0]);
+ fp8_inv_cyc(c[1], a[1]);
+ fp8_neg(c[1], c[1]);
+ fp8_inv_cyc(c[2], a[2]);
+}
+
void fp48_inv(fp48_t c, fp48_t a) {
fp24_t t0;
fp24_t t1;
diff --git a/contrib/relic/src/fpx/relic_fpx_pck.c b/contrib/relic/src/fpx/relic_fpx_pck.c
index ce09f829f..1f9b6b9f9 100644
--- a/contrib/relic/src/fpx/relic_fpx_pck.c
+++ b/contrib/relic/src/fpx/relic_fpx_pck.c
@@ -155,6 +155,28 @@ int fp12_upk_max(fp12_t c, fp12_t a) {
}
}
+void fp24_pck(fp24_t c, fp24_t a) {
+ fp24_copy(c, a);
+ if (fp24_test_cyc(c)) {
+ fp4_zero(c[0][0]);
+ fp4_zero(c[0][1]);
+ }
+}
+
+int fp24_upk(fp24_t c, 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 {
+ fp24_copy(c, a);
+ return 1;
+ }
+}
+
void fp48_pck(fp48_t c, fp48_t a) {
fp48_copy(c, a);
if (fp48_test_cyc(c)) {
diff --git a/contrib/relic/src/fpx/relic_fpx_srt.c b/contrib/relic/src/fpx/relic_fpx_srt.c
index 3e7fdb530..2da52b750 100644
--- a/contrib/relic/src/fpx/relic_fpx_srt.c
+++ b/contrib/relic/src/fpx/relic_fpx_srt.c
@@ -38,72 +38,80 @@
int fp2_srt(fp2_t c, fp2_t a) {
int r = 0;
+ fp_t t0;
fp_t t1;
fp_t t2;
- fp_t t3;
+ fp_null(t0);
fp_null(t1);
fp_null(t2);
- fp_null(t3);
+
+ if (fp2_is_zero(a)) {
+ fp2_zero(c);
+ return 1;
+ }
RLC_TRY {
+ fp_new(t0);
fp_new(t1);
fp_new(t2);
- fp_new(t3);
if (fp_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 (fp_srt(t1, a[0])) {
- fp_copy(c[0], t1);
+ if (fp_srt(t0, a[0])) {
+ fp_copy(c[0], t0);
fp_zero(c[1]);
} else {
- /* Compute a[0]/u^2. */
+ /* Compute a[0]/i^2. */
#ifdef FP_QNRES
- fp_copy(t1, a[0]);
+ fp_copy(t0, a[0]);
#else
if (fp_prime_get_qnr() == -2) {
- fp_hlv(t1, a[0]);
+ fp_hlv(t0, a[0]);
} else {
- fp_set_dig(t1, -fp_prime_get_qnr());
- fp_inv(t1, t1);
- fp_mul(t1, t1, a[0]);
+ fp_set_dig(t0, -fp_prime_get_qnr());
+ fp_inv(t0, t0);
+ fp_mul(t0, t0, a[0]);
}
#endif
- fp_neg(t1, t1);
+ fp_neg(t0, t0);
fp_zero(c[0]);
- if (!fp_srt(c[1], t1)) {
+ if (!fp_srt(c[1], t0)) {
/* should never happen! */
RLC_THROW(ERR_NO_VALID);
}
}
} else {
- /* t1 = a[0]^2 - u^2 * a[1]^2 */
- fp_sqr(t1, a[0]);
- fp_sqr(t2, a[1]);
+ /* t0 = a[0]^2 - i^2 * a[1]^2 */
+ fp_sqr(t0, a[0]);
+ fp_sqr(t1, a[1]);
for (int i = -1; i > fp_prime_get_qnr(); i--) {
- fp_add(t1, t1, t2);
+ fp_add(t0, t0, t1);
}
- fp_add(t1, t1, t2);
-
- if (fp_srt(t2, t1)) {
- /* t1 = (a_0 + sqrt(t1)) / 2 */
- fp_add(t1, a[0], t2);
- fp_hlv(t1, t1);
-
- if (!fp_srt(t3, t1)) {
- /* t1 = (a_0 - sqrt(t1)) / 2 */
- fp_sub(t1, a[0], t2);
- fp_hlv(t1, t1);
- fp_srt(t3, t1);
+ fp_add(t0, t0, t1);
+
+ if (fp_srt(t1, t0)) {
+ /* t0 = (a_0 + sqrt(t0)) / 2 */
+ fp_add(t0, a[0], t1);
+ fp_hlv(t0, 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);
+ }
}
- /* c_0 = sqrt(t1) */
- fp_copy(c[0], t3);
- /* c_1 = a_1 / (2 * sqrt(t1)) */
- fp_dbl(t3, t3);
- fp_inv(t3, t3);
- fp_mul(c[1], a[1], t3);
+ /* c_0 = sqrt(t0) */
+ fp_copy(c[0], t2);
+ /* c_1 = a_1 / (2 * sqrt(t0)) */
+ fp_dbl(t2, t2);
+ fp_inv(t2, t2);
+ fp_mul(c[1], a[1], t2);
r = 1;
}
}
@@ -112,9 +120,9 @@ int fp2_srt(fp2_t c, fp2_t a) {
RLC_THROW(ERR_CAUGHT);
}
RLC_FINALLY {
+ fp_free(t0);
fp_free(t1);
fp_free(t2);
- fp_free(t3);
}
return r;
}
@@ -130,6 +138,11 @@ int fp3_srt(fp3_t c, fp3_t a) {
fp3_null(t3);
bn_null(e);
+ if (fp3_is_zero(a)) {
+ fp3_zero(c);
+ return 1;
+ }
+
RLC_TRY {
fp3_new(t0);
fp3_new(t1);
@@ -202,3 +215,85 @@ int fp3_srt(fp3_t c, fp3_t a) {
return r;
}
+
+int fp4_srt(fp4_t c, fp4_t a) {
+ int r = 0;
+ fp2_t t0, t1, t2;
+
+ fp2_null(t0);
+ fp2_null(t1);
+ fp2_null(t2);
+
+ if (fp4_is_zero(a)) {
+ fp4_zero(c);
+ return 1;
+ }
+
+ RLC_TRY {
+ fp2_new(t0);
+ fp2_new(t1);
+ fp2_new(t2);
+
+ if (fp2_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 (fp2_srt(t0, a[0])) {
+ fp2_copy(c[0], t0);
+ fp2_zero(c[1]);
+ } else {
+ /* Compute a[0]/s^2. */
+ fp2_set_dig(t0, 1);
+ fp2_mul_nor(t0, t0);
+ fp2_inv(t0, t0);
+ fp2_mul(t0, a[0], t0);
+ fp2_neg(t0, t0);
+ fp2_zero(c[0]);
+ if (!fp2_srt(c[1], t0)) {
+ /* should never happen! */
+ RLC_THROW(ERR_NO_VALID);
+ }
+ fp2_mul_art(c[1], c[1]);
+ }
+ } else {
+ /* t0 = a[0]^2 - s^2 * a[1]^2 */
+ fp2_sqr(t0, a[0]);
+ fp2_sqr(t1, a[1]);
+ fp2_mul_nor(t2, t1);
+ fp2_sub(t0, t0, t2);
+
+ if (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);
+ }
+ }
+ /* c_0 = sqrt(t0) */
+ fp2_copy(c[0], t2);
+
+ /* c_1 = a_1 / (2 * sqrt(t0)) */
+ fp2_dbl(t2, t2);
+ fp2_inv(t2, t2);
+ fp2_mul(c[1], a[1], t2);
+ r = 1;
+ }
+ }
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ } RLC_FINALLY {
+ fp2_free(t0);
+ fp2_free(t1);
+ fp2_free(t2);
+ }
+ return r;
+}
diff --git a/contrib/relic/src/fpx/relic_fpx_util.c b/contrib/relic/src/fpx/relic_fpx_util.c
index d2a69e4ad..1de8cc6fc 100644
--- a/contrib/relic/src/fpx/relic_fpx_util.c
+++ b/contrib/relic/src/fpx/relic_fpx_util.c
@@ -583,28 +583,69 @@ void fp24_print(fp24_t a) {
fp8_print(a[2]);
}
-int fp24_size_bin(fp24_t a) {
- return 24 * RLC_FP_BYTES;
+int fp24_size_bin(fp24_t a, int pack) {
+ if (pack) {
+ if (fp24_test_cyc(a)) {
+ return 16 * RLC_FP_BYTES;
+ } else {
+ return 24 * RLC_FP_BYTES;
+ }
+ } else {
+ return 24 * RLC_FP_BYTES;
+ }
}
void fp24_read_bin(fp24_t a, const uint8_t *bin, int len) {
- if (len != 24 * RLC_FP_BYTES) {
+ if (len != 16 * RLC_FP_BYTES && len != 24 * 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);
- fp8_read_bin(a[2], bin + 16 * RLC_FP_BYTES, 8 * RLC_FP_BYTES);
+ if (len == 16 * RLC_FP_BYTES) {
+ fp4_zero(a[0][0]);
+ fp4_zero(a[0][1]);
+ fp4_read_bin(a[1][0], bin, 4 * RLC_FP_BYTES);
+ fp4_read_bin(a[1][1], bin + 4 * RLC_FP_BYTES, 4 * RLC_FP_BYTES);
+ fp4_read_bin(a[2][0], bin + 8 * RLC_FP_BYTES, 4 * RLC_FP_BYTES);
+ fp4_read_bin(a[2][1], bin + 12 * RLC_FP_BYTES, 4 * RLC_FP_BYTES);
+ fp24_back_cyc(a, a);
+ }
+ if (len == 24 * RLC_FP_BYTES) {
+ fp8_read_bin(a[0], bin, 8 * RLC_FP_BYTES);
+ fp8_read_bin(a[1], bin + 8 * RLC_FP_BYTES, 8 * RLC_FP_BYTES);
+ fp8_read_bin(a[2], bin + 16 * RLC_FP_BYTES, 8 * RLC_FP_BYTES);
+ }
}
-void fp24_write_bin(uint8_t *bin, int len, fp24_t a) {
- if (len != 24 * RLC_FP_BYTES) {
- RLC_THROW(ERR_NO_BUFFER);
- return;
+void fp24_write_bin(uint8_t *bin, int len, fp24_t a, int pack) {
+ fp24_t t;
+
+ fp24_null(t);
+
+ RLC_TRY {
+ fp24_new(t);
+
+ if (pack) {
+ if (len != 16 * RLC_FP_BYTES) {
+ RLC_THROW(ERR_NO_BUFFER);
+ }
+ fp24_pck(t, a);
+ fp4_write_bin(bin, 4 * RLC_FP_BYTES, a[1][0]);
+ fp4_write_bin(bin + 4 * RLC_FP_BYTES, 4 * RLC_FP_BYTES, a[1][1]);
+ fp4_write_bin(bin + 8 * RLC_FP_BYTES, 4 * RLC_FP_BYTES, a[2][0]);
+ fp4_write_bin(bin + 12 * RLC_FP_BYTES, 4 * RLC_FP_BYTES, a[2][1]);
+ } else {
+ if (len != 24 * RLC_FP_BYTES) {
+ RLC_THROW(ERR_NO_BUFFER);
+ }
+ fp8_write_bin(bin, 8 * RLC_FP_BYTES, a[0]);
+ fp8_write_bin(bin + 8 * RLC_FP_BYTES, 8 * RLC_FP_BYTES, a[1]);
+ fp8_write_bin(bin + 16 * RLC_FP_BYTES, 8 * RLC_FP_BYTES, a[2]);
+ }
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ } RLC_FINALLY {
+ fp24_free(t);
}
- fp8_write_bin(bin, 8 * RLC_FP_BYTES, a[0]);
- fp8_write_bin(bin + 8 * RLC_FP_BYTES, 8 * RLC_FP_BYTES, a[1]);
- fp8_write_bin(bin + 16 * RLC_FP_BYTES, 8 * RLC_FP_BYTES, a[2]);
}
void fp24_set_dig(fp24_t a, dig_t b) {
@@ -690,8 +731,8 @@ void fp48_write_bin(uint8_t *bin, int len, fp48_t a, int pack) {
if (len != 48 * RLC_FP_BYTES) {
RLC_THROW(ERR_NO_BUFFER);
}
- fp24_write_bin(bin, 24 * RLC_FP_BYTES, a[0]);
- fp24_write_bin(bin + 24 * RLC_FP_BYTES, 24 * RLC_FP_BYTES, a[1]);
+ fp24_write_bin(bin, 24 * RLC_FP_BYTES, a[0], 0);
+ fp24_write_bin(bin + 24 * RLC_FP_BYTES, 24 * RLC_FP_BYTES, a[1], 0);
}
} RLC_CATCH_ANY {
RLC_THROW(ERR_CAUGHT);
diff --git a/contrib/relic/src/low/easy/relic_bn_div_low.c b/contrib/relic/src/low/easy/relic_bn_div_low.c
index 69a9ec686..c03e37fa9 100644
--- a/contrib/relic/src/low/easy/relic_bn_div_low.c
+++ b/contrib/relic/src/low/easy/relic_bn_div_low.c
@@ -83,13 +83,9 @@ void bn_divn_low(dig_t *c, dig_t *d, dig_t *a, int sa, dig_t *b, int sb) {
}
if (a[i] == b[t]) {
- c[i - t - 1] = ((((dbl_t)1) << RLC_DIG) - 1);
+ c[i - t - 1] = RLC_MASK(RLC_DIG);
} else {
- dbl_t tmp;
- tmp = ((dbl_t)a[i]) << ((dbl_t)RLC_DIG);
- tmp |= (dbl_t)(a[i - 1]);
- tmp /= (dbl_t)(b[t]);
- c[i - t - 1] = (dig_t)tmp;
+ RLC_DIV_DIG(c[i - t - 1], carry, a[i], a[i - 1], b[t]);
}
c[i - t - 1]++;
@@ -130,21 +126,12 @@ void bn_divn_low(dig_t *c, dig_t *d, dig_t *a, int sa, dig_t *b, int sb) {
}
void bn_div1_low(dig_t *c, dig_t *d, const dig_t *a, int size, dig_t b) {
- dbl_t w;
- dig_t r;
- int i;
+ dig_t q, r, w = 0;
- w = 0;
- for (i = size - 1; i >= 0; i--) {
- w = (w << ((dbl_t)RLC_DIG)) | ((dbl_t)a[i]);
-
- if (w >= b) {
- r = (dig_t)(w / b);
- w -= ((dbl_t)r) * ((dbl_t)b);
- } else {
- r = 0;
- }
- c[i] = (dig_t)r;
+ for (int i = size - 1; i >= 0; i--) {
+ RLC_DIV_DIG(q, r, w, a[i], b);
+ c[i] = q;
+ w = r;
}
*d = (dig_t)w;
}
diff --git a/contrib/relic/src/low/easy/relic_bn_mod_low.c b/contrib/relic/src/low/easy/relic_bn_mod_low.c
index 2be2a5f4f..304422580 100644
--- a/contrib/relic/src/low/easy/relic_bn_mod_low.c
+++ b/contrib/relic/src/low/easy/relic_bn_mod_low.c
@@ -32,42 +32,7 @@
#include "relic_bn.h"
#include "relic_bn_low.h"
-
-/*============================================================================*/
-/* Private definitions */
-/*============================================================================*/
-
-/**
- * Accumulates a double precision digit in a triple register variable.
- *
- * @param[in,out] R2 - most significant word of the triple register.
- * @param[in,out] R1 - middle word of the triple register.
- * @param[in,out] R0 - lowest significant word of the triple register.
- * @param[in] A - the first digit to multiply.
- * @param[in] B - the second digit to multiply.
- */
-#define COMBA_STEP_BN_MOD_LOW(R2, R1, R0, A, B) \
- dbl_t r = (dbl_t)(A) * (dbl_t)(B); \
- dig_t _r = (R1); \
- (R0) += (dig_t)(r); \
- (R1) += (R0) < (dig_t)(r); \
- (R2) += (R1) < _r; \
- (R1) += (dig_t)(r >> (dbl_t)RLC_DIG); \
- (R2) += (R1) < (dig_t)(r >> (dbl_t)RLC_DIG); \
-
-/**
- * Accumulates a single precision digit in a triple register variable.
- *
- * @param[in,out] R2 - most significant word of the triple register.
- * @param[in,out] R1 - middle word of the triple register.
- * @param[in,out] R0 - lowest significant word of the triple register.
- * @param[in] A - the first digit to accumulate.
- */
-#define COMBA_ADD(R2, R1, R0, A) \
- dig_t __r = (R1); \
- (R0) += (A); \
- (R1) += (R0) < (A); \
- (R2) += (R1) < __r; \
+#include "relic_util.h"
/*============================================================================*/
/* Public definitions */
@@ -75,7 +40,7 @@
void bn_modn_low(dig_t *c, const dig_t *a, int sa, const dig_t *m, int sm, dig_t u) {
int i, j;
- dig_t r0, r1, r2;
+ dig_t t, r0, r1, r2;
dig_t *tmp, *tmpc;
const dig_t *tmpm;
@@ -86,13 +51,13 @@ void bn_modn_low(dig_t *c, const dig_t *a, int sa, const dig_t *m, int sm, dig_t
tmp = c;
tmpm = m + i;
for (j = 0; j < i; j++, tmp++, tmpm--) {
- COMBA_STEP_BN_MOD_LOW(r2, r1, r0, *tmp, *tmpm);
+ RLC_COMBA_STEP_MUL(r2, r1, r0, *tmp, *tmpm);
}
if (i < sa) {
- COMBA_ADD(r2, r1, r0, *a);
+ RLC_COMBA_ADD(t, r2, r1, r0, *a);
}
*tmpc = (dig_t)(r0 * u);
- COMBA_STEP_BN_MOD_LOW(r2, r1, r0, *tmpc, *m);
+ RLC_COMBA_STEP_MUL(r2, r1, r0, *tmpc, *m);
r0 = r1;
r1 = r2;
r2 = 0;
@@ -101,10 +66,10 @@ void bn_modn_low(dig_t *c, const dig_t *a, int sa, const dig_t *m, int sm, dig_t
tmp = c + (i - sm + 1);
tmpm = m + sm - 1;
for (j = i - sm + 1; j < sm; j++, tmp++, tmpm--) {
- COMBA_STEP_BN_MOD_LOW(r2, r1, r0, *tmp, *tmpm);
+ RLC_COMBA_STEP_MUL(r2, r1, r0, *tmp, *tmpm);
}
if (i < sa) {
- COMBA_ADD(r2, r1, r0, *a);
+ RLC_COMBA_ADD(t, r2, r1, r0, *a);
}
c[i - sm] = r0;
r0 = r1;
@@ -113,7 +78,7 @@ void bn_modn_low(dig_t *c, const dig_t *a, int sa, const dig_t *m, int sm, dig_t
}
if (i < sa) {
- COMBA_ADD(r2, r1, r0, *a);
+ RLC_COMBA_ADD(t, r2, r1, r0, *a);
}
c[sm - 1] = r0;
if (r1) {
diff --git a/contrib/relic/src/low/easy/relic_bn_mul_low.c b/contrib/relic/src/low/easy/relic_bn_mul_low.c
index b640a6451..0e4c67e4d 100644
--- a/contrib/relic/src/low/easy/relic_bn_mul_low.c
+++ b/contrib/relic/src/low/easy/relic_bn_mul_low.c
@@ -32,69 +32,65 @@
#include "relic_bn.h"
#include "relic_bn_low.h"
-
-/*============================================================================*/
-/* Private definitions */
-/*============================================================================*/
-
-/**
- * Accumulates a double precision digit in a triple register variable.
- *
- * @param[in,out] R2 - most significant word of the triple register.
- * @param[in,out] R1 - middle word of the triple register.
- * @param[in,out] R0 - lowest significant word of the triple register.
- * @param[in] A - the first digit to multiply.
- * @param[in] B - the second digit to multiply.
- */
-#define COMBA_STEP_BN_MUL_LOW(R2, R1, R0, A, B) \
- dbl_t r = (dbl_t)(A) * (dbl_t)(B); \
- dig_t _r = (R1); \
- (R0) += (dig_t)(r); \
- (R1) += (R0) < (dig_t)(r); \
- (R2) += (R1) < _r; \
- (R1) += (dig_t)((r) >> (dbl_t)RLC_DIG); \
- (R2) += (R1) < (dig_t)((r) >> (dbl_t)RLC_DIG); \
+#include "relic_util.h"
/*============================================================================*/
/* Public definitions */
/*============================================================================*/
dig_t bn_mula_low(dig_t *c, const dig_t *a, dig_t digit, int size) {
- int i;
- dig_t carry;
- dbl_t r;
-
- carry = 0;
- for (i = 0; i < size; i++, a++, c++) {
- /* Multiply the digit *tmpa by b and accumulate with the previous
+ dig_t _c, r0, r1, carry = 0;
+ for (int i = 0; i < size; i++, a++, c++) {
+ /* Multiply the digit *a by d and accumulate with the previous
* result in the same columns and the propagated carry. */
- r = (dbl_t)(*c) + (dbl_t)(*a) * (dbl_t)(digit) + (dbl_t)(carry);
+ RLC_MUL_DIG(r1, r0, *a, digit);
+ _c = r0 + carry;
+ carry = r1 + (_c < carry);
/* Increment the column and assign the result. */
- *c = (dig_t)r;
+ *c = *c + _c;
/* Update the carry. */
- carry = (dig_t)(r >> (dbl_t)RLC_DIG);
+ carry += (*c < _c);
}
return carry;
}
dig_t bn_mul1_low(dig_t *c, const dig_t *a, dig_t digit, int size) {
- int i;
- dig_t carry;
- dbl_t r;
-
- carry = 0;
- for (i = 0; i < size; i++, a++, c++) {
- /* Multiply the digit *tmpa by b and accumulate with the previous
- * result in the same columns and the propagated carry. */
- r = (dbl_t)(carry) + (dbl_t)(*a) * (dbl_t)(digit);
- /* Increment the column and assign the result. */
- *c = (dig_t)r;
- /* Update the carry. */
- carry = (dig_t)(r >> (dbl_t)RLC_DIG);
+ dig_t r0, r1, carry = 0;
+ for (int i = 0; i < size; i++, a++, c++) {
+ RLC_MUL_DIG(r1, r0, *a, digit);
+ *c = r0 + carry;
+ carry = r1 + (*c < carry);
}
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);
+
+ 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);
+ _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);
+ _c += c0;
+ c0 = r + (_c < c0);
+ _c ^= sign;
+ c[i] = _c + c1;
+ c1 = (c[i] < _c);
+ }
+ return (c0 ^ sign) + c1;
+}
+
void bn_muln_low(dig_t *c, const dig_t *a, const dig_t *b, int size) {
int i, j;
const dig_t *tmpa, *tmpb;
@@ -105,7 +101,7 @@ void bn_muln_low(dig_t *c, const dig_t *a, const dig_t *b, int size) {
tmpa = a;
tmpb = b + i;
for (j = 0; j <= i; j++, tmpa++, tmpb--) {
- COMBA_STEP_BN_MUL_LOW(r2, r1, r0, *tmpa, *tmpb);
+ RLC_COMBA_STEP_MUL(r2, r1, r0, *tmpa, *tmpb);
}
*c = r0;
r0 = r1;
@@ -116,7 +112,7 @@ void bn_muln_low(dig_t *c, const dig_t *a, const dig_t *b, int size) {
tmpa = a + i + 1;
tmpb = b + (size - 1);
for (j = 0; j < size - (i + 1); j++, tmpa++, tmpb--) {
- COMBA_STEP_BN_MUL_LOW(r2, r1, r0, *tmpa, *tmpb);
+ RLC_COMBA_STEP_MUL(r2, r1, r0, *tmpa, *tmpb);
}
*c = r0;
r0 = r1;
@@ -138,7 +134,7 @@ void bn_muld_low(dig_t *c, const dig_t *a, int sa, const dig_t *b, int sb,
tmpa = a;
tmpb = b + i;
for (j = 0; j <= i; j++, tmpa++, tmpb--) {
- COMBA_STEP_BN_MUL_LOW(r2, r1, r0, *tmpa, *tmpb);
+ RLC_COMBA_STEP_MUL(r2, r1, r0, *tmpa, *tmpb);
}
*c = r0;
r0 = r1;
@@ -150,7 +146,7 @@ void bn_muld_low(dig_t *c, const dig_t *a, int sa, const dig_t *b, int sb,
tmpa = a + ++ta;
tmpb = b + (sb - 1);
for (j = 0; j < sb; j++, tmpa++, tmpb--) {
- COMBA_STEP_BN_MUL_LOW(r2, r1, r0, *tmpa, *tmpb);
+ RLC_COMBA_STEP_MUL(r2, r1, r0, *tmpa, *tmpb);
}
*c = r0;
r0 = r1;
@@ -161,7 +157,7 @@ void bn_muld_low(dig_t *c, const dig_t *a, int sa, const dig_t *b, int sb,
tmpa = a + ++ta;
tmpb = b + (sb - 1);
for (j = 0; j < sa - ta; j++, tmpa++, tmpb--) {
- COMBA_STEP_BN_MUL_LOW(r2, r1, r0, *tmpa, *tmpb);
+ RLC_COMBA_STEP_MUL(r2, r1, r0, *tmpa, *tmpb);
}
*c = r0;
r0 = r1;
diff --git a/contrib/relic/src/low/easy/relic_bn_shift_low.c b/contrib/relic/src/low/easy/relic_bn_shift_low.c
index e2555162a..d333df931 100644
--- a/contrib/relic/src/low/easy/relic_bn_shift_low.c
+++ b/contrib/relic/src/low/easy/relic_bn_shift_low.c
@@ -126,3 +126,19 @@ dig_t bn_rshb_low(dig_t *c, const dig_t *a, int size, int bits) {
}
return carry;
}
+
+dig_t bn_rshs_low(dig_t *c, const dig_t *a, int size, int bits) {
+ dig_t r, carry, shift, mask;
+
+ /* Prepare the bit mask. */
+ shift = (RLC_DIG - bits) % RLC_DIG;
+ mask = RLC_MASK(bits);
+ carry = a[size - 1] & mask;
+ c[size - 1] = (dis_t)a[size - 1] >> bits;
+ for (int i = size - 2; i >= 0; i--) {
+ r = a[i] & mask;
+ c[i] = (a[i] >> bits) | (carry << shift);
+ carry = r;
+ }
+ return carry;
+}
diff --git a/contrib/relic/src/low/easy/relic_bn_sqr_low.c b/contrib/relic/src/low/easy/relic_bn_sqr_low.c
index e52fccf12..ad4872f9f 100644
--- a/contrib/relic/src/low/easy/relic_bn_sqr_low.c
+++ b/contrib/relic/src/low/easy/relic_bn_sqr_low.c
@@ -32,47 +32,7 @@
#include "relic_bn.h"
#include "relic_bn_low.h"
-
-/*============================================================================*/
-/* Private definitions */
-/*============================================================================*/
-
-/**
- * Computes the step of a Comba squaring.
- *
- * @param[in,out] R2 - most significant word of the triple register.
- * @param[in,out] R1 - middle word of the triple register.
- * @param[in,out] R0 - lowest significant word of the triple register.
- * @param[in] A - the first digit to multiply.
- * @param[in] B - the second digit to multiply.
- */
-#define COMBA_STEP_BN_SQR_LOW(R2, R1, R0, A, B) \
- dbl_t r = (dbl_t)(A) * (dbl_t)(B); \
- dbl_t s = r + r; \
- dig_t _r = (R1); \
- (R0) += (dig_t)s; \
- (R1) += (R0) < (dig_t)s; \
- (R2) += (R1) < _r; \
- (R1) += (dig_t)(s >> (dbl_t)RLC_DIG); \
- (R2) += (R1) < (dig_t)(s >> (dbl_t)RLC_DIG); \
- (R2) += (s < r); \
-
-/**
- * Computes the step of a Comba squaring when the loop length is odd.
- *
- * @param[in,out] R2 - most significant word of the triple register.
- * @param[in,out] R1 - middle word of the triple register.
- * @param[in,out] R0 - lowest significant word of the triple register.
- * @param[in] A - the first digit to multiply.
- */
-#define COMBA_FINAL(R2, R1, R0, A) \
- dbl_t r = (dbl_t)(*tmpa) * (dbl_t)(*tmpa); \
- dig_t _r = (R1); \
- (R0) += (dig_t)(r); \
- (R1) += (R0) < (dig_t)r; \
- (R2) += (R1) < _r; \
- (R1) += (dig_t)(r >> (dbl_t)RLC_DIG); \
- (R2) += (R1) < (dig_t)(r >> (dbl_t)RLC_DIG); \
+#include "relic_util.h"
/*============================================================================*/
/* Public definitions */
@@ -81,6 +41,41 @@
dig_t bn_sqra_low(dig_t *c, const dig_t *a, int size) {
int i;
dig_t c0, c1;
+
+#ifdef RLC_CONF_NODBL
+ dig_t r0, r1, _r0, _r1, s0, s1, t, t0, t1;
+
+ t = a[0];
+
+ /* Accumulate this column with the square of a->dp[i]. */
+ RLC_MUL_DIG(_r1, _r0, t, t);
+ r0 = _r0 + c[0];
+ r1 = _r1 + (r0 < _r0);
+ c[0] = r0;
+
+ /* Update the carry. */
+ c0 = r1;
+ c1 = 0;
+
+ /* Version of the main loop not using double-precision types. */
+ for (i = 1; i < size; i++) {
+ RLC_MUL_DIG(_r1, _r0, t, a[i]);
+ r0 = _r0 + _r0;
+ r1 = _r1 + _r1 + (r0 < _r0);
+
+ s0 = r0 + c0;
+ s1 = r1 + (s0 < r0);
+
+ t0 = s0 + c[i];
+ t1 = s1 + (t0 < s0);
+ c[i] = t0;
+
+ /* Accumulate the old delayed carry. */
+ c0 = t1 + c1;
+ /* Compute the new delayed carry. */
+ c1 = (t1 < s1) || (s1 < r1) || (r1 < _r1) || (c0 < c1);
+ }
+#else
dbl_t r, r0, r1;
/* Accumulate this column with the square of a->dp[i]. */
@@ -91,6 +86,7 @@ dig_t bn_sqra_low(dig_t *c, const dig_t *a, int size) {
c0 = (dig_t)(r >> (dbl_t)RLC_DIG);
c1 = 0;
+ /* Version using double-precision types is hopefully faster. */
for (i = 1; i < size; i++) {
r = (dbl_t)(a[0]) * (dbl_t)(a[i]);
r0 = r + r;
@@ -102,6 +98,8 @@ dig_t bn_sqra_low(dig_t *c, const dig_t *a, int size) {
/* Compute the new delayed carry. */
c1 = (r0 < r) || (r1 < r0) || (c0 < c1);
}
+#endif
+
c[size] += c0;
c1 += (c[size] < c0);
return c1;
@@ -123,10 +121,10 @@ void bn_sqrn_low(dig_t *c, const dig_t *a, int size) {
/* Compute the number of additions in this column. */
j = (i + 1);
for (j = 0; j < (i + 1) / 2; j++, tmpa++, tmpb--) {
- COMBA_STEP_BN_SQR_LOW(r2, r1, r0, *tmpa, *tmpb);
+ RLC_COMBA_STEP_SQR(r2, r1, r0, *tmpa, *tmpb);
}
if (!(i & 0x01)) {
- COMBA_FINAL(r2, r1, r0, *tmpa);
+ RLC_COMBA_STEP_MUL(r2, r1, r0, *tmpa, *tmpa);
}
*c = r0;
r0 = r1;
@@ -139,10 +137,10 @@ void bn_sqrn_low(dig_t *c, const dig_t *a, int size) {
/* Compute the number of additions in this column. */
for (j = 0; j < (size - 1 - i) / 2; j++, tmpa++, tmpb--) {
- COMBA_STEP_BN_SQR_LOW(r2, r1, r0, *tmpa, *tmpb);
+ RLC_COMBA_STEP_SQR(r2, r1, r0, *tmpa, *tmpb);
}
if (!((size - i) & 0x01)) {
- COMBA_FINAL(r2, r1, r0, *tmpa);
+ RLC_COMBA_STEP_MUL(r2, r1, r0, *tmpa, *tmpa);
}
*c = r0;
r0 = r1;
diff --git a/contrib/relic/src/low/easy/relic_fb_itr_low.c b/contrib/relic/src/low/easy/relic_fb_itr_low.c
index 69d476270..a8556a783 100644
--- a/contrib/relic/src/low/easy/relic_fb_itr_low.c
+++ b/contrib/relic/src/low/easy/relic_fb_itr_low.c
@@ -50,11 +50,7 @@ void fb_itrn_low(dig_t *c, const dig_t *a, dig_t *t) {
tmp = a;
for (j = 0; j < RLC_FB_DIGS; j++, tmp++) {
u = (*tmp >> i) & 0x0F;
-#if ALLOC == AUTO
p = (t + ((j * RLC_DIG + i) * 4 + u) * RLC_FB_DIGS);
-#else
- p = ((fb_t *)t)[(j * RLC_DIG + i) * 4 + u];
-#endif
fb_addn_low(v, v, p);
}
}
diff --git a/contrib/relic/src/low/easy/relic_fp_inv_low.c b/contrib/relic/src/low/easy/relic_fp_inv_low.c
index 4d4bed832..02c43b679 100644
--- a/contrib/relic/src/low/easy/relic_fp_inv_low.c
+++ b/contrib/relic/src/low/easy/relic_fp_inv_low.c
@@ -43,7 +43,7 @@
void fp_invm_low(dig_t *c, const dig_t *a) {
bn_st e;
- bn_init(&e, RLC_FP_DIGS);
+ bn_make(&e, RLC_FP_DIGS);
e.used = RLC_FP_DIGS;
dv_copy(e.dp, fp_prime_get(), RLC_FP_DIGS);
diff --git a/contrib/relic/src/low/easy/relic_fp_mul_low.c b/contrib/relic/src/low/easy/relic_fp_mul_low.c
index a6c2d02d5..8295ab618 100644
--- a/contrib/relic/src/low/easy/relic_fp_mul_low.c
+++ b/contrib/relic/src/low/easy/relic_fp_mul_low.c
@@ -31,65 +31,38 @@
#include "relic_fp.h"
#include "relic_fp_low.h"
+#include "relic_util.h"
/*============================================================================*/
/* Private definitions */
/*============================================================================*/
-/**
- * Accumulates a double precision digit in a triple register variable.
- *
- * @param[in,out] R2 - most significant word of the triple register.
- * @param[in,out] R1 - middle word of the triple register.
- * @param[in,out] R0 - lowest significant word of the triple register.
- * @param[in] A - the first digit to multiply.
- * @param[in] B - the second digit to multiply.
- */
-#define COMBA_STEP_MUL(R2, R1, R0, A, B) \
- dbl_t r = (dbl_t)(A) * (dbl_t)(B); \
- dig_t _r = (R1); \
- (R0) += (dig_t)(r); \
- (R1) += (R0) < (dig_t)(r); \
- (R2) += (R1) < _r; \
- (R1) += (dig_t)((r) >> (dbl_t)RLC_DIG); \
- (R2) += (R1) < (dig_t)((r) >> (dbl_t)RLC_DIG); \
-
/*============================================================================*/
/* Public definitions */
/*============================================================================*/
dig_t fp_mula_low(dig_t *c, const dig_t *a, dig_t digit) {
- int i;
- dig_t carry;
- dbl_t r;
-
- carry = 0;
- for (i = 0; i < RLC_FP_DIGS; i++, a++, c++) {
- /* Multiply the digit *tmpa by b and accumulate with the previous
+ dig_t _c, r0, r1, carry = 0;
+ for (int i = 0; i < RLC_FP_DIGS; i++, a++, c++) {
+ /* Multiply the digit *a by d and accumulate with the previous
* result in the same columns and the propagated carry. */
- r = (dbl_t)(*c) + (dbl_t)(*a) * (dbl_t)(digit) + (dbl_t)(carry);
+ RLC_MUL_DIG(r1, r0, *a, digit);
+ _c = r0 + carry;
+ carry = r1 + (_c < carry);
/* Increment the column and assign the result. */
- *c = (dig_t)r;
+ *c = *c + _c;
/* Update the carry. */
- carry = (dig_t)(r >> (dbl_t)RLC_DIG);
+ carry += (*c < _c);
}
return carry;
}
dig_t fp_mul1_low(dig_t *c, const dig_t *a, dig_t digit) {
- int i;
- dig_t carry;
- dbl_t r;
-
- carry = 0;
- for (i = 0; i < RLC_FP_DIGS; i++, a++, c++) {
- /* Multiply the digit *tmpa by b and accumulate with the previous
- * result in the same columns and the propagated carry. */
- r = (dbl_t)(*a) * (dbl_t)(digit) + (dbl_t)(carry);
- /* Increment the column and assign the result. */
- *c = (dig_t)r;
- /* Update the carry. */
- carry = (dig_t)(r >> (dbl_t)RLC_DIG);
+ dig_t r0, r1, carry = 0;
+ for (int i = 0; i < RLC_FP_DIGS; i++, a++, c++) {
+ RLC_MUL_DIG(r1, r0, *a, digit);
+ *c = r0 + carry;
+ carry = r1 + (*c < carry);
}
return carry;
}
@@ -104,7 +77,7 @@ void fp_muln_low(dig_t *c, const dig_t *a, const dig_t *b) {
tmpa = a;
tmpb = b + i;
for (j = 0; j <= i; j++, tmpa++, tmpb--) {
- COMBA_STEP_MUL(r2, r1, r0, *tmpa, *tmpb);
+ RLC_COMBA_STEP_MUL(r2, r1, r0, *tmpa, *tmpb);
}
*c = r0;
r0 = r1;
@@ -115,7 +88,7 @@ void fp_muln_low(dig_t *c, const dig_t *a, const dig_t *b) {
tmpa = a + i + 1;
tmpb = b + (RLC_FP_DIGS - 1);
for (j = 0; j < RLC_FP_DIGS - (i + 1); j++, tmpa++, tmpb--) {
- COMBA_STEP_MUL(r2, r1, r0, *tmpa, *tmpb);
+ RLC_COMBA_STEP_MUL(r2, r1, r0, *tmpa, *tmpb);
}
*c = r0;
r0 = r1;
diff --git a/contrib/relic/src/low/easy/relic_fp_rdc_low.c b/contrib/relic/src/low/easy/relic_fp_rdc_low.c
index 23a28e075..6854aec0a 100644
--- a/contrib/relic/src/low/easy/relic_fp_rdc_low.c
+++ b/contrib/relic/src/low/easy/relic_fp_rdc_low.c
@@ -34,48 +34,13 @@
#include "relic_fp_low.h"
#include "relic_bn_low.h"
-/*============================================================================*/
-/* Private definitions */
-/*============================================================================*/
-
-/**
- * Accumulates a double precision digit in a triple register variable.
- *
- * @param[in,out] R2 - most significant word of the triple register.
- * @param[in,out] R1 - middle word of the triple register.
- * @param[in,out] R0 - lowest significant word of the triple register.
- * @param[in] A - the first digit to multiply.
- * @param[in] B - the second digit to multiply.
- */
-#define COMBA_STEP_RDC(R2, R1, R0, A, B) \
- dbl_t r = (dbl_t)(A) * (dbl_t)(B); \
- dig_t _r = (R1); \
- (R0) += (dig_t)(r); \
- (R1) += (R0) < (dig_t)(r); \
- (R2) += (R1) < _r; \
- (R1) += (dig_t)(r >> (dbl_t)RLC_DIG); \
- (R2) += (R1) < (dig_t)(r >> (dbl_t)RLC_DIG); \
-
-/**
- * Accumulates a single precision digit in a triple register variable.
- *
- * @param[in,out] R2 - most significant word of the triple register.
- * @param[in,out] R1 - middle word of the triple register.
- * @param[in,out] R0 - lowest significant word of the triple register.
- * @param[in] A - the first digit to accumulate.
- */
-#define COMBA_ADD(R2, R1, R0, A) \
- dig_t __r = (R1); \
- (R0) += (A); \
- (R1) += (R0) < (A); \
- (R2) += (R1) < __r; \
-
/*============================================================================*/
/* 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];
+ rlc_align dig_t q[2 * RLC_FP_DIGS], _q[2 * RLC_FP_DIGS];
+ rlc_align dig_t t[2 * RLC_FP_DIGS], r[RLC_FP_DIGS];
const int *sform;
int len, first, i, j, k, b0, d0, b1, d1;
@@ -128,7 +93,7 @@ void fp_rdcs_low(dig_t *c, const dig_t *a, const dig_t *m) {
_q[first - 1] &= RLC_MASK(b0);
}
if (sform[len - 2] < 0) {
- fp_add(r, r, _q);
+ fp_addm_low(r, r, _q);
} else {
if (k++ % 2 == 0) {
if (fp_subn_low(r, r, _q)) {
@@ -147,7 +112,7 @@ void fp_rdcs_low(dig_t *c, const dig_t *a, const dig_t *m) {
void fp_rdcn_low(dig_t *c, dig_t *a) {
int i, j;
- dig_t r0, r1, r2, u, *tmp, *tmpc;
+ dig_t t, r0, r1, r2, u, *tmp, *tmpc;
const dig_t *m, *tmpm;
u = *(fp_prime_get_rdc());
@@ -159,11 +124,11 @@ void fp_rdcn_low(dig_t *c, dig_t *a) {
tmp = c;
tmpm = m + i;
for (j = 0; j < i; j++, tmp++, tmpm--) {
- COMBA_STEP_RDC(r2, r1, r0, *tmp, *tmpm);
+ RLC_COMBA_STEP_MUL(r2, r1, r0, *tmp, *tmpm);
}
- COMBA_ADD(r2, r1, r0, *a);
+ RLC_COMBA_ADD(t, r2, r1, r0, *a);
*tmpc = (dig_t)(r0 * u);
- COMBA_STEP_RDC(r2, r1, r0, *tmpc, *m);
+ RLC_COMBA_STEP_MUL(r2, r1, r0, *tmpc, *m);
r0 = r1;
r1 = r2;
r2 = 0;
@@ -173,15 +138,15 @@ void fp_rdcn_low(dig_t *c, dig_t *a) {
tmp = c + (i - RLC_FP_DIGS + 1);
tmpm = m + RLC_FP_DIGS - 1;
for (j = i - RLC_FP_DIGS + 1; j < RLC_FP_DIGS; j++, tmp++, tmpm--) {
- COMBA_STEP_RDC(r2, r1, r0, *tmp, *tmpm);
+ RLC_COMBA_STEP_MUL(r2, r1, r0, *tmp, *tmpm);
}
- COMBA_ADD(r2, r1, r0, *a);
+ RLC_COMBA_ADD(t, r2, r1, r0, *a);
c[i - RLC_FP_DIGS] = r0;
r0 = r1;
r1 = r2;
r2 = 0;
}
- COMBA_ADD(r2, r1, r0, *a);
+ RLC_COMBA_ADD(t, r2, r1, r0, *a);
c[RLC_FP_DIGS - 1] = r0;
if (r1 || dv_cmp(c, m, RLC_FP_DIGS) != RLC_LT) {
diff --git a/contrib/relic/src/low/x64-asm-254/relic_fp_inv_low.c b/contrib/relic/src/low/easy/relic_fp_smb_low.c
similarity index 69%
rename from contrib/relic/src/low/x64-asm-254/relic_fp_inv_low.c
rename to contrib/relic/src/low/easy/relic_fp_smb_low.c
index d9a4d6521..2e35c4f8b 100644
--- a/contrib/relic/src/low/x64-asm-254/relic_fp_inv_low.c
+++ b/contrib/relic/src/low/easy/relic_fp_smb_low.c
@@ -1,6 +1,6 @@
/*
* RELIC is an Efficient LIbrary for Cryptography
- * Copyright (c) 2013 RELIC Authors
+ * Copyright (c) 2021 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
@@ -24,13 +24,14 @@
/**
* @file
*
- * Implementation of the low-le&vel in&version functions.
+ * Implementation of the low-level inversion functions.
*
* @&version $Id$
* @ingroup fp
*/
#include "relic_bn.h"
+#include "relic_bn_low.h"
#include "relic_fp.h"
#include "relic_fp_low.h"
#include "relic_core.h"
@@ -39,35 +40,26 @@
/* Public definitions */
/*============================================================================*/
-int fp_invn_asm(dig_t *, const dig_t *, const dig_t *);
+int fp_smbm_low(const dig_t *a) {
+ bn_st e;
+ dig_t t[RLC_FP_DIGS];
-void fp_invm_low(dig_t *c, const dig_t *a) {
- fp_t t, x1;
- int j, k;
+ bn_make(&e, RLC_FP_DIGS);
- fp_null(t);
- fp_null(x1);
+ e.used = RLC_FP_DIGS;
+ dv_copy(e.dp, fp_prime_get(), RLC_FP_DIGS);
+ bn_rsh1_low(e.dp, e.dp, RLC_FP_DIGS);
+#if AUTO == ALLOC
+ fp_exp(t, a, &e);
+#else
+ fp_exp(t, (const fp_t)a, &e);
+#endif
- RLC_TRY {
- fp_new(t);
- fp_new(x1);
+ int r = (fp_cmp_dig(t, 1) == RLC_EQ);
+ fp_negm_low(t, t);
+ r = RLC_SEL(r, -(fp_cmp_dig(t, 1) == RLC_EQ), !r);
- /* u = a, v = p, x1 = 1, x2 = 0, k = 0. */
- k = fp_invn_asm(x1, a, c);
- if (k > RLC_FP_DIGS * RLC_DIG) {
- t[0] = t[1] = t[2] = t[3] = 0;
- k = 512 - k;
- j = k % 64;
- k = k / 64;
- t[k] = (dig_t)1 << j;
- fp_mul(c, x1, t);
- }
- }
- RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- }
- RLC_FINALLY {
- fp_free(t);
- fp_free(x1);
- }
+ bn_clean(&e);
+
+ return r;
}
diff --git a/contrib/relic/src/low/easy/relic_fp_sqr_low.c b/contrib/relic/src/low/easy/relic_fp_sqr_low.c
index f201dd8af..6953c2ef0 100644
--- a/contrib/relic/src/low/easy/relic_fp_sqr_low.c
+++ b/contrib/relic/src/low/easy/relic_fp_sqr_low.c
@@ -32,47 +32,6 @@
#include "relic_fp.h"
#include "relic_fp_low.h"
-/*============================================================================*/
-/* Private definitions */
-/*============================================================================*/
-
-/**
- * Computes the step of a Comba squaring.
- *
- * @param[in,out] R2 - most significant word of the triple register.
- * @param[in,out] R1 - middle word of the triple register.
- * @param[in,out] R0 - lowest significant word of the triple register.
- * @param[in] A - the first digit to multiply.
- * @param[in] B - the second digit to multiply.
- */
-#define COMBA_STEP_SQR(R2, R1, R0, A, B) \
- dbl_t r = (dbl_t)(A) * (dbl_t)(B); \
- dbl_t s = r + r; \
- dig_t _r = (R1); \
- (R0) += (dig_t)s; \
- (R1) += (R0) < (dig_t)s; \
- (R2) += (R1) < _r; \
- (R1) += (dig_t)(s >> (dbl_t)RLC_DIG); \
- (R2) += (R1) < (dig_t)(s >> (dbl_t)RLC_DIG); \
- (R2) += (s < r); \
-
-/**
- * Computes the step of a Comba squaring when the loop length is odd.
- *
- * @param[in,out] R2 - most significant word of the triple register.
- * @param[in,out] R1 - middle word of the triple register.
- * @param[in,out] R0 - lowest significant word of the triple register.
- * @param[in] A - the first digit to multiply.
- */
-#define COMBA_FINAL(R2, R1, R0, A) \
- dbl_t r = (dbl_t)(*tmpa) * (dbl_t)(*tmpa); \
- dig_t _r = (R1); \
- (R0) += (dig_t)(r); \
- (R1) += (R0) < (dig_t)r; \
- (R2) += (R1) < _r; \
- (R1) += (dig_t)(r >> (dbl_t)RLC_DIG); \
- (R2) += (R1) < (dig_t)(r >> (dbl_t)RLC_DIG); \
-
/*============================================================================*/
/* Public definitions */
/*============================================================================*/
@@ -92,10 +51,10 @@ void fp_sqrn_low(dig_t *c, const dig_t *a) {
/* Compute the number of additions in this column. */
for (j = 0; j < (i + 1) / 2; j++, tmpa++, tmpb--) {
- COMBA_STEP_SQR(r2, r1, r0, *tmpa, *tmpb);
+ RLC_COMBA_STEP_SQR(r2, r1, r0, *tmpa, *tmpb);
}
if (!(i & 0x01)) {
- COMBA_FINAL(r2, r1, r0, *tmpa);
+ RLC_COMBA_STEP_MUL(r2, r1, r0, *tmpa, *tmpa);
}
*c = r0;
r0 = r1;
@@ -108,10 +67,10 @@ void fp_sqrn_low(dig_t *c, const dig_t *a) {
/* Compute the number of additions in this column. */
for (j = 0; j < (RLC_FP_DIGS - 1 - i) / 2; j++, tmpa++, tmpb--) {
- COMBA_STEP_SQR(r2, r1, r0, *tmpa, *tmpb);
+ RLC_COMBA_STEP_SQR(r2, r1, r0, *tmpa, *tmpb);
}
if (!((RLC_FP_DIGS - i) & 0x01)) {
- COMBA_FINAL(r2, r1, r0, *tmpa);
+ RLC_COMBA_STEP_MUL(r2, r1, r0, *tmpa, *tmpa);
}
*c = r0;
r0 = r1;
diff --git a/contrib/relic/src/low/gmp-sec/relic_bn_mul_low.c b/contrib/relic/src/low/gmp-sec/relic_bn_mul_low.c
index ee999713b..5fa5d265e 100644
--- a/contrib/relic/src/low/gmp-sec/relic_bn_mul_low.c
+++ b/contrib/relic/src/low/gmp-sec/relic_bn_mul_low.c
@@ -54,6 +54,24 @@ dig_t bn_mul1_low(dig_t *c, const dig_t *a, dig_t digit, int size) {
return u[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);
+
+ sa = -sa;
+ 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);
+ for (size_t i = 0; i < size; i++) {
+ c[i] = c[i] ^ sign;
+ }
+ return (carry ^ sign) + bn_add1_low(c, c, -sign, size);
+}
+
void bn_muln_low(dig_t *c, const dig_t *a, const dig_t *b, int size) {
dig_t *t = RLC_ALLOCA(dig_t, mpn_sec_mul_itch(size, size));
mpn_sec_mul(c, a, size, b, size, t);
diff --git a/contrib/relic/src/low/gmp-sec/relic_bn_shift_low.c b/contrib/relic/src/low/gmp-sec/relic_bn_shift_low.c
index 4ca729761..5127b3e4a 100644
--- a/contrib/relic/src/low/gmp-sec/relic_bn_shift_low.c
+++ b/contrib/relic/src/low/gmp-sec/relic_bn_shift_low.c
@@ -56,3 +56,16 @@ dig_t bn_rsh1_low(dig_t *c, const dig_t *a, int size) {
dig_t bn_rshb_low(dig_t *c, const dig_t *a, int size, int bits) {
return mpn_rshift(c, a, size, bits);
}
+
+dig_t bn_rshs_low(dig_t *c, const dig_t *a, int size, int bits) {
+ dig_t r, carry, shift, mask;
+
+ /* Prepare the bit mask. */
+ shift = (RLC_DIG - bits) % RLC_DIG;
+ mask = RLC_MASK(bits);
+ r = a[size - 1] & mask;
+ c[size - 1] = (dis_t)a[size - 1] >> bits;
+ carry = mpn_rshift(c, a, size - 1, bits);
+ c[size - 2] |= (r << shift);
+ return carry;
+}
diff --git a/contrib/relic/src/low/gmp-sec/relic_fp_add_low.c b/contrib/relic/src/low/gmp-sec/relic_fp_add_low.c
index 943a6a027..66305f681 100644
--- a/contrib/relic/src/low/gmp-sec/relic_fp_add_low.c
+++ b/contrib/relic/src/low/gmp-sec/relic_fp_add_low.c
@@ -90,7 +90,7 @@ dig_t fp_subd_low(dig_t *c, const dig_t *a, const dig_t *b) {
void fp_subc_low(dig_t *c, const dig_t *a, const dig_t *b) {
dig_t carry = mpn_sub_n(c, a, b, 2 * RLC_FP_DIGS);
- mpn_cnd_sub_n(carry, c + RLC_FP_DIGS, c + RLC_FP_DIGS,
+ mpn_cnd_add_n(carry, c + RLC_FP_DIGS, c + RLC_FP_DIGS,
fp_prime_get(), RLC_FP_DIGS);
}
@@ -124,6 +124,6 @@ void fp_hlvd_low(dig_t *c, const dig_t *a) {
mpn_sec_add_1(c + RLC_FP_DIGS, a + RLC_FP_DIGS, RLC_FP_DIGS, carry, t);
carry = mpn_rshift(c + RLC_FP_DIGS, c + RLC_FP_DIGS, RLC_FP_DIGS, 1);
mpn_rshift(c, c, RLC_FP_DIGS, 1);
- c[RLC_FP_DIGS - 1] ^= ((dig_t)carry << (RLC_DIG - 1));
+ c[RLC_FP_DIGS - 1] ^= carry;
RLC_FREE(t);
}
diff --git a/contrib/relic/src/low/gmp-sec/relic_fp_rdc_low.c b/contrib/relic/src/low/gmp-sec/relic_fp_rdc_low.c
index e42e9d073..47e225350 100644
--- a/contrib/relic/src/low/gmp-sec/relic_fp_rdc_low.c
+++ b/contrib/relic/src/low/gmp-sec/relic_fp_rdc_low.c
@@ -42,10 +42,9 @@
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];
- rlc_align dig_t _r[2 * RLC_FP_DIGS], r[2 * RLC_FP_DIGS], t[2 * RLC_FP_DIGS];
+ rlc_align dig_t t[2 * RLC_FP_DIGS], r[RLC_FP_DIGS];
const int *sform;
- int len, first, i, j, b0, d0, b1, d1;
- dig_t carry;
+ int len, first, i, j, k, b0, d0, b1, d1;
sform = fp_prime_get_sps(&len);
@@ -64,40 +63,47 @@ void fp_rdcs_low(dig_t *c, const dig_t *a, const dig_t *m) {
r[first - 1] &= RLC_MASK(b0);
}
- carry = 0;
+ 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);
+ dv_lshd(t, q, 2 * RLC_FP_DIGS, d1);
if (b1 > 0) {
bn_lshb_low(t, t, 2 * RLC_FP_DIGS, b1);
}
- if (sform[i] > 0) {
- bn_subn_low(_q, _q, t, 2 * RLC_FP_DIGS);
- } else {
+ /* Check if these two have the same sign. */
+ if ((sform[len - 2] < 0) == (sform[i] < 0)) {
bn_addn_low(_q, _q, t, 2 * RLC_FP_DIGS);
+ } else {
+ bn_subn_low(_q, _q, t, 2 * RLC_FP_DIGS);
}
}
- if (sform[0] > 0) {
- bn_subn_low(_q, _q, q, 2 * RLC_FP_DIGS);
- } else {
+ /* Check if these two have the same sign. */
+ if ((sform[len - 2] < 0) == (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);
}
-
- dv_copy(_r, _q, first);
if (b0 > 0) {
- _r[first - 1] &= RLC_MASK(b0);
+ _q[first - 1] &= RLC_MASK(b0);
}
- carry = fp_addn_low(r, r, _r);
- if (carry) {
- fp_subn_low(r, r, m);
+ if (sform[len - 2] < 0) {
+ fp_addm_low(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) {
diff --git a/contrib/relic/src/low/gmp/relic_bn_mul_low.c b/contrib/relic/src/low/gmp/relic_bn_mul_low.c
index 2229b6d2e..a6806a55f 100644
--- a/contrib/relic/src/low/gmp/relic_bn_mul_low.c
+++ b/contrib/relic/src/low/gmp/relic_bn_mul_low.c
@@ -48,6 +48,24 @@ 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);
}
+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);
+
+ 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);
+ for (size_t i = 0; i < size; i++) {
+ c[i] = c[i] ^ sign;
+ }
+ return (carry ^ sign) + mpn_add_1(c, c, size, -sign);
+}
+
void bn_muln_low(dig_t *c, const dig_t *a, const dig_t *b, int size) {
mpn_mul_n(c, a, b, size);
}
diff --git a/contrib/relic/src/low/gmp/relic_bn_shift_low.c b/contrib/relic/src/low/gmp/relic_bn_shift_low.c
index 0445b5ab8..eb8ed87b1 100644
--- a/contrib/relic/src/low/gmp/relic_bn_shift_low.c
+++ b/contrib/relic/src/low/gmp/relic_bn_shift_low.c
@@ -56,3 +56,16 @@ dig_t bn_rsh1_low(dig_t *c, const dig_t *a, int size) {
dig_t bn_rshb_low(dig_t *c, const dig_t *a, int size, int bits) {
return mpn_rshift(c, a, size, bits);
}
+
+dig_t bn_rshs_low(dig_t *c, const dig_t *a, int size, int bits) {
+ dig_t r, carry, shift, mask;
+
+ /* Prepare the bit mask. */
+ shift = (RLC_DIG - bits) % RLC_DIG;
+ mask = RLC_MASK(bits);
+ r = a[size - 1] & mask;
+ c[size - 1] = (dis_t)a[size - 1] >> bits;
+ carry = mpn_rshift(c, a, size - 1, bits);
+ c[size - 2] |= (r << shift);
+ return carry;
+}
diff --git a/contrib/relic/src/low/gmp/relic_fp_add_low.c b/contrib/relic/src/low/gmp/relic_fp_add_low.c
index a445aa2d9..b5c6dc505 100644
--- a/contrib/relic/src/low/gmp/relic_fp_add_low.c
+++ b/contrib/relic/src/low/gmp/relic_fp_add_low.c
@@ -124,9 +124,7 @@ void fp_hlvm_low(dig_t *c, const dig_t *a) {
dv_copy(c, a, RLC_FP_DIGS);
}
mpn_rshift(c, c, RLC_FP_DIGS, 1);
- if (carry) {
- c[RLC_FP_DIGS - 1] ^= ((dig_t)1 << (RLC_DIG - 1));
- }
+ c[RLC_FP_DIGS - 1] ^= ((dig_t)carry << (RLC_DIG - 1));
}
void fp_hlvd_low(dig_t *c, const dig_t *a) {
@@ -142,7 +140,5 @@ void fp_hlvd_low(dig_t *c, const dig_t *a) {
carry = mpn_rshift(c + RLC_FP_DIGS, c + RLC_FP_DIGS, RLC_FP_DIGS, 1);
mpn_rshift(c, c, RLC_FP_DIGS, 1);
- if (carry) {
- c[RLC_FP_DIGS - 1] ^= ((dig_t)1 << (RLC_DIG - 1));
- }
+ c[RLC_FP_DIGS - 1] ^= carry;
}
diff --git a/contrib/relic/src/low/gmp/relic_fp_rdc_low.c b/contrib/relic/src/low/gmp/relic_fp_rdc_low.c
index 1b75939cb..d8953cf9c 100644
--- a/contrib/relic/src/low/gmp/relic_fp_rdc_low.c
+++ b/contrib/relic/src/low/gmp/relic_fp_rdc_low.c
@@ -42,10 +42,9 @@
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];
- rlc_align dig_t _r[2 * RLC_FP_DIGS], r[2 * RLC_FP_DIGS], t[2 * RLC_FP_DIGS];
+ rlc_align dig_t t[2 * RLC_FP_DIGS], r[RLC_FP_DIGS];
const int *sform;
- int len, first, i, j, b0, d0, b1, d1;
- dig_t carry;
+ int len, first, i, j, k, b0, d0, b1, d1;
sform = fp_prime_get_sps(&len);
@@ -53,7 +52,6 @@ void fp_rdcs_low(dig_t *c, const dig_t *a, const dig_t *m) {
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);
@@ -65,40 +63,47 @@ void fp_rdcs_low(dig_t *c, const dig_t *a, const dig_t *m) {
r[first - 1] &= RLC_MASK(b0);
}
- carry = 0;
+ 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);
+ dv_lshd(t, q, 2 * RLC_FP_DIGS, d1);
if (b1 > 0) {
bn_lshb_low(t, t, 2 * RLC_FP_DIGS, b1);
}
- if (sform[i] > 0) {
- bn_subn_low(_q, _q, t, 2 * RLC_FP_DIGS);
- } else {
+ /* Check if these two have the same sign. */
+ if ((sform[len - 2] < 0) == (sform[i] < 0)) {
bn_addn_low(_q, _q, t, 2 * RLC_FP_DIGS);
+ } else {
+ bn_subn_low(_q, _q, t, 2 * RLC_FP_DIGS);
}
}
- if (sform[0] > 0) {
- bn_subn_low(_q, _q, q, 2 * RLC_FP_DIGS);
- } else {
+ /* Check if these two have the same sign. */
+ if ((sform[len - 2] < 0) == (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);
}
-
- dv_copy(_r, _q, first);
if (b0 > 0) {
- _r[first - 1] &= RLC_MASK(b0);
+ _q[first - 1] &= RLC_MASK(b0);
}
- carry = fp_addn_low(r, r, _r);
- if (carry) {
- fp_subn_low(r, r, m);
+ if (sform[len - 2] < 0) {
+ fp_addm_low(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) {
diff --git a/contrib/relic/src/low/msp-asm/relic_bn_add_low.c b/contrib/relic/src/low/msp-asm/relic_bn_add_low.c
index 4b810145c..9c8ec9679 100644
--- a/contrib/relic/src/low/msp-asm/relic_bn_add_low.c
+++ b/contrib/relic/src/low/msp-asm/relic_bn_add_low.c
@@ -1,6 +1,6 @@
/*
* RELIC is an Efficient LIbrary for Cryptography
- * Copyright (c) 2007, 2008, 2009 RELIC Authors
+ * Copyright (c) 2012 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
diff --git a/contrib/relic/src/low/msp-asm/relic_bn_shift_low.c b/contrib/relic/src/low/msp-asm/relic_bn_shift_low.c
index fc462c662..3f784c556 100644
--- a/contrib/relic/src/low/msp-asm/relic_bn_shift_low.c
+++ b/contrib/relic/src/low/msp-asm/relic_bn_shift_low.c
@@ -1,6 +1,6 @@
/*
* RELIC is an Efficient LIbrary for Cryptography
- * Copyright (c) 2007, 2008, 2009 RELIC Authors
+ * Copyright (c) 2012 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
diff --git a/contrib/relic/src/low/msp-asm/relic_fb_add_low.c b/contrib/relic/src/low/msp-asm/relic_fb_add_low.c
index d6fd6c432..07a50dc9f 100644
--- a/contrib/relic/src/low/msp-asm/relic_fb_add_low.c
+++ b/contrib/relic/src/low/msp-asm/relic_fb_add_low.c
@@ -1,6 +1,6 @@
/*
* RELIC is an Efficient LIbrary for Cryptography
- * Copyright (c) 2007, 2008, 2009 RELIC Authors
+ * Copyright (c) 2012 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
diff --git a/contrib/relic/src/low/msp-asm/relic_fb_add_low.s b/contrib/relic/src/low/msp-asm/relic_fb_add_low.s
index e6b228d3f..89938d4ca 100644
--- a/contrib/relic/src/low/msp-asm/relic_fb_add_low.s
+++ b/contrib/relic/src/low/msp-asm/relic_fb_add_low.s
@@ -1,6 +1,6 @@
/*
* RELIC is an Efficient LIbrary for Cryptography
- * Copyright (c) 2007, 2008, 2009 RELIC Authors
+ * Copyright (c) 2012 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
diff --git a/contrib/relic/src/low/msp-asm/relic_fb_mul_low.c b/contrib/relic/src/low/msp-asm/relic_fb_mul_low.c
index d1c64a96b..b79bdda9d 100644
--- a/contrib/relic/src/low/msp-asm/relic_fb_mul_low.c
+++ b/contrib/relic/src/low/msp-asm/relic_fb_mul_low.c
@@ -1,6 +1,6 @@
/*
* RELIC is an Efficient LIbrary for Cryptography
- * Copyright (c) 2007, 2008, 2009 RELIC Authors
+ * Copyright (c) 2012 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
diff --git a/contrib/relic/src/low/msp-asm/relic_fb_rdc_low.c b/contrib/relic/src/low/msp-asm/relic_fb_rdc_low.c
index 786ccce0f..9c6567d4e 100644
--- a/contrib/relic/src/low/msp-asm/relic_fb_rdc_low.c
+++ b/contrib/relic/src/low/msp-asm/relic_fb_rdc_low.c
@@ -1,6 +1,6 @@
/*
* RELIC is an Efficient LIbrary for Cryptography
- * Copyright (c) 2007, 2008, 2009 RELIC Authors
+ * Copyright (c) 2012 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
diff --git a/contrib/relic/src/low/msp-asm/relic_fb_shift_low.c b/contrib/relic/src/low/msp-asm/relic_fb_shift_low.c
index cf8a71aa9..593445682 100644
--- a/contrib/relic/src/low/msp-asm/relic_fb_shift_low.c
+++ b/contrib/relic/src/low/msp-asm/relic_fb_shift_low.c
@@ -1,6 +1,6 @@
/*
* RELIC is an Efficient LIbrary for Cryptography
- * Copyright (c) 2007, 2008, 2009 RELIC Authors
+ * Copyright (c) 2012 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
diff --git a/contrib/relic/src/low/msp-asm/relic_fb_sqr_low.c b/contrib/relic/src/low/msp-asm/relic_fb_sqr_low.c
index 2f54af0b9..5cfac64c4 100644
--- a/contrib/relic/src/low/msp-asm/relic_fb_sqr_low.c
+++ b/contrib/relic/src/low/msp-asm/relic_fb_sqr_low.c
@@ -1,6 +1,6 @@
/*
* RELIC is an Efficient LIbrary for Cryptography
- * Copyright (c) 2007, 2008, 2009 RELIC Authors
+ * Copyright (c) 2012 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
diff --git a/contrib/relic/src/low/msp-asm/relic_fb_sqr_low.s b/contrib/relic/src/low/msp-asm/relic_fb_sqr_low.s
index 168cf7234..eb3a89c24 100644
--- a/contrib/relic/src/low/msp-asm/relic_fb_sqr_low.s
+++ b/contrib/relic/src/low/msp-asm/relic_fb_sqr_low.s
@@ -1,6 +1,6 @@
/*
* RELIC is an Efficient LIbrary for Cryptography
- * Copyright (c) 2007, 2008, 2009 RELIC Authors
+ * Copyright (c) 2012 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
diff --git a/contrib/relic/src/low/msp-asm/relic_fb_srt_low.c b/contrib/relic/src/low/msp-asm/relic_fb_srt_low.c
index d8f7873d3..a2d0195a0 100644
--- a/contrib/relic/src/low/msp-asm/relic_fb_srt_low.c
+++ b/contrib/relic/src/low/msp-asm/relic_fb_srt_low.c
@@ -1,6 +1,6 @@
/*
* RELIC is an Efficient LIbrary for Cryptography
- * Copyright (c) 2007, 2008, 2009 RELIC Authors
+ * Copyright (c) 2012 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
@@ -289,7 +289,7 @@ const uint8_t fb_srt_table_evens[256] = { 0, 1, 16, 17, 2, 3, 18, 19, 32, 33,
const uint8_t fb_srt_table_odds[256] = { 0, 16, 1, 17, 32, 48, 33, 49, 2, 18, 3,
19, 34, 50, 35, 51, 64, 80, 65, 81, 96, 112, 97, 113, 66, 82, 67, 83, 98,
114, 99, 115, 4, 20, 5, 21, 36, 52, 37, 53, 6, 22, 7, 23, 38, 54, 39, 55,
- 68, 84, 69, 85, 100, 116, 101, 117, 70, 86, 71, 87, 102, 118, 103, 119, 128,
+ 68, 84, 69, 85, 100, 116, 101, 117, 70, 86, 71, 87, 102, 118, 103, 119, 128,
144, 129, 145, 160, 176, 161, 177, 130, 146, 131, 147, 162, 178, 163, 179,
192, 208, 193, 209, 224, 240, 225, 241, 194, 210, 195, 211, 226, 242, 227,
243, 132, 148, 133, 149, 164, 180, 165, 181, 134, 150, 135, 151, 166, 182,
@@ -303,4 +303,4 @@ const uint8_t fb_srt_table_odds[256] = { 0, 16, 1, 17, 32, 48, 33, 49, 2, 18, 3,
141, 157, 172, 188, 173, 189, 142, 158, 143, 159, 174, 190, 175, 191, 204,
220, 205, 221, 236, 252, 237, 253, 206, 222, 207, 223, 238, 254, 239, 255 };
-#endif
\ No newline at end of file
+#endif
diff --git a/contrib/relic/src/low/msp-asm/relic_fp_add_low.c b/contrib/relic/src/low/msp-asm/relic_fp_add_low.c
index 0313295f6..02d8c22ca 100644
--- a/contrib/relic/src/low/msp-asm/relic_fp_add_low.c
+++ b/contrib/relic/src/low/msp-asm/relic_fp_add_low.c
@@ -1,6 +1,6 @@
/*
* RELIC is an Efficient LIbrary for Cryptography
- * Copyright (c) 2007, 2008, 2009 RELIC Authors
+ * Copyright (c) 2012 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
diff --git a/contrib/relic/src/low/msp-asm/relic_fp_inv_low.c b/contrib/relic/src/low/msp-asm/relic_fp_inv_low.c
index b111c90f4..5b94516d7 100644
--- a/contrib/relic/src/low/msp-asm/relic_fp_inv_low.c
+++ b/contrib/relic/src/low/msp-asm/relic_fp_inv_low.c
@@ -1,6 +1,6 @@
/*
* RELIC is an Efficient LIbrary for Cryptography
- * Copyright (c) 2007, 2008, 2009 RELIC Authors
+ * Copyright (c) 2012 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
diff --git a/contrib/relic/src/low/msp-asm/relic_fpx_add_low.c b/contrib/relic/src/low/msp-asm/relic_fpx_add_low.c
index 0efe96e46..be614e595 100644
--- a/contrib/relic/src/low/msp-asm/relic_fpx_add_low.c
+++ b/contrib/relic/src/low/msp-asm/relic_fpx_add_low.c
@@ -1,6 +1,6 @@
/*
* RELIC is an Efficient LIbrary for Cryptography
- * Copyright (c) 2007-2011 RELIC Authors
+ * Copyright (c) 2014 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
diff --git a/contrib/relic/src/low/x64-asm-254/relic_fp_inv_low.s b/contrib/relic/src/low/x64-asm-254/relic_fp_inv_low.s
deleted file mode 100644
index 76124434f..000000000
--- a/contrib/relic/src/low/x64-asm-254/relic_fp_inv_low.s
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- * RELIC is an Efficient LIbrary for Cryptography
- * Copyright (c) 2013 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 inversion functions.
- *
- * @&version $Id$
- * @ingroup fp
- */
-
-#include "macro.s"
-
-/*============================================================================*/
-/* Public definitions */
-/*============================================================================*/
-
-/* No carry */
-.macro DBLN R
- addq %rdi,%rdi
- adcq %rdx,%rdx
- adcq %rsi,%rsi
- adcq %rcx,%rcx
-.endm
-
-.macro DBLN2 R
- addq %rdi,%rdi
- adcq %rdx,%rdx
-.endm
-
-.macro DBLN3 R
- addq %rdi,%rdi
- adcq %rdx,%rdx
- adcq %rsi,%rsi
-.endm
-
-#define P0 $0xA700000000000013
-#define P1 $0x6121000000000013
-#define P2 $0xBA344D8000000008
-#define P3 $0x2523648240000001
-
-#define Q3 $0x1B0A32FDF6403A3D
-#define Q2 $0x281E3A1B7F86954F
-#define Q1 $0x55EFBF6E8C1CC3F1
-#define Q0 $0xB3E886745370473D
-
-#define R0 $0x15FFFFFFFFFFFF8E
-#define R1 $0xB939FFFFFFFFFF8A
-#define R2 $0xA2C62EFFFFFFFFCD
-#define R3 $0x212BA4F27FFFFFF5
-
-.global cdecl(fp_invn_asm)
-
-/**
- * rdi = a, rsi = x1, rdx = c
- */
-cdecl(fp_invn_asm):
- push %r12
- push %r13
- push %r14
- push %r15
- push %rbp
- push %rbx
- push %rdi
- subq $96, %rsp
-
- xorq %rax, %rax
- movq P0,%r12
- movq P1,%r13
- movq P2,%r14
- movq P3,%r15
-
- movq 0(%rsi),%rbp
- movq 8(%rsi),%rbx
- movq 16(%rsi),%rcx
- movq 24(%rsi),%rsi
-
- movq R0,%r8
- movq %r8,0(%rdx)
- movq R1,%r9
- movq %r9,8(%rdx)
- movq R2,%r10
- movq %r10,16(%rdx)
- movq R3,%r11
- movq %r11,24(%rdx)
-
- movq $1,%rdi
- xorq %r8, %r8
- xorq %r9, %r9
- xorq %r10, %r10
- xorq %rdx, %rdx
-
-loop:
- movq %r15,%r11
- orq %rsi,%r11
- jz loop2
- inc %rax
- test $1, %r12
- jnz v_odd
- shrd $1, %r13, %r12
- shrd $1, %r14, %r13
- shrd $1, %r15, %r14
- shr $1, %r15
- DBLN2 %rsp
- jmp loop
-v_odd:
- test $1, %rbp
- jnz u_odd
- shrd $1, %rbx, %rbp
- shrd $1, %rcx, %rbx
- shrd $1, %rsi, %rcx
- shr $1, %rsi
- addq %r8,%r8
- adcq %r9,%r9
- jmp loop
-u_odd:
- subq %rbp, %r12
- sbbq %rbx, %r13
- sbbq %rcx, %r14
- sbbq %rsi, %r15
- jc cmp_lt
- shrd $1, %r13, %r12
- shrd $1, %r14, %r13
- shrd $1, %r15, %r14
- shr $1, %r15
- addq %rdi,%r8
- adcq %rdx,%r9
- DBLN2 %rsp
- jmp loop
-cmp_lt:
- addq %rbp, %r12
- adcq %rbx, %r13
- adcq %rcx, %r14
- adcq %rsi, %r15
- subq %r12, %rbp
- sbbq %r13, %rbx
- sbbq %r14, %rcx
- sbbq %r15, %rsi
- shrd $1, %rbx, %rbp
- shrd $1, %rcx, %rbx
- shrd $1, %rsi, %rcx
- shr $1, %rsi
- addq %r8,%rdi
- adcq %r9,%rdx
- addq %r8,%r8
- adcq %r9,%r9
- jmp loop
-
-loop2:
- movq %r14,%r11
- orq %rcx,%r11
- jz loop3
- inc %rax
- test $1, %r12
- jnz v_odd2
- shrd $1, %r13, %r12
- shrd $1, %r14, %r13
- shr $1, %r14
- DBLN3 %rsp
- jmp loop2
-v_odd2:
- test $1, %rbp
- jnz u_odd2
- shrd $1, %rbx, %rbp
- shrd $1, %rcx, %rbx
- shr $1, %rcx
- addq %r8,%r8
- adcq %r9,%r9
- adcq %r10,%r10
- jmp loop2
-u_odd2:
- subq %rbp, %r12
- sbbq %rbx, %r13
- sbbq %rcx, %r14
- jc cmp_lt2
- shrd $1, %r13, %r12
- shrd $1, %r14, %r13
- shr $1, %r14
- addq %rdi,%r8
- adcq %rdx,%r9
- adcq %rsi,%r10
- DBLN3 %rsp
- jmp loop2
-cmp_lt2:
- addq %rbp, %r12
- adcq %rbx, %r13
- adcq %rcx, %r14
- subq %r12, %rbp
- sbbq %r13, %rbx
- sbbq %r14, %rcx
- shrd $1, %rbx, %rbp
- shrd $1, %rcx, %rbx
- shr $1, %rcx
- addq %r8,%rdi
- adcq %r9,%rdx
- adcq %r10,%rsi
- addq %r8,%r8
- adcq %r9,%r9
- adcq %r10,%r10
- jmp loop2
-
-loop3:
- movq %r13,%r11
- orq %rbx,%r11
- jz loop4
- inc %rax
- test $1, %r12
- jnz v_odd3
- shrd $1, %r13, %r12
- shr $1, %r13
- DBLN %rsp
- jmp loop3
-v_odd3:
- test $1, %rbp
- jnz u_odd3
- shrd $1, %rbx, %rbp
- shr $1, %rbx
- addq %r8,%r8
- adcq %r9,%r9
- adcq %r10,%r10
- adcq %r15,%r15
- jmp loop3
-u_odd3:
- subq %rbp, %r12
- sbbq %rbx, %r13
- jc cmp_lt3
- shrd $1, %r13, %r12
- shr $1, %r13
- addq %rdi,%r8
- adcq %rdx,%r9
- adcq %rsi,%r10
- adcq %rcx,%r15
- DBLN %rsp
- jmp loop3
-cmp_lt3:
- addq %rbp, %r12
- adcq %rbx, %r13
- subq %r12, %rbp
- sbbq %r13, %rbx
- shrd $1, %rbx, %rbp
- shr $1, %rbx
- addq %r8,%rdi
- adcq %r9,%rdx
- adcq %r10,%rsi
- adcq %r15,%rcx
- addq %r8,%r8
- adcq %r9,%r9
- adcq %r10,%r10
- adcq %r15,%r15
- jmp loop3
-
-loop4:
- movq %r12,%r11
- orq %r12,%r11
- jz end
- inc %rax
- test $1, %r12
- jnz v_odd4
- shr $1, %r12
- DBLN %rsp
- jmp loop4
-v_odd4:
- test $1, %rbp
- jnz u_odd4
- shrd $1, %rbx, %rbp
- shr $1, %rbx
- addq %r8,%r8
- adcq %r9,%r9
- adcq %r10,%r10
- adcq %r15,%r15
- jmp loop4
-u_odd4:
- subq %rbp, %r12
- jc cmp_lt4
- shr $1, %r12
- addq %rdi,%r8
- adcq %rdx,%r9
- adcq %rsi,%r10
- adcq %rcx,%r15
- DBLN %rsp
- jmp loop4
-cmp_lt4:
- addq %rbp, %r12
- subq %r12, %rbp
- shr $1, %rbp
- addq %r8,%rdi
- adcq %r9,%rdx
- adcq %r10,%rsi
- adcq %r15,%rcx
- addq %r8,%r8
- adcq %r9,%r9
- adcq %r10,%r10
- adcq %r15,%r15
- jmp loop4
-
-end:
- movq Q0,%r12
- movq Q1,%r13
- movq Q2,%r14
- movq Q3,%r15
- movq %rax,%rbx
- movq %rsp,%rbp
- movq %rdx,0(%rsp)
- addq $32,%rbp
- FP_MULN_LOW %rbp, %r8, %r9, %r10, %rdi, 0(%rsp), %rsi, %rcx, %r12, %r13, %r14, %r15
- addq $96, %rsp
- pop %rdi
- FP_RDCN_LOW %rdi, %rbp
- movq %rbx,%rax
-exit:
- pop %rbx
- pop %rbp
- pop %r15
- pop %r14
- pop %r13
- pop %r12
- ret
diff --git a/contrib/relic/src/low/x64-asm-254/CMakeLists.txt b/contrib/relic/src/low/x64-asm-4l/CMakeLists.txt
similarity index 100%
rename from contrib/relic/src/low/x64-asm-254/CMakeLists.txt
rename to contrib/relic/src/low/x64-asm-4l/CMakeLists.txt
diff --git a/contrib/relic/src/low/x64-asm-254/macro.s b/contrib/relic/src/low/x64-asm-4l/macro.s
similarity index 68%
rename from contrib/relic/src/low/x64-asm-254/macro.s
rename to contrib/relic/src/low/x64-asm-4l/macro.s
index 7f4e9558b..c6f836230 100755
--- a/contrib/relic/src/low/x64-asm-254/macro.s
+++ b/contrib/relic/src/low/x64-asm-4l/macro.s
@@ -31,12 +31,24 @@
* @ingroup fp
*/
+#if FP_PRIME == 254
+
#define P0 $0xA700000000000013
#define P1 $0x6121000000000013
#define P2 $0xBA344D8000000008
#define P3 $0x2523648240000001
#define U0 $0x08435E50D79435E5
+#elif FP_PRIME == 255
+
+#define P0 $0xFFFFFFFFFFFFFFED
+#define P1 $0xFFFFFFFFFFFFFFFF
+#define P2 $0xFFFFFFFFFFFFFFFF
+#define P3 $0x7FFFFFFFFFFFFFFF
+#define U0 $0x86BCA1AF286BCA1B
+
+#endif
+
#define NP40 $0xC000000000000000
#define NP41 $0xE9C0000000000004
#define NP42 $0x1848400000000004
@@ -102,6 +114,8 @@
.endif
.endm
+#if FP_PRIME == 254
+
/* Montgomery reduction, comba, optimized for BN254 */
.macro FP_RDCN_LOW C, A
xorq %r10, %r10
@@ -253,6 +267,166 @@
movq %rcx,24(\C)
.endm
+#else
+
+/* Montgomery reduction, comba, optimized for BN254 */
+.macro FP_RDCN_LOW C, A
+ xorq %r10, %r10
+ movq U0, %rcx
+// i=0
+ movq 0(\A), %r8
+ movq %r8, %rax
+ mulq %rcx // v*U0
+ movq %rax, %r14
+ movq P0, %r11
+ mulq %r11 // z0*m0
+ addq %rax,%r8
+ movq P1, %r12
+ adcq 8(\A),%rdx
+ movq %rdx,%r9
+ adcq $0,%r10
+// i=1, j=0
+ movq %r14, %rax
+ mulq %r12 // z0*m1
+ addq %rax,%r9
+ movq %r9, %rax
+ adcq %rdx,%r10
+
+ mulq %rcx // v*U0
+ movq %rax, 8(\A)
+ xorq %r8,%r8
+ mulq %r11 // z1*m0
+ addq %rax,%r9
+ movq P2, %r13
+ adcq %rdx,%r10
+ adcq $0,%r8
+// i=2, j=0,1
+ movq %r14, %rax
+ mulq %r13 // z0*m2
+ addq 16(\A),%r10
+ adcq $0,%r8
+
+ addq %rax,%r10
+ adcq %rdx,%r8
+
+ xorq %r9,%r9
+ movq 8(\A), %rax
+ mulq %r12 // z1*m1
+ addq %rax,%r10
+ adcq %rdx,%r8
+ adcq $0,%r9
+ movq %r10, %rax
+ mulq %rcx // v*U0
+ movq %rax, 16(\A)
+ mulq %r11 // z2*m0
+ addq %rax,%r10
+ movq %r14, %rax
+ adcq %rdx,%r8
+ movq P3, %r14
+ adcq $0,%r9
+// i=3, j=0,1,2
+ mulq %r14 // z0*m3
+ addq 24(\A),%r8
+ adcq $0,%r9
+
+ xorq %r10, %r10
+ addq %rax,%r8
+ adcq %rdx,%r9
+ adcq $0,%r10
+
+ movq 8(\A), %rax
+ mulq %r13 // z1*m2
+ addq %rax,%r8
+ movq 16(\A), %rax
+ adcq %rdx,%r9
+ adcq $0,%r10
+
+ mulq %r12 // z2*m1
+ addq %rax,%r8
+ movq %r8, %rax
+ adcq %rdx,%r9
+ adcq $0,%r10
+
+ mulq %rcx // v*U0
+ movq %rax, 24(\A)
+ mulq %r11 // z3*m0
+ addq %rax,%r8
+ adcq %rdx,%r9
+ adcq $0,%r10
+// loop 2
+// i=4, j=1,2,3
+ movq 8(\A), %rax
+ mulq %r14 // z1*m3
+ addq 32(\A),%r9
+ adcq $0,%r10
+
+ xorq %r8, %r8
+ addq %rax,%r9
+ adcq %rdx,%r10
+ adcq $0,%r8
+
+ movq 16(\A), %rax
+ mulq %r13 // z2*m2
+ addq %rax,%r9
+ adcq %rdx,%r10
+ adcq $0,%r8
+ movq 24(\A), %rax
+
+ mulq %r12 // z3*m1
+ addq %rax,%r9
+ adcq %rdx,%r10
+ movq %r9,%r12 // Z0
+ adcq $0,%r8
+// i=5, j=2,3
+ xorq %r11, %r11
+ movq 16(\A), %rax
+ mulq %r14 // z2*m3
+ addq %rax,%r10
+ adcq %rdx,%r8
+ adcq $0,%r11
+
+ movq 24(\A), %rax
+ mulq %r13 // z3*m2
+ addq %rax,%r10
+ adcq %rdx,%r8
+ adcq $0,%r11
+
+ addq 40(\A),%r10
+ movq %r10,%r13 // Z1
+ adcq $0,%r8
+// i=6, j=3
+ movq 24(\A), %rax
+ mulq %r14 // z3*m3
+ addq %rax,%r8
+ adcq %rdx,%r11
+
+ addq 48(\A),%r8
+ movq %r8,%r14 // Z2
+ adcq $0,%r11
+
+ addq 56(\A),%r11
+ movq %r11,%rcx // Z3
+
+ movq P0,%rax
+ subq %rax,%r9
+ movq P1,%rax
+ sbbq %rax,%r10
+ movq P2,%rax
+ sbbq %rax,%r8
+ movq P3,%rax
+ sbbq %rax,%r11
+ cmovnc %r9,%r12
+ movq %r12,0(\C)
+ cmovnc %r10,%r13
+ movq %r13,8(\C)
+ cmovnc %r8,%r14
+ movq %r14,16(\C)
+ cmovnc %r11,%rcx
+ movq %rcx,24(\C)
+.endm
+
+#endif
+
.macro FP_MULN_LOW C, R0, R1, R2, A0, A1, A2, A3, B0, B1, B2, B3
movq \A0,%rax
mulq \B0
diff --git a/contrib/relic/src/low/x64-asm-254/relic_fp_add_low.s b/contrib/relic/src/low/x64-asm-4l/relic_fp_add_low.s
similarity index 96%
rename from contrib/relic/src/low/x64-asm-254/relic_fp_add_low.s
rename to contrib/relic/src/low/x64-asm-4l/relic_fp_add_low.s
index b2f18b111..ab2ae7fa3 100755
--- a/contrib/relic/src/low/x64-asm-254/relic_fp_add_low.s
+++ b/contrib/relic/src/low/x64-asm-4l/relic_fp_add_low.s
@@ -35,6 +35,7 @@
#include "macro.s"
.text
+
.global cdecl(fp_add1_low)
.global cdecl(fp_addn_low)
.global cdecl(fp_addm_low)
@@ -289,27 +290,31 @@ cdecl(fp_subd_low):
ret
cdecl(fp_negm_low):
- movq 0(%rsi) , %r8
- or 8(%rsi) , %r8
- or 16(%rsi), %r8
- or 24(%rsi), %r8
+ xorq %rax, %rax
mov P0, %rcx
mov P1, %r9
mov P2, %r10
mov P3, %r11
+ subq 0(%rsi) , %rcx
+ sbbq 8(%rsi) , %r9
+ sbbq 16(%rsi) , %r10
+ sbbq 24(%rsi) , %r11
+
+ movq 0(%rsi) , %r8
+ or 8(%rsi) , %r8
+ or 16(%rsi), %r8
+ or 24(%rsi), %r8
test %r8, %r8
- cmovnz %rcx , %r8
- subq 0(%rsi) , %r8
- movq %r8 , 0(%rdi)
- cmovnz %r9 , %r8
- sbbq 8(%rsi) , %r8
- movq %r8 , 8(%rdi)
- cmovnz %r10 , %r8
- sbbq 16(%rsi), %r8
- movq %r8 , 16(%rdi)
- cmovnz %r11 , %r8
- sbbq 24(%rsi), %r8
- movq %r8 , 24(%rdi)
+
+ cmovnz %rcx, %rax
+ movq %rax, 0(%rdi)
+ cmovnz %r9, %rax
+ movq %rax, 8(%rdi)
+ cmovnz %r10, %rax
+ movq %rax, 16(%rdi)
+ cmovnz %r11, %rax
+ movq %rax, 24(%rdi)
+
ret
cdecl(fp_dbln_low):
diff --git a/contrib/relic/src/low/x64-asm-382/relic_fp_inv_low.c b/contrib/relic/src/low/x64-asm-4l/relic_fp_inv_low.c
similarity index 100%
rename from contrib/relic/src/low/x64-asm-382/relic_fp_inv_low.c
rename to contrib/relic/src/low/x64-asm-4l/relic_fp_inv_low.c
diff --git a/contrib/relic/src/low/x64-asm-254/relic_fp_mul_low.c b/contrib/relic/src/low/x64-asm-4l/relic_fp_mul_low.c
similarity index 100%
rename from contrib/relic/src/low/x64-asm-254/relic_fp_mul_low.c
rename to contrib/relic/src/low/x64-asm-4l/relic_fp_mul_low.c
diff --git a/contrib/relic/src/low/x64-asm-254/relic_fp_mul_low.s b/contrib/relic/src/low/x64-asm-4l/relic_fp_mul_low.s
similarity index 100%
rename from contrib/relic/src/low/x64-asm-254/relic_fp_mul_low.s
rename to contrib/relic/src/low/x64-asm-4l/relic_fp_mul_low.s
diff --git a/contrib/relic/src/low/x64-asm-254/relic_fp_rdc_low.c b/contrib/relic/src/low/x64-asm-4l/relic_fp_rdc_low.c
similarity index 100%
rename from contrib/relic/src/low/x64-asm-254/relic_fp_rdc_low.c
rename to contrib/relic/src/low/x64-asm-4l/relic_fp_rdc_low.c
diff --git a/contrib/relic/src/low/x64-asm-254/relic_fp_rdc_low.s b/contrib/relic/src/low/x64-asm-4l/relic_fp_rdc_low.s
similarity index 100%
rename from contrib/relic/src/low/x64-asm-254/relic_fp_rdc_low.s
rename to contrib/relic/src/low/x64-asm-4l/relic_fp_rdc_low.s
diff --git a/contrib/relic/src/low/x64-asm-254/relic_fp_shift_low.c b/contrib/relic/src/low/x64-asm-4l/relic_fp_shift_low.c
similarity index 100%
rename from contrib/relic/src/low/x64-asm-254/relic_fp_shift_low.c
rename to contrib/relic/src/low/x64-asm-4l/relic_fp_shift_low.c
diff --git a/contrib/relic/src/low/x64-asm-254/relic_fp_shift_low.s b/contrib/relic/src/low/x64-asm-4l/relic_fp_shift_low.s
similarity index 99%
rename from contrib/relic/src/low/x64-asm-254/relic_fp_shift_low.s
rename to contrib/relic/src/low/x64-asm-4l/relic_fp_shift_low.s
index 595f5175a..1ecfc09e9 100755
--- a/contrib/relic/src/low/x64-asm-254/relic_fp_shift_low.s
+++ b/contrib/relic/src/low/x64-asm-4l/relic_fp_shift_low.s
@@ -45,7 +45,6 @@ cdecl(fp_rsh1_low):
ret
cdecl(fp_lsh1_low):
-fp_lsh1_low:
movq 0(%rsi), %r8
movq 8(%rsi), %r9
movq 16(%rsi), %r10
diff --git a/contrib/relic/src/low/x64-asm-254/relic_fp_sqr_low.c b/contrib/relic/src/low/x64-asm-4l/relic_fp_sqr_low.c
similarity index 100%
rename from contrib/relic/src/low/x64-asm-254/relic_fp_sqr_low.c
rename to contrib/relic/src/low/x64-asm-4l/relic_fp_sqr_low.c
diff --git a/contrib/relic/src/low/x64-asm-254/relic_fp_sqr_low.s b/contrib/relic/src/low/x64-asm-4l/relic_fp_sqr_low.s
similarity index 100%
rename from contrib/relic/src/low/x64-asm-254/relic_fp_sqr_low.s
rename to contrib/relic/src/low/x64-asm-4l/relic_fp_sqr_low.s
diff --git a/contrib/relic/src/low/x64-asm-254/relic_fpx_add_low.c b/contrib/relic/src/low/x64-asm-4l/relic_fpx_add_low.c
similarity index 100%
rename from contrib/relic/src/low/x64-asm-254/relic_fpx_add_low.c
rename to contrib/relic/src/low/x64-asm-4l/relic_fpx_add_low.c
diff --git a/contrib/relic/src/low/x64-asm-254/relic_fpx_add_low.s b/contrib/relic/src/low/x64-asm-4l/relic_fpx_add_low.s
similarity index 100%
rename from contrib/relic/src/low/x64-asm-254/relic_fpx_add_low.s
rename to contrib/relic/src/low/x64-asm-4l/relic_fpx_add_low.s
diff --git a/contrib/relic/src/low/x64-asm-254/relic_fpx_mul_low.c b/contrib/relic/src/low/x64-asm-4l/relic_fpx_mul_low.c
similarity index 100%
rename from contrib/relic/src/low/x64-asm-254/relic_fpx_mul_low.c
rename to contrib/relic/src/low/x64-asm-4l/relic_fpx_mul_low.c
diff --git a/contrib/relic/src/low/x64-asm-254/relic_fpx_mul_low.s b/contrib/relic/src/low/x64-asm-4l/relic_fpx_mul_low.s
similarity index 100%
rename from contrib/relic/src/low/x64-asm-254/relic_fpx_mul_low.s
rename to contrib/relic/src/low/x64-asm-4l/relic_fpx_mul_low.s
diff --git a/contrib/relic/src/low/x64-asm-254/relic_fpx_rdc_low.c b/contrib/relic/src/low/x64-asm-4l/relic_fpx_rdc_low.c
similarity index 100%
rename from contrib/relic/src/low/x64-asm-254/relic_fpx_rdc_low.c
rename to contrib/relic/src/low/x64-asm-4l/relic_fpx_rdc_low.c
diff --git a/contrib/relic/src/low/x64-asm-254/relic_fpx_rdc_low.s b/contrib/relic/src/low/x64-asm-4l/relic_fpx_rdc_low.s
similarity index 100%
rename from contrib/relic/src/low/x64-asm-254/relic_fpx_rdc_low.s
rename to contrib/relic/src/low/x64-asm-4l/relic_fpx_rdc_low.s
diff --git a/contrib/relic/src/low/x64-asm-254/relic_fpx_sqr_low.c b/contrib/relic/src/low/x64-asm-4l/relic_fpx_sqr_low.c
similarity index 100%
rename from contrib/relic/src/low/x64-asm-254/relic_fpx_sqr_low.c
rename to contrib/relic/src/low/x64-asm-4l/relic_fpx_sqr_low.c
diff --git a/contrib/relic/src/low/x64-asm-254/relic_fpx_sqr_low.s b/contrib/relic/src/low/x64-asm-4l/relic_fpx_sqr_low.s
similarity index 100%
rename from contrib/relic/src/low/x64-asm-254/relic_fpx_sqr_low.s
rename to contrib/relic/src/low/x64-asm-4l/relic_fpx_sqr_low.s
diff --git a/contrib/relic/src/low/x64-asm-382/CMakeLists.txt b/contrib/relic/src/low/x64-asm-6l/CMakeLists.txt
similarity index 100%
rename from contrib/relic/src/low/x64-asm-382/CMakeLists.txt
rename to contrib/relic/src/low/x64-asm-6l/CMakeLists.txt
diff --git a/contrib/relic/src/low/x64-asm-382/macro.s b/contrib/relic/src/low/x64-asm-6l/macro.s
similarity index 95%
rename from contrib/relic/src/low/x64-asm-382/macro.s
rename to contrib/relic/src/low/x64-asm-6l/macro.s
index 9c1dfb375..e477e69ed 100644
--- a/contrib/relic/src/low/x64-asm-382/macro.s
+++ b/contrib/relic/src/low/x64-asm-6l/macro.s
@@ -40,7 +40,7 @@
#define P4 0x4B1BA7B6434BACD7
#define P5 0x1A0111EA397FE69A
#define U0 0x89F3FFFCFFFCFFFD
-#else
+#elif FP_PRIME == 382
#define P0 0x004E000000000013
#define P1 0x09480097801382BE
#define P2 0xA6E58DBE43002A06
@@ -48,6 +48,14 @@
#define P4 0x2D996CC179C6D166
#define P5 0x24009015183F9489
#define U0 0xDF615E50D79435E5
+#elif FP_PRIME == 383
+#define P0 0xDA371D6485AAB0AB
+#define P1 0x7A8C3F298A64852B
+#define P2 0xAC31B801696124F4
+#define P3 0xA0AD462CF365A511
+#define P4 0xA06DADC41FEA9284
+#define P5 0x5565569564AB6EB5
+#define U0 0x69BC0571073435FD
#endif
.text
diff --git a/contrib/relic/src/low/x64-asm-382/relic_fp_add_low.s b/contrib/relic/src/low/x64-asm-6l/relic_fp_add_low.s
similarity index 99%
rename from contrib/relic/src/low/x64-asm-382/relic_fp_add_low.s
rename to contrib/relic/src/low/x64-asm-6l/relic_fp_add_low.s
index 0c9565a6c..d49e8438f 100644
--- a/contrib/relic/src/low/x64-asm-382/relic_fp_add_low.s
+++ b/contrib/relic/src/low/x64-asm-6l/relic_fp_add_low.s
@@ -51,6 +51,8 @@ p5: .quad P5
.global p4
.global p5
+#if OPSYS != WINDOWS
+
.hidden p0
.hidden p1
.hidden p2
@@ -58,6 +60,8 @@ p5: .quad P5
.hidden p4
.hidden p5
+#endif
+
.text
.global fp_add1_low
diff --git a/contrib/relic/src/low/x64-asm-6l/relic_fp_inv_low.c b/contrib/relic/src/low/x64-asm-6l/relic_fp_inv_low.c
new file mode 100644
index 000000000..b3276603e
--- /dev/null
+++ b/contrib/relic/src/low/x64-asm-6l/relic_fp_inv_low.c
@@ -0,0 +1,70 @@
+/*
+ * 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 inversion functions.
+ *
+ * @&version $Id$
+ * @ingroup fp
+ */
+
+#include
+
+#include "relic_fp.h"
+#include "relic_fp_low.h"
+#include "relic_core.h"
+
+/*============================================================================*/
+/* Public definitions */
+/*============================================================================*/
+
+void fp_invm_low(dig_t *c, const dig_t *a) {
+ mp_size_t cn;
+ rlc_align dig_t s[RLC_FP_DIGS], t[2 * RLC_FP_DIGS], u[RLC_FP_DIGS + 1];
+
+#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
+
+ dv_copy(s, fp_prime_get(), RLC_FP_DIGS);
+
+ mpn_gcdext(t, c, &cn, u, RLC_FP_DIGS, s, RLC_FP_DIGS);
+ if (cn < 0) {
+ dv_zero(c - cn, RLC_FP_DIGS + cn);
+ mpn_sub_n(c, fp_prime_get(), c, RLC_FP_DIGS);
+ } else {
+ dv_zero(c + cn, RLC_FP_DIGS - cn);
+ }
+
+#if FP_RDC == MONTY
+ dv_zero(t, RLC_FP_DIGS);
+ dv_copy(t + RLC_FP_DIGS, c, RLC_FP_DIGS);
+ mpn_tdiv_qr(u, c, 0, t, 2 * RLC_FP_DIGS, fp_prime_get(), RLC_FP_DIGS);
+#endif
+}
diff --git a/contrib/relic/src/low/x64-asm-382/relic_fp_mul_low.c b/contrib/relic/src/low/x64-asm-6l/relic_fp_mul_low.c
similarity index 100%
rename from contrib/relic/src/low/x64-asm-382/relic_fp_mul_low.c
rename to contrib/relic/src/low/x64-asm-6l/relic_fp_mul_low.c
diff --git a/contrib/relic/src/low/x64-asm-382/relic_fp_mul_low.s b/contrib/relic/src/low/x64-asm-6l/relic_fp_mul_low.s
similarity index 100%
rename from contrib/relic/src/low/x64-asm-382/relic_fp_mul_low.s
rename to contrib/relic/src/low/x64-asm-6l/relic_fp_mul_low.s
diff --git a/contrib/relic/src/low/x64-asm-382/relic_fp_rdc_low.c b/contrib/relic/src/low/x64-asm-6l/relic_fp_rdc_low.c
similarity index 100%
rename from contrib/relic/src/low/x64-asm-382/relic_fp_rdc_low.c
rename to contrib/relic/src/low/x64-asm-6l/relic_fp_rdc_low.c
diff --git a/contrib/relic/src/low/x64-asm-382/relic_fp_rdc_low.s b/contrib/relic/src/low/x64-asm-6l/relic_fp_rdc_low.s
similarity index 100%
rename from contrib/relic/src/low/x64-asm-382/relic_fp_rdc_low.s
rename to contrib/relic/src/low/x64-asm-6l/relic_fp_rdc_low.s
diff --git a/contrib/relic/src/low/x64-asm-382/relic_fp_shift_low.c b/contrib/relic/src/low/x64-asm-6l/relic_fp_shift_low.c
similarity index 100%
rename from contrib/relic/src/low/x64-asm-382/relic_fp_shift_low.c
rename to contrib/relic/src/low/x64-asm-6l/relic_fp_shift_low.c
diff --git a/contrib/relic/src/low/x64-asm-382/relic_fp_shift_low.s b/contrib/relic/src/low/x64-asm-6l/relic_fp_shift_low.s
similarity index 100%
rename from contrib/relic/src/low/x64-asm-382/relic_fp_shift_low.s
rename to contrib/relic/src/low/x64-asm-6l/relic_fp_shift_low.s
diff --git a/contrib/relic/src/low/x64-asm-6l/relic_fp_smb_low.c b/contrib/relic/src/low/x64-asm-6l/relic_fp_smb_low.c
new file mode 100644
index 000000000..d25200282
--- /dev/null
+++ b/contrib/relic/src/low/x64-asm-6l/relic_fp_smb_low.c
@@ -0,0 +1,67 @@
+/*
+ * RELIC is an Efficient LIbrary for Cryptography
+ * Copyright (c) 2021 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 inversion functions.
+ *
+ * @&version $Id$
+ * @ingroup fp
+ */
+
+#include
+
+#include "relic_fp.h"
+#include "relic_fp_low.h"
+#include "relic_core.h"
+
+/*============================================================================*/
+/* Public definitions */
+/*============================================================================*/
+
+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;
+}
diff --git a/contrib/relic/src/low/x64-asm-382/relic_fp_sqr_low.c b/contrib/relic/src/low/x64-asm-6l/relic_fp_sqr_low.c
similarity index 100%
rename from contrib/relic/src/low/x64-asm-382/relic_fp_sqr_low.c
rename to contrib/relic/src/low/x64-asm-6l/relic_fp_sqr_low.c
diff --git a/contrib/relic/src/low/x64-asm-511/CMakeLists.txt b/contrib/relic/src/low/x64-asm-8l/CMakeLists.txt
similarity index 100%
rename from contrib/relic/src/low/x64-asm-511/CMakeLists.txt
rename to contrib/relic/src/low/x64-asm-8l/CMakeLists.txt
diff --git a/contrib/relic/src/low/x64-asm-511/macro.s b/contrib/relic/src/low/x64-asm-8l/macro.s
similarity index 95%
rename from contrib/relic/src/low/x64-asm-511/macro.s
rename to contrib/relic/src/low/x64-asm-8l/macro.s
index 6c966a3a6..af7492df8 100644
--- a/contrib/relic/src/low/x64-asm-511/macro.s
+++ b/contrib/relic/src/low/x64-asm-8l/macro.s
@@ -32,6 +32,7 @@
* @ingroup fp
*/
+#if FP_PRIME == 511
#define P0 0x84DD401C8E4AB001
#define P1 0x98707BD8B8D7F1F5
#define P2 0x9BF81D9D036E1774
@@ -41,6 +42,17 @@
#define P6 0x0000031F8F000000
#define P7 0x4000000000156000
#define U0 0xDF085042554AAFFF
+#else
+#define P0 0xA13D118DB8BFD2AB
+#define P1 0xEE63BD076E8D9300
+#define P2 0xCFCB5C6071BAD3D2
+#define P3 0x626E85BF7C18A0F0
+#define P4 0x32EA0103E01090BB
+#define P5 0xCB8AC8495D187E8C
+#define P6 0xFCEDF2B4F9C0ECF6
+#define P7 0x155556FFFF39CA9B
+#define U0 0x6EFA1180A5FE67FD
+#endif
.text
diff --git a/contrib/relic/src/low/x64-asm-511/relic_fp_add_low.s b/contrib/relic/src/low/x64-asm-8l/relic_fp_add_low.s
similarity index 100%
rename from contrib/relic/src/low/x64-asm-511/relic_fp_add_low.s
rename to contrib/relic/src/low/x64-asm-8l/relic_fp_add_low.s
diff --git a/contrib/relic/src/low/x64-asm-511/relic_fp_inv_low.c b/contrib/relic/src/low/x64-asm-8l/relic_fp_inv_low.c
similarity index 100%
rename from contrib/relic/src/low/x64-asm-511/relic_fp_inv_low.c
rename to contrib/relic/src/low/x64-asm-8l/relic_fp_inv_low.c
diff --git a/contrib/relic/src/low/x64-asm-511/relic_fp_inv_low.s b/contrib/relic/src/low/x64-asm-8l/relic_fp_inv_low.s
similarity index 100%
rename from contrib/relic/src/low/x64-asm-511/relic_fp_inv_low.s
rename to contrib/relic/src/low/x64-asm-8l/relic_fp_inv_low.s
diff --git a/contrib/relic/src/low/x64-asm-511/relic_fp_mul_low.c b/contrib/relic/src/low/x64-asm-8l/relic_fp_mul_low.c
similarity index 100%
rename from contrib/relic/src/low/x64-asm-511/relic_fp_mul_low.c
rename to contrib/relic/src/low/x64-asm-8l/relic_fp_mul_low.c
diff --git a/contrib/relic/src/low/x64-asm-511/relic_fp_mul_low.s b/contrib/relic/src/low/x64-asm-8l/relic_fp_mul_low.s
similarity index 100%
rename from contrib/relic/src/low/x64-asm-511/relic_fp_mul_low.s
rename to contrib/relic/src/low/x64-asm-8l/relic_fp_mul_low.s
diff --git a/contrib/relic/src/low/x64-asm-511/relic_fp_rdc_low.c b/contrib/relic/src/low/x64-asm-8l/relic_fp_rdc_low.c
similarity index 100%
rename from contrib/relic/src/low/x64-asm-511/relic_fp_rdc_low.c
rename to contrib/relic/src/low/x64-asm-8l/relic_fp_rdc_low.c
diff --git a/contrib/relic/src/low/x64-asm-511/relic_fp_rdc_low.s b/contrib/relic/src/low/x64-asm-8l/relic_fp_rdc_low.s
similarity index 100%
rename from contrib/relic/src/low/x64-asm-511/relic_fp_rdc_low.s
rename to contrib/relic/src/low/x64-asm-8l/relic_fp_rdc_low.s
diff --git a/contrib/relic/src/low/x64-asm-511/relic_fp_shift_low.c b/contrib/relic/src/low/x64-asm-8l/relic_fp_shift_low.c
similarity index 100%
rename from contrib/relic/src/low/x64-asm-511/relic_fp_shift_low.c
rename to contrib/relic/src/low/x64-asm-8l/relic_fp_shift_low.c
diff --git a/contrib/relic/src/low/x64-asm-511/relic_fp_shift_low.s b/contrib/relic/src/low/x64-asm-8l/relic_fp_shift_low.s
similarity index 100%
rename from contrib/relic/src/low/x64-asm-511/relic_fp_shift_low.s
rename to contrib/relic/src/low/x64-asm-8l/relic_fp_shift_low.s
diff --git a/contrib/relic/src/low/x64-asm-8l/relic_fp_smb_low.c b/contrib/relic/src/low/x64-asm-8l/relic_fp_smb_low.c
new file mode 100644
index 000000000..d25200282
--- /dev/null
+++ b/contrib/relic/src/low/x64-asm-8l/relic_fp_smb_low.c
@@ -0,0 +1,67 @@
+/*
+ * RELIC is an Efficient LIbrary for Cryptography
+ * Copyright (c) 2021 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 inversion functions.
+ *
+ * @&version $Id$
+ * @ingroup fp
+ */
+
+#include
+
+#include "relic_fp.h"
+#include "relic_fp_low.h"
+#include "relic_core.h"
+
+/*============================================================================*/
+/* Public definitions */
+/*============================================================================*/
+
+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;
+}
diff --git a/contrib/relic/src/low/x64-asm-511/relic_fp_sqr_low.c b/contrib/relic/src/low/x64-asm-8l/relic_fp_sqr_low.c
similarity index 100%
rename from contrib/relic/src/low/x64-asm-511/relic_fp_sqr_low.c
rename to contrib/relic/src/low/x64-asm-8l/relic_fp_sqr_low.c
diff --git a/contrib/relic/src/low/x64-asm-nine/CMakeLists.txt b/contrib/relic/src/low/x64-asm-9l/CMakeLists.txt
similarity index 100%
rename from contrib/relic/src/low/x64-asm-nine/CMakeLists.txt
rename to contrib/relic/src/low/x64-asm-9l/CMakeLists.txt
diff --git a/contrib/relic/src/low/x64-asm-nine/macro.s b/contrib/relic/src/low/x64-asm-9l/macro.s
similarity index 100%
rename from contrib/relic/src/low/x64-asm-nine/macro.s
rename to contrib/relic/src/low/x64-asm-9l/macro.s
diff --git a/contrib/relic/src/low/x64-asm-nine/relic_fp_add_low.s b/contrib/relic/src/low/x64-asm-9l/relic_fp_add_low.s
similarity index 100%
rename from contrib/relic/src/low/x64-asm-nine/relic_fp_add_low.s
rename to contrib/relic/src/low/x64-asm-9l/relic_fp_add_low.s
diff --git a/contrib/relic/src/low/x64-asm-nine/relic_fp_mul_low.c b/contrib/relic/src/low/x64-asm-9l/relic_fp_mul_low.c
similarity index 100%
rename from contrib/relic/src/low/x64-asm-nine/relic_fp_mul_low.c
rename to contrib/relic/src/low/x64-asm-9l/relic_fp_mul_low.c
diff --git a/contrib/relic/src/low/x64-asm-nine/relic_fp_mul_low.s b/contrib/relic/src/low/x64-asm-9l/relic_fp_mul_low.s
similarity index 100%
rename from contrib/relic/src/low/x64-asm-nine/relic_fp_mul_low.s
rename to contrib/relic/src/low/x64-asm-9l/relic_fp_mul_low.s
diff --git a/contrib/relic/src/low/x64-asm-nine/relic_fp_rdc_low.c b/contrib/relic/src/low/x64-asm-9l/relic_fp_rdc_low.c
similarity index 100%
rename from contrib/relic/src/low/x64-asm-nine/relic_fp_rdc_low.c
rename to contrib/relic/src/low/x64-asm-9l/relic_fp_rdc_low.c
diff --git a/contrib/relic/src/low/x64-asm-nine/relic_fp_rdc_low.s b/contrib/relic/src/low/x64-asm-9l/relic_fp_rdc_low.s
similarity index 100%
rename from contrib/relic/src/low/x64-asm-nine/relic_fp_rdc_low.s
rename to contrib/relic/src/low/x64-asm-9l/relic_fp_rdc_low.s
diff --git a/contrib/relic/src/low/x64-asm-9l/relic_fp_smb_low.c b/contrib/relic/src/low/x64-asm-9l/relic_fp_smb_low.c
new file mode 100644
index 000000000..d25200282
--- /dev/null
+++ b/contrib/relic/src/low/x64-asm-9l/relic_fp_smb_low.c
@@ -0,0 +1,67 @@
+/*
+ * RELIC is an Efficient LIbrary for Cryptography
+ * Copyright (c) 2021 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 inversion functions.
+ *
+ * @&version $Id$
+ * @ingroup fp
+ */
+
+#include
+
+#include "relic_fp.h"
+#include "relic_fp_low.h"
+#include "relic_core.h"
+
+/*============================================================================*/
+/* Public definitions */
+/*============================================================================*/
+
+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;
+}
diff --git a/contrib/relic/src/low/x64-asm-nine/relic_fp_sqr_low.c b/contrib/relic/src/low/x64-asm-9l/relic_fp_sqr_low.c
similarity index 100%
rename from contrib/relic/src/low/x64-asm-nine/relic_fp_sqr_low.c
rename to contrib/relic/src/low/x64-asm-9l/relic_fp_sqr_low.c
diff --git a/contrib/relic/src/low/x64-asm-nine/relic_fpx_rdc_low.c b/contrib/relic/src/low/x64-asm-9l/relic_fpx_rdc_low.c
similarity index 100%
rename from contrib/relic/src/low/x64-asm-nine/relic_fpx_rdc_low.c
rename to contrib/relic/src/low/x64-asm-9l/relic_fpx_rdc_low.c
diff --git a/contrib/relic/src/low/x64-asm-nine/relic_fpx_rdc_low.s b/contrib/relic/src/low/x64-asm-9l/relic_fpx_rdc_low.s
similarity index 100%
rename from contrib/relic/src/low/x64-asm-nine/relic_fpx_rdc_low.s
rename to contrib/relic/src/low/x64-asm-9l/relic_fpx_rdc_low.s
diff --git a/contrib/relic/src/md/blake2-impl.h b/contrib/relic/src/md/blake2-impl.h
index 5ac7a430f..c1df82e0c 100644
--- a/contrib/relic/src/md/blake2-impl.h
+++ b/contrib/relic/src/md/blake2-impl.h
@@ -1,22 +1,36 @@
/*
BLAKE2 reference source code package - reference C implementations
- Written in 2012 by Samuel Neves
+ Copyright 2012, Samuel Neves . You may use this under the
+ terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
+ your option. The terms of these licenses can be found at:
- To the extent possible under law, the author(s) have dedicated all copyright
- and related and neighboring rights to this software to the public domain
- worldwide. This software is distributed without any warranty.
+ - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
+ - OpenSSL license : https://www.openssl.org/source/license.html
+ - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
- You should have received a copy of the CC0 Public Domain Dedication along with
- this software. If not, see .
+ More information about the BLAKE2 hash function can be found at
+ https://blake2.net.
*/
-#pragma once
-#ifndef __BLAKE2_IMPL_H__
-#define __BLAKE2_IMPL_H__
+#ifndef BLAKE2_IMPL_H
+#define BLAKE2_IMPL_H
#include
+#include
+
+#if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L)
+ #if defined(_MSC_VER)
+ #define BLAKE2_INLINE __inline
+ #elif defined(__GNUC__)
+ #define BLAKE2_INLINE __inline__
+ #else
+ #define BLAKE2_INLINE
+ #endif
+#else
+ #define BLAKE2_INLINE inline
+#endif
-static inline uint32_t load32( const void *src )
+static BLAKE2_INLINE uint32_t load32( const void *src )
{
#if defined(NATIVE_LITTLE_ENDIAN)
uint32_t w;
@@ -24,15 +38,14 @@ static inline uint32_t load32( const void *src )
return w;
#else
const uint8_t *p = ( const uint8_t * )src;
- uint32_t w = *p++;
- w |= ( uint32_t )( *p++ ) << 8;
- w |= ( uint32_t )( *p++ ) << 16;
- w |= ( uint32_t )( *p++ ) << 24;
- return w;
+ return (( uint32_t )( p[0] ) << 0) |
+ (( uint32_t )( p[1] ) << 8) |
+ (( uint32_t )( p[2] ) << 16) |
+ (( uint32_t )( p[3] ) << 24) ;
#endif
}
-static inline uint64_t load64( const void *src )
+static BLAKE2_INLINE uint64_t load64( const void *src )
{
#if defined(NATIVE_LITTLE_ENDIAN)
uint64_t w;
@@ -40,97 +53,108 @@ static inline uint64_t load64( const void *src )
return w;
#else
const uint8_t *p = ( const uint8_t * )src;
- uint64_t w = *p++;
- w |= ( uint64_t )( *p++ ) << 8;
- w |= ( uint64_t )( *p++ ) << 16;
- w |= ( uint64_t )( *p++ ) << 24;
- w |= ( uint64_t )( *p++ ) << 32;
- w |= ( uint64_t )( *p++ ) << 40;
- w |= ( uint64_t )( *p++ ) << 48;
- w |= ( uint64_t )( *p++ ) << 56;
- return w;
+ return (( uint64_t )( p[0] ) << 0) |
+ (( uint64_t )( p[1] ) << 8) |
+ (( uint64_t )( p[2] ) << 16) |
+ (( uint64_t )( p[3] ) << 24) |
+ (( uint64_t )( p[4] ) << 32) |
+ (( uint64_t )( p[5] ) << 40) |
+ (( uint64_t )( p[6] ) << 48) |
+ (( uint64_t )( p[7] ) << 56) ;
#endif
}
-static inline void store32( void *dst, uint32_t w )
+static BLAKE2_INLINE uint16_t load16( const void *src )
{
#if defined(NATIVE_LITTLE_ENDIAN)
- memcpy(dst, &w, sizeof w);
+ uint16_t w;
+ memcpy(&w, src, sizeof w);
+ return w;
#else
- uint8_t *p = ( uint8_t * )dst;
- *p++ = ( uint8_t )w; w >>= 8;
- *p++ = ( uint8_t )w; w >>= 8;
- *p++ = ( uint8_t )w; w >>= 8;
- *p++ = ( uint8_t )w;
+ const uint8_t *p = ( const uint8_t * )src;
+ return ( uint16_t )((( uint32_t )( p[0] ) << 0) |
+ (( uint32_t )( p[1] ) << 8));
#endif
}
-static inline void store64( void *dst, uint64_t w )
+static BLAKE2_INLINE void store16( void *dst, uint16_t w )
{
#if defined(NATIVE_LITTLE_ENDIAN)
memcpy(dst, &w, sizeof w);
#else
uint8_t *p = ( uint8_t * )dst;
*p++ = ( uint8_t )w; w >>= 8;
- *p++ = ( uint8_t )w; w >>= 8;
- *p++ = ( uint8_t )w; w >>= 8;
- *p++ = ( uint8_t )w; w >>= 8;
- *p++ = ( uint8_t )w; w >>= 8;
- *p++ = ( uint8_t )w; w >>= 8;
- *p++ = ( uint8_t )w; w >>= 8;
*p++ = ( uint8_t )w;
#endif
}
-static inline uint64_t load48( const void *src )
+static BLAKE2_INLINE void store32( void *dst, uint32_t w )
{
- const uint8_t *p = ( const uint8_t * )src;
- uint64_t w = *p++;
- w |= ( uint64_t )( *p++ ) << 8;
- w |= ( uint64_t )( *p++ ) << 16;
- w |= ( uint64_t )( *p++ ) << 24;
- w |= ( uint64_t )( *p++ ) << 32;
- w |= ( uint64_t )( *p++ ) << 40;
- return w;
+#if defined(NATIVE_LITTLE_ENDIAN)
+ memcpy(dst, &w, sizeof w);
+#else
+ uint8_t *p = ( uint8_t * )dst;
+ p[0] = (uint8_t)(w >> 0);
+ p[1] = (uint8_t)(w >> 8);
+ p[2] = (uint8_t)(w >> 16);
+ p[3] = (uint8_t)(w >> 24);
+#endif
}
-static inline void store48( void *dst, uint64_t w )
+static BLAKE2_INLINE void store64( void *dst, uint64_t w )
{
+#if defined(NATIVE_LITTLE_ENDIAN)
+ memcpy(dst, &w, sizeof w);
+#else
uint8_t *p = ( uint8_t * )dst;
- *p++ = ( uint8_t )w; w >>= 8;
- *p++ = ( uint8_t )w; w >>= 8;
- *p++ = ( uint8_t )w; w >>= 8;
- *p++ = ( uint8_t )w; w >>= 8;
- *p++ = ( uint8_t )w; w >>= 8;
- *p++ = ( uint8_t )w;
+ p[0] = (uint8_t)(w >> 0);
+ p[1] = (uint8_t)(w >> 8);
+ p[2] = (uint8_t)(w >> 16);
+ p[3] = (uint8_t)(w >> 24);
+ p[4] = (uint8_t)(w >> 32);
+ p[5] = (uint8_t)(w >> 40);
+ p[6] = (uint8_t)(w >> 48);
+ p[7] = (uint8_t)(w >> 56);
+#endif
}
-static inline uint32_t rotl32( const uint32_t w, const unsigned c )
+static BLAKE2_INLINE uint64_t load48( const void *src )
{
- return ( w << c ) | ( w >> ( 32 - c ) );
+ const uint8_t *p = ( const uint8_t * )src;
+ return (( uint64_t )( p[0] ) << 0) |
+ (( uint64_t )( p[1] ) << 8) |
+ (( uint64_t )( p[2] ) << 16) |
+ (( uint64_t )( p[3] ) << 24) |
+ (( uint64_t )( p[4] ) << 32) |
+ (( uint64_t )( p[5] ) << 40) ;
}
-static inline uint64_t rotl64( const uint64_t w, const unsigned c )
+static BLAKE2_INLINE void store48( void *dst, uint64_t w )
{
- return ( w << c ) | ( w >> ( 64 - c ) );
+ uint8_t *p = ( uint8_t * )dst;
+ p[0] = (uint8_t)(w >> 0);
+ p[1] = (uint8_t)(w >> 8);
+ p[2] = (uint8_t)(w >> 16);
+ p[3] = (uint8_t)(w >> 24);
+ p[4] = (uint8_t)(w >> 32);
+ p[5] = (uint8_t)(w >> 40);
}
-static inline uint32_t rotr32( const uint32_t w, const unsigned c )
+static BLAKE2_INLINE uint32_t rotr32( const uint32_t w, const unsigned c )
{
return ( w >> c ) | ( w << ( 32 - c ) );
}
-static inline uint64_t rotr64( const uint64_t w, const unsigned c )
+static BLAKE2_INLINE uint64_t rotr64( const uint64_t w, const unsigned c )
{
return ( w >> c ) | ( w << ( 64 - c ) );
}
/* prevents compiler optimizing out memset() */
-static inline void secure_zero_memory( void *v, size_t n )
+static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n)
{
- volatile uint8_t *p = ( volatile uint8_t * )v;
- while( n-- ) *p++ = 0;
+ static void *(*const volatile memset_v)(void *, int, size_t) = &memset;
+ memset_v(v, 0, n);
}
#endif
-
diff --git a/contrib/relic/src/md/blake2.h b/contrib/relic/src/md/blake2.h
index 78d806594..ca390305e 100644
--- a/contrib/relic/src/md/blake2.h
+++ b/contrib/relic/src/md/blake2.h
@@ -1,26 +1,27 @@
/*
BLAKE2 reference source code package - reference C implementations
- Written in 2012 by Samuel Neves
+ Copyright 2012, Samuel Neves . You may use this under the
+ terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
+ your option. The terms of these licenses can be found at:
- To the extent possible under law, the author(s) have dedicated all copyright
- and related and neighboring rights to this software to the public domain
- worldwide. This software is distributed without any warranty.
+ - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
+ - OpenSSL license : https://www.openssl.org/source/license.html
+ - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
- You should have received a copy of the CC0 Public Domain Dedication along with
- this software. If not, see .
+ More information about the BLAKE2 hash function can be found at
+ https://blake2.net.
*/
-#pragma once
-#ifndef __BLAKE2_H__
-#define __BLAKE2_H__
+#ifndef BLAKE2_H
+#define BLAKE2_H
#include
#include
#if defined(_MSC_VER)
-#define ALIGNME(x) __declspec(align(x))
+#define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop))
#else
-#define ALIGNME(x) __attribute__((aligned(x)))
+#define BLAKE2_PACKED(x) x __attribute__((packed))
#endif
#if defined(__cplusplus)
@@ -45,112 +46,150 @@ extern "C" {
BLAKE2B_PERSONALBYTES = 16
};
-#pragma pack(push, 1)
- typedef struct __blake2s_param
- {
- uint8_t digest_length; // 1
- uint8_t key_length; // 2
- uint8_t fanout; // 3
- uint8_t depth; // 4
- uint32_t leaf_length; // 8
- uint8_t node_offset[6];// 14
- uint8_t node_depth; // 15
- uint8_t inner_length; // 16
- // uint8_t reserved[0];
- uint8_t salt[BLAKE2S_SALTBYTES]; // 24
- uint8_t personal[BLAKE2S_PERSONALBYTES]; // 32
- } blake2s_param;
-
- ALIGNME( 64 ) typedef struct __blake2s_state
+ typedef struct blake2s_state__
{
uint32_t h[8];
uint32_t t[2];
uint32_t f[2];
- uint8_t buf[2 * BLAKE2S_BLOCKBYTES];
+ uint8_t buf[BLAKE2S_BLOCKBYTES];
size_t buflen;
+ size_t outlen;
uint8_t last_node;
- } blake2s_state ;
+ } blake2s_state;
- typedef struct __blake2b_param
- {
- uint8_t digest_length; // 1
- uint8_t key_length; // 2
- uint8_t fanout; // 3
- uint8_t depth; // 4
- uint32_t leaf_length; // 8
- uint64_t node_offset; // 16
- uint8_t node_depth; // 17
- uint8_t inner_length; // 18
- uint8_t reserved[14]; // 32
- uint8_t salt[BLAKE2B_SALTBYTES]; // 48
- uint8_t personal[BLAKE2B_PERSONALBYTES]; // 64
- } blake2b_param;
-
- ALIGNME( 64 ) typedef struct __blake2b_state
+ typedef struct blake2b_state__
{
uint64_t h[8];
uint64_t t[2];
uint64_t f[2];
- uint8_t buf[2 * BLAKE2B_BLOCKBYTES];
+ uint8_t buf[BLAKE2B_BLOCKBYTES];
size_t buflen;
+ size_t outlen;
uint8_t last_node;
} blake2b_state;
- typedef struct __blake2sp_state
+ typedef struct blake2sp_state__
{
blake2s_state S[8][1];
blake2s_state R[1];
- uint8_t buf[8 * BLAKE2S_BLOCKBYTES];
- size_t buflen;
+ uint8_t buf[8 * BLAKE2S_BLOCKBYTES];
+ size_t buflen;
+ size_t outlen;
} blake2sp_state;
- typedef struct __blake2bp_state
+ typedef struct blake2bp_state__
{
blake2b_state S[4][1];
blake2b_state R[1];
- uint8_t buf[4 * BLAKE2B_BLOCKBYTES];
- size_t buflen;
+ uint8_t buf[4 * BLAKE2B_BLOCKBYTES];
+ size_t buflen;
+ size_t outlen;
} blake2bp_state;
-#pragma pack(pop)
- // Streaming API
- int blake2s_init( blake2s_state *S, const uint8_t outlen );
- int blake2s_init_key( blake2s_state *S, const uint8_t outlen, const void *key, const uint8_t keylen );
+
+ BLAKE2_PACKED(struct blake2s_param__
+ {
+ uint8_t digest_length; /* 1 */
+ uint8_t key_length; /* 2 */
+ uint8_t fanout; /* 3 */
+ uint8_t depth; /* 4 */
+ uint32_t leaf_length; /* 8 */
+ uint32_t node_offset; /* 12 */
+ uint16_t xof_length; /* 14 */
+ uint8_t node_depth; /* 15 */
+ uint8_t inner_length; /* 16 */
+ /* uint8_t reserved[0]; */
+ uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */
+ uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */
+ });
+
+ typedef struct blake2s_param__ blake2s_param;
+
+ BLAKE2_PACKED(struct blake2b_param__
+ {
+ uint8_t digest_length; /* 1 */
+ uint8_t key_length; /* 2 */
+ uint8_t fanout; /* 3 */
+ uint8_t depth; /* 4 */
+ uint32_t leaf_length; /* 8 */
+ uint32_t node_offset; /* 12 */
+ uint32_t xof_length; /* 16 */
+ uint8_t node_depth; /* 17 */
+ uint8_t inner_length; /* 18 */
+ uint8_t reserved[14]; /* 32 */
+ uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */
+ uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */
+ });
+
+ typedef struct blake2b_param__ blake2b_param;
+
+ typedef struct blake2xs_state__
+ {
+ blake2s_state S[1];
+ blake2s_param P[1];
+ } blake2xs_state;
+
+ typedef struct blake2xb_state__
+ {
+ blake2b_state S[1];
+ blake2b_param P[1];
+ } blake2xb_state;
+
+ /* Padded structs result in a compile-time error */
+ enum {
+ BLAKE2_DUMMY_1 = 1/(int)(sizeof(blake2s_param) == BLAKE2S_OUTBYTES),
+ BLAKE2_DUMMY_2 = 1/(int)(sizeof(blake2b_param) == BLAKE2B_OUTBYTES)
+ };
+
+ /* Streaming API */
+ int blake2s_init( blake2s_state *S, size_t outlen );
+ int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen );
int blake2s_init_param( blake2s_state *S, const blake2s_param *P );
- int blake2s_update( blake2s_state *S, const uint8_t *in, uint64_t inlen );
- int blake2s_final( blake2s_state *S, uint8_t *out, uint8_t outlen );
+ int blake2s_update( blake2s_state *S, const void *in, size_t inlen );
+ int blake2s_final( blake2s_state *S, void *out, size_t outlen );
- int blake2b_init( blake2b_state *S, const uint8_t outlen );
- int blake2b_init_key( blake2b_state *S, const uint8_t outlen, const void *key, const uint8_t keylen );
+ int blake2b_init( blake2b_state *S, size_t outlen );
+ int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen );
int blake2b_init_param( blake2b_state *S, const blake2b_param *P );
- int blake2b_update( blake2b_state *S, const uint8_t *in, uint64_t inlen );
- int blake2b_final( blake2b_state *S, uint8_t *out, uint8_t outlen );
+ int blake2b_update( blake2b_state *S, const void *in, size_t inlen );
+ int blake2b_final( blake2b_state *S, void *out, size_t outlen );
- int blake2sp_init( blake2sp_state *S, const uint8_t outlen );
- int blake2sp_init_key( blake2sp_state *S, const uint8_t outlen, const void *key, const uint8_t keylen );
- int blake2sp_update( blake2sp_state *S, const uint8_t *in, uint64_t inlen );
- int blake2sp_final( blake2sp_state *S, uint8_t *out, uint8_t outlen );
+ int blake2sp_init( blake2sp_state *S, size_t outlen );
+ int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen );
+ int blake2sp_update( blake2sp_state *S, const void *in, size_t inlen );
+ int blake2sp_final( blake2sp_state *S, void *out, size_t outlen );
- int blake2bp_init( blake2bp_state *S, const uint8_t outlen );
- int blake2bp_init_key( blake2bp_state *S, const uint8_t outlen, const void *key, const uint8_t keylen );
- int blake2bp_update( blake2bp_state *S, const uint8_t *in, uint64_t inlen );
- int blake2bp_final( blake2bp_state *S, uint8_t *out, uint8_t outlen );
+ int blake2bp_init( blake2bp_state *S, size_t outlen );
+ int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen );
+ int blake2bp_update( blake2bp_state *S, const void *in, size_t inlen );
+ int blake2bp_final( blake2bp_state *S, void *out, size_t outlen );
- // Simple API
- int blake2s( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen );
- int blake2b( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen );
+ /* Variable output length API */
+ int blake2xs_init( blake2xs_state *S, const size_t outlen );
+ int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen );
+ int blake2xs_update( blake2xs_state *S, const void *in, size_t inlen );
+ int blake2xs_final(blake2xs_state *S, void *out, size_t outlen);
- int blake2sp( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen );
- int blake2bp( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen );
+ int blake2xb_init( blake2xb_state *S, const size_t outlen );
+ int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen );
+ int blake2xb_update( blake2xb_state *S, const void *in, size_t inlen );
+ int blake2xb_final(blake2xb_state *S, void *out, size_t outlen);
- static inline int blake2( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen )
- {
- return blake2b( out, in, key, outlen, inlen, keylen );
- }
+ /* Simple API */
+ int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
+ int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
+
+ int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
+ int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
+
+ int blake2xs( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
+ int blake2xb( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
+
+ /* This is simply an alias for blake2b */
+ int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
#if defined(__cplusplus)
}
#endif
#endif
-
diff --git a/contrib/relic/src/md/blake2s-ref.c b/contrib/relic/src/md/blake2s-ref.c
index 9678e79c8..c8b035f62 100644
--- a/contrib/relic/src/md/blake2s-ref.c
+++ b/contrib/relic/src/md/blake2s-ref.c
@@ -1,14 +1,16 @@
/*
BLAKE2 reference source code package - reference C implementations
- Written in 2012 by Samuel Neves
+ Copyright 2012, Samuel Neves . You may use this under the
+ terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
+ your option. The terms of these licenses can be found at:
- To the extent possible under law, the author(s) have dedicated all copyright
- and related and neighboring rights to this software to the public domain
- worldwide. This software is distributed without any warranty.
+ - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
+ - OpenSSL license : https://www.openssl.org/source/license.html
+ - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
- You should have received a copy of the CC0 Public Domain Dedication along with
- this software. If not, see .
+ More information about the BLAKE2 hash function can be found at
+ https://blake2.net.
*/
#include
@@ -38,143 +40,79 @@ static const uint8_t blake2s_sigma[10][16] =
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
};
-static inline int blake2s_set_lastnode( blake2s_state *S )
+static void blake2s_set_lastnode( blake2s_state *S )
{
- S->f[1] = -1;
- return 0;
-}
-
-static inline int blake2s_clear_lastnode( blake2s_state *S )
-{
- S->f[1] = 0;
- return 0;
+ S->f[1] = (uint32_t)-1;
}
/* Some helper functions, not necessarily useful */
-static inline int blake2s_set_lastblock( blake2s_state *S )
+static int blake2s_is_lastblock( const blake2s_state *S )
{
- if( S->last_node ) blake2s_set_lastnode( S );
-
- S->f[0] = -1;
- return 0;
+ return S->f[0] != 0;
}
-static inline int blake2s_clear_lastblock( blake2s_state *S )
+static void blake2s_set_lastblock( blake2s_state *S )
{
- if( S->last_node ) blake2s_clear_lastnode( S );
+ if( S->last_node ) blake2s_set_lastnode( S );
- S->f[0] = 0;
- return 0;
+ S->f[0] = (uint32_t)-1;
}
-static inline int blake2s_increment_counter( blake2s_state *S, const uint32_t inc )
+static void blake2s_increment_counter( blake2s_state *S, const uint32_t inc )
{
S->t[0] += inc;
S->t[1] += ( S->t[0] < inc );
- return 0;
-}
-
-// Parameter-related functions
-static inline int blake2s_param_set_digest_length( blake2s_param *P, const uint8_t digest_length )
-{
- P->digest_length = digest_length;
- return 0;
-}
-
-static inline int blake2s_param_set_fanout( blake2s_param *P, const uint8_t fanout )
-{
- P->fanout = fanout;
- return 0;
-}
-
-static inline int blake2s_param_set_max_depth( blake2s_param *P, const uint8_t depth )
-{
- P->depth = depth;
- return 0;
-}
-
-static inline int blake2s_param_set_leaf_length( blake2s_param *P, const uint32_t leaf_length )
-{
- store32( &P->leaf_length, leaf_length );
- return 0;
-}
-
-static inline int blake2s_param_set_node_offset( blake2s_param *P, const uint64_t node_offset )
-{
- store48( P->node_offset, node_offset );
- return 0;
-}
-
-static inline int blake2s_param_set_node_depth( blake2s_param *P, const uint8_t node_depth )
-{
- P->node_depth = node_depth;
- return 0;
-}
-
-static inline int blake2s_param_set_inner_length( blake2s_param *P, const uint8_t inner_length )
-{
- P->inner_length = inner_length;
- return 0;
}
-static inline int blake2s_param_set_salt( blake2s_param *P, const uint8_t salt[BLAKE2S_SALTBYTES] )
-{
- memcpy( P->salt, salt, BLAKE2S_SALTBYTES );
- return 0;
-}
-
-static inline int blake2s_param_set_personal( blake2s_param *P, const uint8_t personal[BLAKE2S_PERSONALBYTES] )
-{
- memcpy( P->personal, personal, BLAKE2S_PERSONALBYTES );
- return 0;
-}
-
-static inline int blake2s_init0( blake2s_state *S )
+static void blake2s_init0( blake2s_state *S )
{
+ size_t i;
memset( S, 0, sizeof( blake2s_state ) );
- for( int i = 0; i < 8; ++i ) S->h[i] = blake2s_IV[i];
-
- return 0;
+ for( i = 0; i < 8; ++i ) S->h[i] = blake2s_IV[i];
}
/* init2 xors IV with input parameter block */
int blake2s_init_param( blake2s_state *S, const blake2s_param *P )
{
+ const unsigned char *p = ( const unsigned char * )( P );
+ size_t i;
+
blake2s_init0( S );
- const uint32_t *p = ( const uint32_t * )( P );
/* IV XOR ParamBlock */
- for( size_t i = 0; i < 8; ++i )
- S->h[i] ^= load32( &p[i] );
+ for( i = 0; i < 8; ++i )
+ S->h[i] ^= load32( &p[i * 4] );
+ S->outlen = P->digest_length;
return 0;
}
-// Sequential blake2s initialization
-int blake2s_init( blake2s_state *S, const uint8_t outlen )
+/* Sequential blake2s initialization */
+int blake2s_init( blake2s_state *S, size_t outlen )
{
blake2s_param P[1];
/* Move interval verification here? */
if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1;
- P->digest_length = outlen;
+ P->digest_length = (uint8_t)outlen;
P->key_length = 0;
P->fanout = 1;
P->depth = 1;
store32( &P->leaf_length, 0 );
- store48( &P->node_offset, 0 );
+ store32( &P->node_offset, 0 );
+ store16( &P->xof_length, 0 );
P->node_depth = 0;
P->inner_length = 0;
- // memset(P->reserved, 0, sizeof(P->reserved) );
+ /* memset(P->reserved, 0, sizeof(P->reserved) ); */
memset( P->salt, 0, sizeof( P->salt ) );
memset( P->personal, 0, sizeof( P->personal ) );
return blake2s_init_param( S, P );
}
-int blake2s_init_key( blake2s_state *S, const uint8_t outlen, const void *key, const uint8_t keylen )
+int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen )
{
blake2s_param P[1];
@@ -182,15 +120,16 @@ int blake2s_init_key( blake2s_state *S, const uint8_t outlen, const void *key, c
if ( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1;
- P->digest_length = outlen;
- P->key_length = keylen;
+ P->digest_length = (uint8_t)outlen;
+ P->key_length = (uint8_t)keylen;
P->fanout = 1;
P->depth = 1;
store32( &P->leaf_length, 0 );
- store48( &P->node_offset, 0 );
+ store32( &P->node_offset, 0 );
+ store16( &P->xof_length, 0 );
P->node_depth = 0;
P->inner_length = 0;
- // memset(P->reserved, 0, sizeof(P->reserved) );
+ /* memset(P->reserved, 0, sizeof(P->reserved) ); */
memset( P->salt, 0, sizeof( P->salt ) );
memset( P->personal, 0, sizeof( P->personal ) );
@@ -206,16 +145,43 @@ int blake2s_init_key( blake2s_state *S, const uint8_t outlen, const void *key, c
return 0;
}
-static int blake2s_compress( blake2s_state *S, const uint8_t block[BLAKE2S_BLOCKBYTES] )
+#define G(r,i,a,b,c,d) \
+ do { \
+ a = a + b + m[blake2s_sigma[r][2*i+0]]; \
+ d = rotr32(d ^ a, 16); \
+ c = c + d; \
+ b = rotr32(b ^ c, 12); \
+ a = a + b + m[blake2s_sigma[r][2*i+1]]; \
+ d = rotr32(d ^ a, 8); \
+ c = c + d; \
+ b = rotr32(b ^ c, 7); \
+ } while(0)
+
+#define ROUND(r) \
+ do { \
+ G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
+ G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
+ G(r,2,v[ 2],v[ 6],v[10],v[14]); \
+ G(r,3,v[ 3],v[ 7],v[11],v[15]); \
+ G(r,4,v[ 0],v[ 5],v[10],v[15]); \
+ G(r,5,v[ 1],v[ 6],v[11],v[12]); \
+ G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
+ G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
+ } while(0)
+
+static void blake2s_compress( blake2s_state *S, const uint8_t in[BLAKE2S_BLOCKBYTES] )
{
uint32_t m[16];
uint32_t v[16];
+ size_t i;
- for( size_t i = 0; i < 16; ++i )
- m[i] = load32( block + i * sizeof( m[i] ) );
+ for( i = 0; i < 16; ++i ) {
+ m[i] = load32( in + i * sizeof( m[i] ) );
+ }
- for( size_t i = 0; i < 8; ++i )
+ for( i = 0; i < 8; ++i ) {
v[i] = S->h[i];
+ }
v[ 8] = blake2s_IV[0];
v[ 9] = blake2s_IV[1];
@@ -225,28 +191,7 @@ static int blake2s_compress( blake2s_state *S, const uint8_t block[BLAKE2S_BLOCK
v[13] = S->t[1] ^ blake2s_IV[5];
v[14] = S->f[0] ^ blake2s_IV[6];
v[15] = S->f[1] ^ blake2s_IV[7];
-#define G(r,i,a,b,c,d) \
- do { \
- a = a + b + m[blake2s_sigma[r][2*i+0]]; \
- d = rotr32(d ^ a, 16); \
- c = c + d; \
- b = rotr32(b ^ c, 12); \
- a = a + b + m[blake2s_sigma[r][2*i+1]]; \
- d = rotr32(d ^ a, 8); \
- c = c + d; \
- b = rotr32(b ^ c, 7); \
- } while(0)
-#define ROUND(r) \
- do { \
- G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
- G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
- G(r,2,v[ 2],v[ 6],v[10],v[14]); \
- G(r,3,v[ 3],v[ 7],v[11],v[15]); \
- G(r,4,v[ 0],v[ 5],v[10],v[15]); \
- G(r,5,v[ 1],v[ 6],v[11],v[12]); \
- G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
- G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
- } while(0)
+
ROUND( 0 );
ROUND( 1 );
ROUND( 2 );
@@ -258,82 +203,79 @@ static int blake2s_compress( blake2s_state *S, const uint8_t block[BLAKE2S_BLOCK
ROUND( 8 );
ROUND( 9 );
- for( size_t i = 0; i < 8; ++i )
+ for( i = 0; i < 8; ++i ) {
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
+ }
+}
#undef G
#undef ROUND
- return 0;
-}
-
-int blake2s_update( blake2s_state *S, const uint8_t *in, uint64_t inlen )
+int blake2s_update( blake2s_state *S, const void *pin, size_t inlen )
{
- while( inlen > 0 )
+ const unsigned char * in = (const unsigned char *)pin;
+ if( inlen > 0 )
{
size_t left = S->buflen;
- size_t fill = 2 * BLAKE2S_BLOCKBYTES - left;
-
+ size_t fill = BLAKE2S_BLOCKBYTES - left;
if( inlen > fill )
{
- memcpy( S->buf + left, in, fill ); // Fill buffer
- S->buflen += fill;
+ S->buflen = 0;
+ memcpy( S->buf + left, in, fill ); /* Fill buffer */
blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
- blake2s_compress( S, S->buf ); // Compress
- memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES ); // Shift buffer left
- S->buflen -= BLAKE2S_BLOCKBYTES;
- in += fill;
- inlen -= fill;
- }
- else // inlen <= fill
- {
- memcpy( S->buf + left, in, inlen );
- S->buflen += inlen; // Be lazy, do not compress
- in += inlen;
- inlen -= inlen;
+ blake2s_compress( S, S->buf ); /* Compress */
+ in += fill; inlen -= fill;
+ while(inlen > BLAKE2S_BLOCKBYTES) {
+ blake2s_increment_counter(S, BLAKE2S_BLOCKBYTES);
+ blake2s_compress( S, in );
+ in += BLAKE2S_BLOCKBYTES;
+ inlen -= BLAKE2S_BLOCKBYTES;
+ }
}
+ memcpy( S->buf + S->buflen, in, inlen );
+ S->buflen += inlen;
}
-
return 0;
}
-int blake2s_final( blake2s_state *S, uint8_t *out, uint8_t outlen )
+int blake2s_final( blake2s_state *S, void *out, size_t outlen )
{
uint8_t buffer[BLAKE2S_OUTBYTES] = {0};
+ size_t i;
- if( outlen > BLAKE2S_OUTBYTES )
+ if( out == NULL || outlen < S->outlen )
return -1;
- if( S->buflen > BLAKE2S_BLOCKBYTES )
- {
- blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
- blake2s_compress( S, S->buf );
- S->buflen -= BLAKE2S_BLOCKBYTES;
- memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, S->buflen );
- }
+ if( blake2s_is_lastblock( S ) )
+ return -1;
blake2s_increment_counter( S, ( uint32_t )S->buflen );
blake2s_set_lastblock( S );
- memset( S->buf + S->buflen, 0, 2 * BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */
+ memset( S->buf + S->buflen, 0, BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */
blake2s_compress( S, S->buf );
- for( int i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
+ for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
store32( buffer + sizeof( S->h[i] ) * i, S->h[i] );
-
+
memcpy( out, buffer, outlen );
+ secure_zero_memory(buffer, sizeof(buffer));
return 0;
}
-int blake2s( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen )
+int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
{
blake2s_state S[1];
/* Verify parameters */
- if ( NULL == in ) return -1;
+ if ( NULL == in && inlen > 0 ) return -1;
if ( NULL == out ) return -1;
- if ( NULL == key ) keylen = 0; /* Fail here instead if keylen != 0 and key == NULL? */
+ if ( NULL == key && keylen > 0) return -1;
+
+ if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1;
+
+ if( keylen > BLAKE2S_KEYBYTES ) return -1;
if( keylen > 0 )
{
@@ -349,35 +291,77 @@ int blake2s( uint8_t *out, const void *in, const void *key, const uint8_t outlen
return 0;
}
+#if defined(SUPERCOP)
+int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )
+{
+ return blake2s( out, BLAKE2S_OUTBYTES, in, inlen, NULL, 0 );
+}
+#endif
+
#if defined(BLAKE2S_SELFTEST)
#include
#include "blake2-kat.h"
-int main( int argc, char **argv )
+int main( void )
{
uint8_t key[BLAKE2S_KEYBYTES];
- uint8_t buf[KAT_LENGTH];
+ uint8_t buf[BLAKE2_KAT_LENGTH];
+ size_t i, step;
- for( size_t i = 0; i < BLAKE2S_KEYBYTES; ++i )
+ for( i = 0; i < BLAKE2S_KEYBYTES; ++i )
key[i] = ( uint8_t )i;
- for( size_t i = 0; i < KAT_LENGTH; ++i )
+ for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
buf[i] = ( uint8_t )i;
- for( size_t i = 0; i < KAT_LENGTH; ++i )
+ /* Test simple API */
+ for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
{
uint8_t hash[BLAKE2S_OUTBYTES];
- blake2s( hash, buf, key, BLAKE2S_OUTBYTES, i, BLAKE2S_KEYBYTES );
+ blake2s( hash, BLAKE2S_OUTBYTES, buf, i, key, BLAKE2S_KEYBYTES );
if( 0 != memcmp( hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES ) )
{
- puts( "error" );
- return -1;
+ goto fail;
+ }
+ }
+
+ /* Test streaming API */
+ for(step = 1; step < BLAKE2S_BLOCKBYTES; ++step) {
+ for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
+ uint8_t hash[BLAKE2S_OUTBYTES];
+ blake2s_state S;
+ uint8_t * p = buf;
+ size_t mlen = i;
+ int err = 0;
+
+ if( (err = blake2s_init_key(&S, BLAKE2S_OUTBYTES, key, BLAKE2S_KEYBYTES)) < 0 ) {
+ goto fail;
+ }
+
+ while (mlen >= step) {
+ if ( (err = blake2s_update(&S, p, step)) < 0 ) {
+ goto fail;
+ }
+ mlen -= step;
+ p += step;
+ }
+ if ( (err = blake2s_update(&S, p, mlen)) < 0) {
+ goto fail;
+ }
+ if ( (err = blake2s_final(&S, hash, BLAKE2S_OUTBYTES)) < 0) {
+ goto fail;
+ }
+
+ if (0 != memcmp(hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES)) {
+ goto fail;
+ }
}
}
puts( "ok" );
return 0;
+fail:
+ puts("error");
+ return -1;
}
#endif
-
-
diff --git a/contrib/relic/src/md/relic_md_blake2s.c b/contrib/relic/src/md/relic_md_blake2s.c
index 55ea9ff48..cf0b79b54 100644
--- a/contrib/relic/src/md/relic_md_blake2s.c
+++ b/contrib/relic/src/md/relic_md_blake2s.c
@@ -45,7 +45,7 @@
void md_map_b2s160(uint8_t *hash, const uint8_t *msg, int len) {
memset(hash, 0, RLC_MD_LEN_B2S160);
- blake2s(hash, msg, NULL, RLC_MD_LEN_B2S160, len, 0);
+ blake2s(hash, RLC_MD_LEN_B2S160, msg, len, NULL, 0);
}
#endif
@@ -54,7 +54,7 @@ void md_map_b2s160(uint8_t *hash, const uint8_t *msg, int len) {
void md_map_b2s256(uint8_t *hash, const uint8_t *msg, int len) {
memset(hash, 0, RLC_MD_LEN_B2S256);
- blake2s(hash, msg, NULL, RLC_MD_LEN_B2S256, len, 0);
+ blake2s(hash, RLC_MD_LEN_B2S256, msg, len, NULL, 0);
}
#endif
diff --git a/contrib/relic/src/md/relic_md_hmac.c b/contrib/relic/src/md/relic_md_hmac.c
index 712581161..00b7e63b5 100644
--- a/contrib/relic/src/md/relic_md_hmac.c
+++ b/contrib/relic/src/md/relic_md_hmac.c
@@ -42,7 +42,7 @@
void md_hmac(uint8_t *mac, const uint8_t *in, int in_len, const uint8_t *key,
int key_len) {
-#if MD_MAP == SH224 || MD_MAP == SH256 || MD_MAP == BLAKE2S_160 || MD_MAP == BLAKE2S_256
+#if MD_MAP == SH224 || MD_MAP == SH256 || MD_MAP == B2S160 || MD_MAP == B2S256
#define block_size 64
#elif MD_MAP == SH384 || MD_MAP == SH512
#define block_size 128
diff --git a/contrib/relic/src/pc/relic_pc_exp.c b/contrib/relic/src/pc/relic_pc_exp.c
index e2fff2328..38e994455 100644
--- a/contrib/relic/src/pc/relic_pc_exp.c
+++ b/contrib/relic/src/pc/relic_pc_exp.c
@@ -41,6 +41,14 @@ void g1_mul(g1_t c, g1_t a, bn_t b) {
bn_null(n);
bn_null(_b);
+ if (bn_bits(b) <= RLC_DIG) {
+ g1_mul_dig(c, a, b->dp[0]);
+ if (bn_sign(b) == RLC_NEG) {
+ g1_neg(c, c);
+ }
+ return;
+ }
+
RLC_TRY {
bn_new(n);
bn_new(_b);
@@ -85,6 +93,14 @@ void g2_mul(g2_t c, g2_t a, bn_t b) {
bn_null(n);
bn_null(_b);
+ if (bn_bits(b) <= RLC_DIG) {
+ g2_mul_dig(c, a, b->dp[0]);
+ if (bn_sign(b) == RLC_NEG) {
+ g2_neg(c, c);
+ }
+ return;
+ }
+
RLC_TRY {
bn_new(n);
bn_new(_b);
@@ -129,6 +145,14 @@ void gt_exp(gt_t c, gt_t a, bn_t b) {
bn_null(n);
bn_null(_b);
+ if (bn_bits(b) <= RLC_DIG) {
+ gt_exp_dig(c, a, b->dp[0]);
+ if (bn_sign(b) == RLC_NEG) {
+ gt_inv(c, c);
+ }
+ return;
+ }
+
RLC_TRY {
bn_new(n);
bn_new(_b);
@@ -145,6 +169,37 @@ void gt_exp(gt_t c, gt_t a, bn_t b) {
}
}
+void gt_exp_dig(gt_t c, gt_t a, dig_t b) {
+ gt_t t;
+
+ if (b == 0) {
+ gt_set_unity(c);
+ return;
+ }
+
+ gt_null(t);
+
+ RLC_TRY {
+ gt_new(t);
+
+ gt_copy(t, a);
+ for (int i = util_bits_dig(b) - 2; i >= 0; i--) {
+ gt_sqr(t, t);
+ if (b & ((dig_t)1 << i)) {
+ gt_mul(t, t, a);
+ }
+ }
+
+ gt_copy(c, t);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ gt_free(t);
+ }
+}
+
void gt_exp_sim(gt_t e, gt_t a, bn_t b, gt_t c, bn_t d) {
bn_t n, _b, _d;
diff --git a/contrib/relic/src/pc/relic_pc_util.c b/contrib/relic/src/pc/relic_pc_util.c
index af2af3faf..bfd4905e0 100644
--- a/contrib/relic/src/pc/relic_pc_util.c
+++ b/contrib/relic/src/pc/relic_pc_util.c
@@ -50,39 +50,24 @@
void gt_rand(gt_t a) {
gt_rand_imp(a);
#if FP_PRIME < 1536
+#if FP_PRIME == 509
+ pp_exp_k24(a, a);
+#else
pp_exp_k12(a, a);
+#endif
#else
pp_exp_k2(a, a);
#endif
}
void gt_get_gen(gt_t g) {
- g1_t g1;
- g2_t g2;
-
- g1_null(g1);
- g2_null(g2);
-
- RLC_TRY {
- g1_new(g1);
- g2_new(g2);
-
- g1_get_gen(g1);
- g2_get_gen(g2);
-
- pc_map(g, g1, g2);
- } RLC_CATCH_ANY {
- RLC_THROW(ERR_CAUGHT);
- } RLC_FINALLY {
- g1_free(g1);
- g2_free(g2);
- }
+ gt_copy(g, core_get()->gt_g);
}
int g1_is_valid(g1_t a) {
bn_t n;
g1_t t, u, v;
- int r;
+ int r = 0;
if (g1_is_infty(a)) {
return 0;
@@ -102,45 +87,38 @@ int g1_is_valid(g1_t a) {
ep_curve_get_cof(n);
if (bn_cmp_dig(n, 1) == RLC_EQ) {
/* If curve has prime order, simpler to check if point on curve. */
- r = ep_on_curve(a);
+ r = g1_on_curve(a);
} else {
switch (ep_curve_is_pairf()) {
/* Formulas from "Faster Subgroup Checks for BLS12-381" by Bowe.
- * https://eprint.iacr.org/2019/814.pdf */
+ * https://eprint.iacr.org/2019/814.pdf, together with tweaks
+ * by Mike Scott. */
case EP_B12:
- /* Check [(z^2−1)](2\psi(P)-P-\psi^2(P)) == [3]\psi^2(P). */
- ep_psi(v, a);
- ep_dbl(u, v);
- ep_psi(v, v);
- ep_sub(u, u, a);
- ep_sub(u, u, v);
+ /* Check [(z^2−1)](\psi(P)+P) == -P.*/
fp_prime_get_par(n);
bn_sqr(n, n);
- ep_copy(t, u);
+ bn_sub_dig(n, n, 1);
+ ep_psi(t, a);
+ ep_add(t, t, a);
+ ep_copy(u, t);
for (int i = bn_bits(n) - 2; i >= 0; i--) {
- ep_dbl(t, t);
+ g1_dbl(u, u);
if (bn_get_bit(n, i)) {
- ep_add(t, t, u);
+ g1_add(u, u, t);
}
}
- ep_sub(t, t, u);
- ep_dbl(u, v);
- ep_add(u, u, v);
- r = ep_on_curve(t) && (ep_cmp(t, u) == RLC_EQ);
+ g1_neg(v, a);
+ r = g1_on_curve(a) && (g1_cmp(v, u) == RLC_EQ);
break;
default:
pc_get_ord(n);
bn_sub_dig(n, n, 1);
/* Otherwise, check order explicitly. */
- g1_copy(u, a);
- for (int i = bn_bits(n) - 2; i >= 0; i--) {
- g1_dbl(u, u);
- if (bn_get_bit(n, i)) {
- g1_add(u, u, a);
- }
- }
+ /* We use fast scalar multiplication methods here, because
+ * they should work only in the correct subgroup. */
+ g1_mul(u, a, n);
g1_neg(u, u);
- r = ep_on_curve(a) && (g1_cmp(u, a) == RLC_EQ);
+ r = g1_on_curve(a) && (g1_cmp(u, a) == RLC_EQ);
break;
}
}
@@ -169,7 +147,7 @@ int g2_is_valid(g2_t a) {
bn_t p, n;
g2_t u, v;
- int r;
+ int r = 0;
bn_null(n);
bn_null(p);
@@ -194,48 +172,54 @@ int g2_is_valid(g2_t a) {
/* Compute trace t = p - n + 1. */
bn_sub(n, p, n);
bn_add_dig(n, n, 1);
- /* Compute u = a^t. */
g2_mul(u, a, n);
+ if (bn_sign(n) == RLC_NEG) {
+ g2_neg(u, u);
+ }
/* Compute v = a^(p + 1). */
- ep2_frb(v, a, 1);
+ g2_frb(v, a, 1);
g2_add(v, v, a);
/* Check if a^(p + 1) = a^t. */
- r = ep2_on_curve(a) && (g2_cmp(u, v) == RLC_EQ);
+ r = g2_on_curve(a) && (g2_cmp(u, v) == RLC_EQ);
} else {
switch (ep_curve_is_pairf()) {
/* Formulas from "Faster Subgroup Checks for BLS12-381" by Bowe.
* https://eprint.iacr.org/2019/814.pdf */
case EP_B12:
+#if FP_PRIME == 383
+ /* Since p mod n = r, we can check instead that
+ * psi^4(P) + P == \psi^2(P). */
+ ep2_frb(u, a, 4);
+ ep2_add(u, u, a);
+ ep2_frb(v, a, 2);
+#else
/* Check [z]psi^3(P) + P == \psi^2(P). */
fp_prime_get_par(n);
- ep2_copy(u, a);
+ g2_copy(u, a);
for (int i = bn_bits(n) - 2; i >= 0; i--) {
- ep2_dbl(u, u);
+ g2_dbl(u, u);
if (bn_get_bit(n, i)) {
- ep2_add(u, u, a);
+ g2_add(u, u, a);
}
}
if (bn_sign(n) == RLC_NEG) {
- ep2_neg(u, u);
+ g2_neg(u, u);
}
- ep2_frb(u, u, 3);
- ep2_frb(v, a, 2);
- ep2_add(u, u, a);
- r = ep2_on_curve(a) && (g2_cmp(u, v) == RLC_EQ);
+ g2_frb(u, u, 3);
+ g2_frb(v, a, 2);
+ g2_add(u, u, a);
+#endif
+ r = g2_on_curve(a) && (g2_cmp(u, v) == RLC_EQ);
break;
default:
pc_get_ord(n);
bn_sub_dig(n, n, 1);
/* Otherwise, check order explicitly. */
- g2_copy(u, a);
- for (int i = bn_bits(n) - 2; i >= 0; i--) {
- g2_dbl(u, u);
- if (bn_get_bit(n, i)) {
- g2_add(u, u, a);
- }
- }
+ /* We use fast scalar multiplication methods here, because
+ * they should work only in the correct order. */
+ g2_mul(u, a, n);
g2_neg(u, u);
- r = ep2_on_curve(a) && (g2_cmp(u, a) == RLC_EQ);
+ r = g2_on_curve(a) && (g2_cmp(u, a) == RLC_EQ);
break;
}
}
@@ -252,10 +236,13 @@ int g2_is_valid(g2_t a) {
#endif
}
+#define GLS_MEMBER
+
int gt_is_valid(gt_t a) {
bn_t p, n;
gt_t u, v;
- int r;
+ int l, r = 0;
+ const int *b;
if (gt_is_unity(a)) {
return 0;
@@ -275,43 +262,102 @@ int gt_is_valid(gt_t a) {
pc_get_ord(n);
ep_curve_get_cof(p);
+ /* For a BN curve, we can use the fast test from
+ * Unbalancing Pairing-Based Key Exchange Protocols by Scott.
+ * https://eprint.iacr.org/2013/688.pdf */
if (bn_cmp_dig(p, 1) == RLC_EQ) {
dv_copy(p->dp, fp_prime_get(), RLC_FP_DIGS);
p->used = RLC_FP_DIGS;
p->sign = RLC_POS;
- /* Compute trace t = p - n + 1. */
- bn_sub(n, p, n);
- bn_add_dig(n, n, 1);
- /* Compute u = a^t. */
- gt_exp(u, a, n);
+ if (ep_curve_is_pairf() == EP_BN) {
+ /* Compute trace t = p - n + 1, and compute a^t. */
+ fp_prime_get_par(n);
+ b = fp_prime_get_par_sps(&l);
+ fp12_exp_cyc_sps((void *)v, (void *)a, b, l, RLC_POS);
+ fp12_exp_cyc_sps((void *)u, (void *)v, b, l, RLC_POS);
+ gt_sqr(v, u);
+ gt_sqr(u, v);
+ gt_mul(u, u, v);
+ } else {
+ /* Compute trace t = p - n + 1. */
+ bn_sub(n, p, n);
+ /* Compute u = a^t. */
+ gt_exp(u, a, n);
+ }
/* Compute v = a^(p + 1). */
gt_frb(v, a, 1);
- gt_mul(v, v, a);
/* Check if a^(p + 1) = a^t. */
- r = (gt_cmp(u, v) == RLC_EQ);
+ r = fp12_test_cyc((void *)a) && (gt_cmp(u, v) == RLC_EQ);
} else {
+ fp_prime_get_par(n);
+ b = fp_prime_get_par_sps(&l);
switch (ep_curve_is_pairf()) {
/* Formulas from "Faster Subgroup Checks for BLS12-381" by Bowe.
* https://eprint.iacr.org/2019/814.pdf */
case EP_B12:
- /* Check [z]psi^3(P) + P == \psi^2(P). */
- fp_prime_get_par(n);
- gt_exp(u, a, n);
- gt_frb(u, u, 3);
- gt_frb(v, a, 2);
+#if FP_PRIME == 383
+ /* GT-strong, so test for cyclotomic only. */
+ r = 1;
+#else
+#ifdef GLS_MEMBER
+ /* The 4-GLS recoding of the exponent gives this. */
+ fp12_exp_cyc_sps((void *)u, (void *)a, b, l, RLC_POS);
+ gt_inv(u, u);
+ gt_mul(u, u, a);
+ gt_inv(u, u);
+ gt_frb(u, u, 2);
+ gt_frb(v, u, 1);
+ gt_inv(v, v);
+ gt_mul(u, u, v);
+ gt_inv(u, u);
+ r = (gt_cmp(u, a) == RLC_EQ);
+#else
+ gt_frb(u, a, 1);
+ fp12_exp_cyc_sps((void *)v, (void *)a, b, l, bn_sign(n));
+ r = (gt_cmp(u, v) == RLC_EQ);
+ fp12_exp_cyc_sps((void *)u, (void *)v, b, l, bn_sign(n));
+ gt_mul(u, u, a);
+ gt_sqr(v, v);
+ r &= (gt_cmp(u, v) != RLC_EQ);
+#endif
+#endif
+ r &= fp12_test_cyc((void *)a);
+ break;
+#if FP_PRIME == 509
+ case EP_B24:
+#ifdef GLS_MEMBER
+ /* The 8-GLS recoding of the exponent gives this. */
+ fp24_exp_cyc_sps((void *)u, (void *)a, b, l, bn_sign(n));
gt_mul(u, u, a);
+ gt_inv(u, u);
+ gt_frb(u, u, 4);
+ gt_frb(v, u, 1);
+ gt_inv(v, v);
+ gt_mul(u, u, v);
+ gt_frb(v, v, 1);
+ gt_inv(v, v);
+ gt_mul(u, u, v);
+ gt_frb(v, v, 1);
+ gt_inv(v, v);
+ gt_mul(u, u, v);
+ gt_inv(u, u);
+ r = (gt_cmp(u, a) == RLC_EQ);
+#else
+ gt_frb(u, a, 1);
+ fp24_exp_cyc_sps((void *)v, (void *)a, b, l, bn_sign(n));
r = (gt_cmp(u, v) == RLC_EQ);
+ fp24_exp_cyc_sps((void *)u, (void *)v, b, l, bn_sign(n));
+ gt_mul(u, u, a);
+ gt_sqr(v, v);
+ r &= (gt_cmp(u, v) != RLC_EQ);
+#endif
+ r = fp24_test_cyc((void *)a);
break;
+#endif
default:
/* Common case. */
bn_sub_dig(n, n, 1);
- gt_copy(u, a);
- for (int i = bn_bits(n) - 2; i >= 0; i--) {
- gt_sqr(u, u);
- if (bn_get_bit(n, i)) {
- gt_mul(u, u, a);
- }
- }
+ gt_exp(u, a, n);
gt_inv(u, u);
r = (gt_cmp(u, a) == RLC_EQ);
break;
diff --git a/contrib/relic/src/pp/relic_pp_add_k12.c b/contrib/relic/src/pp/relic_pp_add_k12.c
index 2123388af..295e123a9 100644
--- a/contrib/relic/src/pp/relic_pp_add_k12.c
+++ b/contrib/relic/src/pp/relic_pp_add_k12.c
@@ -124,9 +124,9 @@ void pp_add_k12_projc_basic(fp12_t l, ep2_t r, ep2_t q, ep_t p) {
}
/* l10 = - (A * xp). */
- fp_mul(l[one][zero][0], t1[0], p->x);
- fp_mul(l[one][zero][1], t1[1], p->x);
- fp2_neg(l[one][zero], l[one][zero]);
+ fp_neg(t4[0], p->x);
+ fp_mul(l[one][zero][0], t1[0], t4[0]);
+ fp_mul(l[one][zero][1], t1[1], t4[0]);
/* t4 = B * x2. */
fp2_mul(t4, q->x, t1);
@@ -222,9 +222,9 @@ void pp_add_k12_projc_lazyr(fp12_t l, ep2_t r, ep2_t q, ep_t p) {
zero ^= 1;
}
- fp_mul(l[one][zero][0], t1[0], p->x);
- fp_mul(l[one][zero][1], t1[1], p->x);
- fp2_neg(l[one][zero], l[one][zero]);
+ fp_neg(t3[0], p->x);
+ fp_mul(l[one][zero][0], t1[0], t3[0]);
+ fp_mul(l[one][zero][1], t1[1], t3[0]);
#ifdef RLC_FP_ROOM
fp2_mulc_low(u0, q->x, t1);
diff --git a/contrib/relic/src/pp/relic_pp_add_k24.c b/contrib/relic/src/pp/relic_pp_add_k24.c
new file mode 100644
index 000000000..f64d499fe
--- /dev/null
+++ b/contrib/relic/src/pp/relic_pp_add_k24.c
@@ -0,0 +1,160 @@
+/*
+ * RELIC is an Efficient LIbrar->y for Cr->yptography
+ * Copyright (c) 2021 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 24.
+ *
+ * @ingroup pp
+ */
+
+#include "relic_core.h"
+#include "relic_pp.h"
+#include "relic_util.h"
+
+/*============================================================================*/
+/* Public definitions */
+/*============================================================================*/
+
+#if EP_ADD == BASIC || !defined(STRIP)
+
+void pp_add_k24_basic(fp24_t l, ep4_t r, ep4_t q, ep_t p) {
+ 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);
+
+ fp_mul(l[1][1][0][0], s[0][0], p->x);
+ fp_mul(l[1][1][0][1], s[0][1], p->x);
+ fp_mul(l[1][1][1][0], s[1][0], p->x);
+ fp_mul(l[1][1][1][1], s[1][1], p->x);
+
+ fp4_mul(l[0][0], s, t->x);
+ fp4_sub(l[0][0], t->y, l[0][0]);
+ fp4_mul_art(l[0][0], l[0][0]);
+
+ fp_neg(l[0][1][0][0], p->y);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ fp4_free(s);
+ ep4_free(t);
+ }
+}
+
+#endif
+
+#if EP_ADD == PROJC || !defined(STRIP)
+
+void pp_add_k24_projc(fp24_t l, ep4_t r, ep4_t q, ep_t p) {
+ fp4_t t0, t1, t2, t3, t4;
+
+ 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);
+
+ /* B = t0 = x1 - x2 * z1. */
+ fp4_mul(t0, r->z, q->x);
+ fp4_sub(t0, r->x, t0);
+ /* A = t1 = y1 - y2 * z1. */
+ fp4_mul(t1, r->z, q->y);
+ fp4_sub(t1, r->y, t1);
+
+ /* D = B^2. */
+ fp4_sqr(t2, t0);
+ /* G = x1 * D. */
+ fp4_mul(r->x, r->x, t2);
+ /* E = B^3. */
+ fp4_mul(t2, t2, t0);
+ /* C = A^2. */
+ fp4_sqr(t3, t1);
+ /* F = E + z1 * C. */
+ fp4_mul(t3, t3, r->z);
+ fp4_add(t3, t2, t3);
+
+ /* l10 = - (A * xp). */
+ fp_neg(t4[0][0], p->x);
+ fp_mul(l[1][1][0][0], t1[0][0], t4[0][0]);
+ fp_mul(l[1][1][0][1], t1[0][1], t4[0][0]);
+ fp_mul(l[1][1][1][0], t1[1][0], t4[0][0]);
+ fp_mul(l[1][1][1][1], t1[1][1], t4[0][0]);
+
+ /* t4 = B * x2. */
+ fp4_mul(t4, q->x, t1);
+
+ /* H = E + F - 2 * G. */
+ fp4_sub(t3, t3, r->x);
+ fp4_sub(t3, t3, r->x);
+ /* y3 = A * (G - H) - y1 * E. */
+ fp4_sub(r->x, r->x, t3);
+ fp4_mul(t1, t1, r->x);
+ fp4_mul(r->y, t2, r->y);
+ fp4_sub(r->y, t1, r->y);
+ /* x3 = B * H. */
+ fp4_mul(r->x, t0, t3);
+ /* z3 = z1 * E. */
+ fp4_mul(r->z, r->z, t2);
+
+ /* l11 = J = B * x2 - A * y2. */
+ fp4_mul(t2, q->y, t0);
+ fp4_sub(l[0][0], t4, t2);
+ fp4_mul_art(l[0][0], l[0][0]);
+
+ /* l00 = B * yp. */
+ fp_mul(l[0][1][0][0], p->y, t0[0][0]);
+ fp_mul(l[0][1][0][1], p->y, t0[0][1]);
+ fp_mul(l[0][1][1][0], p->y, t0[1][0]);
+ fp_mul(l[0][1][1][1], p->y, t0[1][1]);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ } RLC_FINALLY {
+ fp4_free(t0);
+ fp4_free(t1);
+ fp4_free(t2);
+ fp4_free(t3);
+ fp4_free(t4);
+ }
+}
+
+#endif
diff --git a/contrib/relic/src/pp/relic_pp_add_k48.c b/contrib/relic/src/pp/relic_pp_add_k48.c
index 0c96b61d0..225612b74 100644
--- a/contrib/relic/src/pp/relic_pp_add_k48.c
+++ b/contrib/relic/src/pp/relic_pp_add_k48.c
@@ -186,15 +186,15 @@ void pp_add_k48_projc(fp48_t l, fp8_t rx, fp8_t ry, fp8_t rz, fp8_t qx,
fp8_add(t3, t2, t3);
/* l10 = - (A * xp). */
- fp_mul(l[0][1][0][0][0], p->x, t1[0][0][0]);
- fp_mul(l[0][1][0][0][1], p->x, t1[0][0][1]);
- fp_mul(l[0][1][0][1][0], p->x, t1[0][1][0]);
- fp_mul(l[0][1][0][1][1], p->x, t1[0][1][1]);
- fp_mul(l[0][1][1][0][0], p->x, t1[1][0][0]);
- fp_mul(l[0][1][1][0][1], p->x, t1[1][0][1]);
- fp_mul(l[0][1][1][1][0], p->x, t1[1][1][0]);
- fp_mul(l[0][1][1][1][1], p->x, t1[1][1][1]);
- fp8_neg(l[0][1], l[0][1]);
+ fp_neg(t4[0][0][0], p->x);
+ fp_mul(l[0][1][0][0][0], t1[0][0][0], t4[0][0][0]);
+ fp_mul(l[0][1][0][0][1], t1[0][0][1], t4[0][0][0]);
+ fp_mul(l[0][1][0][1][0], t1[0][1][0], t4[0][0][0]);
+ fp_mul(l[0][1][0][1][1], t1[0][1][1], t4[0][0][0]);
+ fp_mul(l[0][1][1][0][0], t1[1][0][0], t4[0][0][0]);
+ fp_mul(l[0][1][1][0][1], t1[1][0][1], t4[0][0][0]);
+ fp_mul(l[0][1][1][1][0], t1[1][1][0], t4[0][0][0]);
+ fp_mul(l[0][1][1][1][1], t1[1][1][1], t4[0][0][0]);
/* t4 = B * x2. */
fp8_mul(t4, qx, t1);
diff --git a/contrib/relic/src/pp/relic_pp_add_k54.c b/contrib/relic/src/pp/relic_pp_add_k54.c
index 841c9b0d5..bdbdcde90 100644
--- a/contrib/relic/src/pp/relic_pp_add_k54.c
+++ b/contrib/relic/src/pp/relic_pp_add_k54.c
@@ -187,16 +187,16 @@ void pp_add_k54_projc(fp54_t l, fp9_t rx, fp9_t ry, fp9_t rz, fp9_t qx,
fp9_add(t3, t2, t3);
/* l10 = - (A * xp). */
- fp_mul(l[2][0][0][0], p->x, t1[0][0]);
- fp_mul(l[2][0][0][1], p->x, t1[0][1]);
- fp_mul(l[2][0][0][2], p->x, t1[0][2]);
- fp_mul(l[2][0][1][0], p->x, t1[1][0]);
- fp_mul(l[2][0][1][1], p->x, t1[1][1]);
- fp_mul(l[2][0][1][2], p->x, t1[1][2]);
- fp_mul(l[2][0][2][0], p->x, t1[2][0]);
- fp_mul(l[2][0][2][1], p->x, t1[2][1]);
- fp_mul(l[2][0][2][2], p->x, t1[2][2]);
- fp9_neg(l[2][0], l[2][0]);
+ fp_neg(t4[0][0], p->x);
+ fp_mul(l[2][0][0][0], t1[0][0], t4[0][0]);
+ fp_mul(l[2][0][0][1], t1[0][1], t4[0][0]);
+ fp_mul(l[2][0][0][2], t1[0][2], t4[0][0]);
+ fp_mul(l[2][0][1][0], t1[1][0], t4[0][0]);
+ fp_mul(l[2][0][1][1], t1[1][1], t4[0][0]);
+ fp_mul(l[2][0][1][2], t1[1][2], t4[0][0]);
+ fp_mul(l[2][0][2][0], t1[2][0], t4[0][0]);
+ fp_mul(l[2][0][2][1], t1[2][1], t4[0][0]);
+ fp_mul(l[2][0][2][2], t1[2][2], t4[0][0]);
/* t4 = B * x2. */
fp9_mul(t4, qx, t1);
diff --git a/contrib/relic/src/pp/relic_pp_dbl_k12.c b/contrib/relic/src/pp/relic_pp_dbl_k12.c
index f6bcf48ea..743eb365a 100644
--- a/contrib/relic/src/pp/relic_pp_dbl_k12.c
+++ b/contrib/relic/src/pp/relic_pp_dbl_k12.c
@@ -54,7 +54,6 @@ void pp_dbl_k12_basic(fp12_t l, ep2_t r, ep2_t q, ep_t p) {
ep2_new(t);
ep2_copy(t, q);
ep2_dbl_slp_basic(r, s, q);
- fp12_zero(l);
if (ep2_curve_is_twist() == RLC_EP_MTYPE) {
one ^= 1;
diff --git a/contrib/relic/src/pp/relic_pp_dbl_k24.c b/contrib/relic/src/pp/relic_pp_dbl_k24.c
new file mode 100644
index 000000000..3935047ae
--- /dev/null
+++ b/contrib/relic/src/pp/relic_pp_dbl_k24.c
@@ -0,0 +1,177 @@
+/*
+ * RELIC is an Efficient LIbrar->y for Cr->yptography
+ * 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 pairing computation for curves with embedding degree 24.
+ *
+ * @ingroup pp
+ */
+
+#include "relic_core.h"
+#include "relic_pp.h"
+#include "relic_util.h"
+
+/*============================================================================*/
+/* Public definitions */
+/*============================================================================*/
+
+#if EP_ADD == PROJC || !defined(STRIP)
+
+void pp_dbl_k24_basic(fp24_t l, ep4_t r, ep4_t q, ep_t p) {
+ fp4_t s;
+ ep4_t t;
+
+ 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);
+ fp24_zero(l);
+
+ fp_mul(l[1][1][0][0], s[0][0], p->x);
+ fp_mul(l[1][1][0][1], s[0][1], p->x);
+ fp_mul(l[1][1][1][0], s[1][0], p->x);
+ fp_mul(l[1][1][1][1], s[1][1], p->x);
+
+ fp4_mul(l[0][0], s, t->x);
+ fp4_sub(l[0][0], t->y, l[0][0]);
+ fp4_mul_art(l[0][0], l[0][0]);
+
+ fp_copy(l[0][1][0][0], p->y);
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ fp2_free(s);
+ ep4_free(t);
+ }
+}
+
+#endif
+
+#if EP_ADD == PROJC || !defined(STRIP)
+
+void pp_dbl_k24_projc(fp24_t l, ep4_t r, ep4_t q, ep_t p) {
+ fp4_t t0, t1, t2, t3, t4, t5, t6;
+
+ fp4_null(t0);
+ fp4_null(t1);
+ fp4_null(t2);
+ fp4_null(t3);
+ fp4_null(t4);
+ fp4_null(t5);
+ fp4_null(t6);
+
+ RLC_TRY {
+ fp4_new(t0);
+ fp4_new(t1);
+ fp4_new(t2);
+ fp4_new(t3);
+ fp4_new(t4);
+ fp4_new(t5);
+ fp4_new(t6);
+
+ /* A = x1^2. */
+ fp4_sqr(t0, q->x);
+ /* B = y1^2. */
+ fp4_sqr(t1, q->y);
+ /* C = z1^2. */
+ fp4_sqr(t2, q->z);
+ /* D = 3bC, general b. */
+ fp4_dbl(t3, t2);
+ fp4_add(t3, t3, t2);
+ ep4_curve_get_b(t4);
+ fp4_mul(t3, t3, t4);
+
+ /* E = (x1 + y1)^2 - A - B. */
+ fp4_add(t4, q->x, q->y);
+ fp4_sqr(t4, t4);
+ fp4_sub(t4, t4, t0);
+ fp4_sub(t4, t4, t1);
+
+ /* F = (y1 + z1)^2 - B - C. */
+ fp4_add(t5, q->y, q->z);
+ fp4_sqr(t5, t5);
+ fp4_sub(t5, t5, t1);
+ fp4_sub(t5, t5, t2);
+
+ /* G = 3D. */
+ fp4_dbl(t6, t3);
+ fp4_add(t6, t6, t3);
+
+ /* x3 = E * (B - G). */
+ fp4_sub(r->x, t1, t6);
+ fp4_mul(r->x, r->x, t4);
+
+ /* y3 = (B + G)^2 -12D^2. */
+ fp4_add(t6, t6, t1);
+ fp4_sqr(t6, t6);
+ fp4_sqr(t2, t3);
+ fp4_dbl(r->y, t2);
+ fp4_dbl(t2, r->y);
+ fp4_dbl(r->y, t2);
+ fp4_add(r->y, r->y, t2);
+ fp4_sub(r->y, t6, r->y);
+
+ /* z3 = 4B * F. */
+ fp4_dbl(r->z, t1);
+ fp4_dbl(r->z, r->z);
+ fp4_mul(r->z, r->z, t5);
+
+ /* l11 = D - B. */
+ fp4_sub(l[0][0], t3, t1);
+ fp4_mul_art(l[0][0], l[0][0]);
+
+ /* l10 = (3 * xp) * A. */
+ fp_mul(l[1][1][0][0], p->x, t0[0][0]);
+ fp_mul(l[1][1][0][1], p->x, t0[0][1]);
+ fp_mul(l[1][1][1][0], p->x, t0[1][0]);
+ fp_mul(l[1][1][1][1], p->x, t0[1][1]);
+
+ /* l00 = F * (-yp). */
+ fp_mul(l[0][1][0][0], p->y, t5[0][0]);
+ fp_mul(l[0][1][0][1], p->y, t5[0][1]);
+ fp_mul(l[0][1][1][0], p->y, t5[1][0]);
+ fp_mul(l[0][1][1][1], p->y, t5[1][1]);
+ }
+ 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
diff --git a/contrib/relic/src/pp/relic_pp_exp_k24.c b/contrib/relic/src/pp/relic_pp_exp_k24.c
new file mode 100644
index 000000000..7f075d680
--- /dev/null
+++ b/contrib/relic/src/pp/relic_pp_exp_k24.c
@@ -0,0 +1,107 @@
+/*
+ * 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 24.
+ *
+ * @ingroup pp
+ */
+
+#include "relic_core.h"
+#include "relic_pp.h"
+#include "relic_util.h"
+
+/*============================================================================*/
+/* Public definitions */
+/*============================================================================*/
+
+void pp_exp_k24(fp24_t c, fp24_t a) {
+ fp24_t t[8];
+ const int *b;
+ bn_t x;
+ int l;
+
+ bn_null(x);
+
+ RLC_TRY {
+ bn_new(x);
+ for (int i = 0; i < 8; i++) {
+ fp24_null(t[i]);
+ fp24_new(t[i]);
+ }
+
+ fp_prime_get_par(x);
+ b = fp_prime_get_par_sps(&l);
+ /* First, compute m^(p^12 - 1)(p^4 + 1). */
+ fp24_conv_cyc(c, a);
+
+ /* v7 = f^x. */
+ fp24_exp_cyc_sps(t[7], c, b, l, bn_sign(x));
+
+ /* v6 = f^(-2x + 1). */
+ fp24_sqr_cyc(t[6], t[7]);
+ fp24_inv_cyc(t[6], t[6]);
+ fp24_mul(t[6], t[6], c);
+
+ /* v7 = f^(x^2 - 2x + 1). */
+ fp24_exp_cyc_sps(t[7], t[7], b, l, bn_sign(x));
+ fp24_mul(t[7], t[7], t[6]);
+
+ fp24_exp_cyc_sps(t[6], t[7], b, l, bn_sign(x));
+
+ fp24_exp_cyc_sps(t[5], t[6], b, l, bn_sign(x));
+
+ fp24_exp_cyc_sps(t[4], t[5], b, l, bn_sign(x));
+
+ fp24_exp_cyc_sps(t[3], t[4], b, l, bn_sign(x));
+ fp24_inv_cyc(t[2], t[7]);
+ fp24_mul(t[3], t[3], t[2]);
+
+ fp24_exp_cyc_sps(t[2], t[3], b, l, bn_sign(x));
+
+ fp24_exp_cyc_sps(t[1], t[2], b, l, bn_sign(x));
+
+ /* c = c^3. */
+ fp24_sqr_cyc(t[0], c);
+ fp24_mul(c, c, t[0]);
+
+ fp24_exp_cyc_sps(t[0], t[1], b, l, bn_sign(x));
+
+ fp24_mul(c, c, t[0]);
+ for (int i = 1; i < 8; i++) {
+ fp24_frb(t[i], t[i], i);
+ fp24_mul(c, c, t[i]);
+ }
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ bn_free(x);
+ for (int i = 0; i < 8; i++) {
+ fp24_free(t[i]);
+ }
+ }
+}
diff --git a/contrib/relic/src/pp/relic_pp_map.c b/contrib/relic/src/pp/relic_pp_map.c
index a718f36fc..389c13bda 100644
--- a/contrib/relic/src/pp/relic_pp_map.c
+++ b/contrib/relic/src/pp/relic_pp_map.c
@@ -39,8 +39,10 @@
void pp_map_init(void) {
ep2_curve_init();
+ ep4_curve_init();
}
void pp_map_clean(void) {
ep2_curve_clean();
+ ep4_curve_clean();
}
diff --git a/contrib/relic/src/pp/relic_pp_map_k12.c b/contrib/relic/src/pp/relic_pp_map_k12.c
index 94d5b0e52..8f4f35ba6 100644
--- a/contrib/relic/src/pp/relic_pp_map_k12.c
+++ b/contrib/relic/src/pp/relic_pp_map_k12.c
@@ -393,7 +393,7 @@ void pp_map_sim_weilp_k12(fp12_t r, ep_t *p, ep2_t *q, int m) {
fp12_null(r0);
fp12_null(r1);
- bn_null(r);
+ bn_null(n);
RLC_TRY {
fp12_new(r0);
diff --git a/contrib/relic/src/pp/relic_pp_map_k24.c b/contrib/relic/src/pp/relic_pp_map_k24.c
new file mode 100644
index 000000000..70af03e18
--- /dev/null
+++ b/contrib/relic/src/pp/relic_pp_map_k24.c
@@ -0,0 +1,249 @@
+/*
+ * 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 pairing computation for curves with embedding degree 12.
+ *
+ * @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_k24(fp24_t r, ep4_t *t, ep4_t *q, ep_t *p, int m, bn_t a) {
+ fp24_t l;
+ ep_t *_p = RLC_ALLOCA(ep_t, m);
+ ep4_t *_q = RLC_ALLOCA(ep4_t, m);
+ int i, j, len = bn_bits(a) + 1;
+ int8_t s[RLC_FP_BITS + 1];
+
+ if (m == 0) {
+ return;
+ }
+
+ fp24_null(l);
+
+ RLC_TRY {
+ fp24_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_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
+ }
+
+ fp24_zero(l);
+ bn_rec_naf(s, &len, a, 2);
+ pp_dbl_k24(r, t[0], t[0], _p[0]);
+ for (j = 1; j < m; j++) {
+ pp_dbl_k24(l, t[j], t[j], _p[j]);
+ fp24_mul_dxs(r, r, l);
+ }
+ if (s[len - 2] > 0) {
+ for (j = 0; j < m; j++) {
+ pp_add_k24(l, t[j], q[j], p[j]);
+ fp24_mul_dxs(r, r, l);
+ }
+ }
+ if (s[len - 2] < 0) {
+ for (j = 0; j < m; j++) {
+ pp_add_k24(l, t[j], _q[j], p[j]);
+ fp24_mul_dxs(r, r, l);
+ }
+ }
+
+ for (i = len - 3; i >= 0; i--) {
+ fp24_sqr(r, r);
+ for (j = 0; j < m; j++) {
+ pp_dbl_k24(l, t[j], t[j], _p[j]);
+ fp24_mul(r, r, l);
+ if (s[i] > 0) {
+ pp_add_k24(l, t[j], q[j], p[j]);
+ fp24_mul_dxs(r, r, l);
+ }
+ if (s[i] < 0) {
+ pp_add_k24(l, t[j], _q[j], p[j]);
+ fp24_mul_dxs(r, r, l);
+ }
+ }
+ }
+ }
+ RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ }
+ RLC_FINALLY {
+ fp24_free(l);
+ for (j = 0; j < m; j++) {
+ ep_free(_p[j]);
+ ep4_free(_q[j]);
+ }
+ RLC_FREE(_p);
+ RLC_FREE(_q);
+ }
+}
+
+/*============================================================================*/
+/* Public definitions */
+/*============================================================================*/
+
+#if PP_MAP == OATEP || !defined(STRIP)
+
+void pp_map_k24(fp24_t r, ep_t p, 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);
+ fp24_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_B24:
+ /* r = f_{|a|,Q}(P). */
+ 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;
+ }
+ }
+ }
+ 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_k24(fp24_t r, ep_t *p, 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);
+ fp24_set_dig(r, 1);
+
+ if (j > 0) {
+ switch (ep_curve_is_pairf()) {
+ case EP_B24:
+ /* r = f_{|a|,Q}(P). */
+ pp_mil_k24(r, t, _q, _p, j, a);
+ if (bn_sign(a) == RLC_NEG) {
+ fp24_inv_cyc(r, r);
+ }
+ pp_exp_k24(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/contrib/relic/src/pp/relic_pp_norm.c b/contrib/relic/src/pp/relic_pp_norm.c
index 535c771ae..b2a8f8521 100644
--- a/contrib/relic/src/pp/relic_pp_norm.c
+++ b/contrib/relic/src/pp/relic_pp_norm.c
@@ -77,8 +77,26 @@ void pp_norm_k12(ep2_t r, ep2_t p) {
fp2_inv(r->z, p->z);
fp2_mul(r->x, p->x, r->z);
fp2_mul(r->y, p->y, r->z);
- fp_set_dig(r->z[0], 1);
- fp_zero(r->z[1]);
+ fp2_set_dig(r->z, 1);
+ r->coord = BASIC;
+#endif
+}
+
+void pp_norm_k24(ep4_t r, ep4_t p) {
+ if (ep4_is_infty(p)) {
+ ep4_set_infty(r);
+ return;
+ }
+
+ if (p->coord) {
+ /* 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);
+ fp4_set_dig(r->z, 1);
r->coord = BASIC;
#endif
}
diff --git a/contrib/relic/src/rand/relic_rand_call.c b/contrib/relic/src/rand/relic_rand_call.c
index 2422a2579..f59236be6 100644
--- a/contrib/relic/src/rand/relic_rand_call.c
+++ b/contrib/relic/src/rand/relic_rand_call.c
@@ -77,6 +77,9 @@ void rand_bytes(uint8_t *buf, int size) {
ctx_t *ctx = core_get();
ctx->rand_call(buf, size, ctx->rand_args);
+ if (rand_check(buf, size) == RLC_ERR) {
+ RLC_THROW(ERR_NO_RAND);
+ }
}
void rand_seed(void (*callback)(uint8_t *, int, void *), void *args) {
diff --git a/contrib/relic/src/rand/relic_rand_core.c b/contrib/relic/src/rand/relic_rand_core.c
index 5ddf6bd27..10f8929f8 100644
--- a/contrib/relic/src/rand/relic_rand_core.c
+++ b/contrib/relic/src/rand/relic_rand_core.c
@@ -75,6 +75,9 @@
#define RLC_RAND_PATH "/dev/urandom"
#endif
+/** The maximum number of bytes that can be repeated in the output. */
+#define RAND_REP 6
+
/*============================================================================*/
/* Public definitions */
/*============================================================================*/
@@ -180,6 +183,23 @@ void rand_init(void) {
#endif
}
+int rand_check(uint8_t *buf, int size) {
+ int count = 0;
+
+ for (int i = 1; i < size; i++) {
+ if (buf[i] == buf[i - 1]) {
+ count++;
+ } else {
+ count = 0;
+ }
+ }
+
+ if (count > RAND_REP) {
+ return RLC_ERR;
+ }
+ return RLC_OK;
+}
+
void rand_clean(void) {
ctx_t *ctx = core_get();
if (ctx != NULL) {
diff --git a/contrib/relic/src/relic_core.c b/contrib/relic/src/relic_core.c
index 7a5e6726c..5ec5cf04f 100644
--- a/contrib/relic/src/relic_core.c
+++ b/contrib/relic/src/relic_core.c
@@ -34,6 +34,7 @@
#include
#include "relic_core.h"
+#include "relic_bench.h"
#include "relic_multi.h"
#include "relic_rand.h"
#include "relic_types.h"
@@ -68,6 +69,8 @@
#define MSG_NO_CURVE "no curve supported at this security level"
/** Error message respective to ERR_NO_CONFIG. */
#define MSG_NO_CONFIG "invalid library configuration"
+/** Error message respective to ERR_NO_CURVE. */
+#define MSG_NO_RAND "faulty pseudo-random number generator"
/*============================================================================*/
/* Public definitions */
@@ -111,6 +114,7 @@ int core_init(void) {
core_ctx->reason[ERR_NO_FIELD] = MSG_NO_FIELD;
core_ctx->reason[ERR_NO_CURVE] = MSG_NO_CURVE;
core_ctx->reason[ERR_NO_CONFIG] = MSG_NO_CONFIG;
+ core_ctx->reason[ERR_NO_RAND] = MSG_NO_RAND;
core_ctx->last = NULL;
#endif /* CHECK */
diff --git a/contrib/relic/test/test_bn.c b/contrib/relic/test/test_bn.c
index 3b8abde97..ab5eff825 100644
--- a/contrib/relic/test/test_bn.c
+++ b/contrib/relic/test/test_bn.c
@@ -180,12 +180,16 @@ static int util(void) {
TEST_END;
TEST_CASE("generating a random integer is consistent") {
- bn_rand(b, RLC_POS, RLC_BN_BITS);
+ do {
+ bn_rand(b, RLC_POS, RLC_BN_BITS);
+ } while (bn_is_zero(b));
bn_rand_mod(a, b);
TEST_ASSERT(bn_sign(a) == bn_sign(b), end);
TEST_ASSERT(bn_is_zero(a) == 0, end);
TEST_ASSERT(bn_cmp(a, b) == RLC_LT, end);
- bn_rand(b, RLC_NEG, RLC_DIG);
+ do {
+ bn_rand(b, RLC_NEG, RLC_DIG);
+ } while (bn_bits(b) <= 1);
bn_rand_mod(a, b);
TEST_ASSERT(bn_sign(a) == bn_sign(b), end);
TEST_ASSERT(bn_is_zero(a) == 0, end);
@@ -1305,7 +1309,7 @@ static int lcm(void) {
}
static int symbol(void) {
- int code = RLC_ERR;
+ int r, code = RLC_ERR;
bn_t a, b, c, p, q;
bn_null(a);
@@ -1327,35 +1331,33 @@ static int symbol(void) {
} while (bn_is_even(p) || bn_is_even(q));
TEST_CASE("legendre symbol is correct") {
- bn_smb_leg(c, p, p);
- TEST_ASSERT(bn_is_zero(c) == 1, end);
+ TEST_ASSERT(bn_smb_leg(p, p) == 0, end);
bn_rand(a, RLC_POS, RLC_BN_BITS);
bn_sqr(a, a);
bn_mod(a, a, p);
- bn_smb_leg(c, a, p);
- TEST_ASSERT(bn_cmp_dig(c, 1) == RLC_EQ, end);
+ TEST_ASSERT(bn_smb_leg(a, p) == 1, end);
bn_rand(a, RLC_POS, RLC_BN_BITS);
- bn_smb_leg(c, a, p);
- bn_set_dig(a, 1);
- TEST_ASSERT(bn_cmp_abs(c, a) == RLC_EQ, end);
+ r = bn_smb_leg(a, p);
+ TEST_ASSERT(r == 1 || r == -1, end);
} TEST_END;
TEST_CASE("legendre symbol is a homomorphism") {
bn_rand(a, RLC_POS, RLC_BN_BITS / 2);
bn_rand(b, RLC_POS, RLC_BN_BITS / 2);
bn_mul(c, a, b);
- bn_smb_leg(a, a, p);
- bn_smb_leg(b, b, p);
- bn_smb_leg(c, c, p);
- bn_mul(a, a, b);
- TEST_ASSERT(bn_cmp(a, c) == RLC_EQ, end);
+ r = bn_smb_leg(a, p) * bn_smb_leg(b, p);
+ TEST_ASSERT(r == bn_smb_leg(c, p), end);
} TEST_END;
TEST_ONCE("legendre symbol satisfies quadratic reciprocity") {
/* Check the first supplement: (-1|p) = (-1)^(p-1)/2. */
bn_set_dig(a, 1);
bn_neg(a, a);
- bn_smb_leg(b, a, p);
+ r = bn_smb_leg(a, p);
+ bn_set_dig(b, (r < 0 ? -r : r));
+ if (r < 0) {
+ bn_neg(b, b);
+ }
bn_sub_dig(c, p, 1);
bn_rsh(c, c, 1);
if (bn_is_even(c)) {
@@ -1364,7 +1366,11 @@ static int symbol(void) {
TEST_ASSERT(bn_cmp(a, b) == RLC_EQ, end);
/* Check second supplement: (2|p) = (-1)^(p^2-1)/8. */
bn_set_dig(a, 2);
- bn_smb_leg(b, a, p);
+ r = bn_smb_leg(a, p);
+ bn_set_dig(b, (r < 0 ? -r : r));
+ if (r < 0) {
+ bn_neg(b, b);
+ }
bn_sqr(c, p);
bn_sub_dig(c, c, 1);
bn_rsh(c, c, 3);
@@ -1374,8 +1380,16 @@ static int symbol(void) {
}
TEST_ASSERT(bn_cmp(a, b) == RLC_EQ, end);
/* Check quadratic reciprocity law. */
- bn_smb_leg(a, q, p);
- bn_smb_leg(b, p, q);
+ r = bn_smb_leg(q, p);
+ bn_set_dig(a, (r < 0 ? -r : r));
+ if (r < 0) {
+ bn_neg(a, a);
+ }
+ r = bn_smb_leg(p, q);
+ bn_set_dig(b, (r < 0 ? -r : r));
+ if (r < 0) {
+ bn_neg(b, b);
+ }
bn_sub_dig(c, p, 1);
bn_rsh(c, c, 1);
if (!bn_is_even(c)) {
@@ -1390,9 +1404,7 @@ static int symbol(void) {
TEST_CASE("jacobi symbol is correct") {
bn_rand(a, RLC_POS, RLC_BN_BITS);
- bn_smb_leg(c, a, p);
- bn_smb_jac(b, a, p);
- TEST_ASSERT(bn_cmp_abs(c, b) == RLC_EQ, end);
+ TEST_ASSERT(bn_smb_leg(a, p) == bn_smb_jac(a, p), end);
} TEST_END;
TEST_CASE("jacobi symbol is a homomorphism") {
@@ -1403,11 +1415,8 @@ static int symbol(void) {
bn_add_dig(p, p, 1);
}
bn_mul(c, a, b);
- bn_smb_jac(a, a, p);
- bn_smb_jac(b, b, p);
- bn_smb_jac(c, c, p);
- bn_mul(a, a, b);
- TEST_ASSERT(bn_cmp(a, c) == RLC_EQ, end);
+ r = bn_smb_jac(a, p) * bn_smb_jac(b, p);
+ TEST_ASSERT(r == bn_smb_jac(c, p), end);
} TEST_END;
TEST_CASE("jacobi symbol is consistent with gcd") {
@@ -1416,13 +1425,16 @@ static int symbol(void) {
if (bn_is_even(p)) {
bn_add_dig(p, p, 1);
}
- bn_smb_jac(c, a, p);
+ r = bn_smb_jac(a, p);
+ bn_set_dig(c, (r < 0 ? -r : r));
+ if (r < 0) {
+ bn_neg(c, c);
+ }
bn_gcd(b, a, p);
if (bn_cmp_dig(b, 1) != RLC_EQ) {
- TEST_ASSERT(bn_is_zero(c), end);
+ TEST_ASSERT(r == 0, end);
} else {
- bn_set_dig(a, 1);
- TEST_ASSERT(bn_cmp_abs(c, a) == RLC_EQ, end);
+ TEST_ASSERT(r == 1 || r == -1, end);
}
} TEST_END;
@@ -1438,7 +1450,11 @@ static int symbol(void) {
/* Check the first supplement: (-1|n) = (-1)^(n-1)/2. */
bn_set_dig(a, 1);
bn_neg(a, a);
- bn_smb_jac(b, a, p);
+ r = bn_smb_jac(a, p);
+ bn_set_dig(b, (r < 0 ? -r : r));
+ if (r < 0) {
+ bn_neg(b, b);
+ }
bn_sub_dig(c, p, 1);
bn_rsh(c, c, 1);
if (bn_is_even(c)) {
@@ -1447,7 +1463,11 @@ static int symbol(void) {
TEST_ASSERT(bn_cmp(a, b) == RLC_EQ, end);
/* Check second supplement: (2|p) = (-1)^(p^2-1)/8. */
bn_set_dig(a, 2);
- bn_smb_jac(b, a, p);
+ r = bn_smb_jac(a, p);
+ bn_set_dig(b, (r < 0 ? -r : r));
+ if (r < 0) {
+ bn_neg(b, b);
+ }
bn_sqr(c, p);
bn_sub_dig(c, c, 1);
bn_rsh(c, c, 3);
@@ -1457,8 +1477,16 @@ static int symbol(void) {
}
TEST_ASSERT(bn_cmp(a, b) == RLC_EQ, end);
/* Check quadratic reciprocity law. */
- bn_smb_jac(a, p, q);
- bn_smb_jac(b, q, p);
+ r = bn_smb_jac(p, q);
+ bn_set_dig(a, (r < 0 ? -r : r));
+ if (r < 0) {
+ bn_neg(a, a);
+ }
+ r = bn_smb_jac(q, p);
+ bn_set_dig(b, (r < 0 ? -r : r));
+ if (r < 0) {
+ bn_neg(b, b);
+ }
bn_sub_dig(c, p, 1);
bn_rsh(c, c, 1);
if (!bn_is_even(c)) {
@@ -1738,16 +1766,20 @@ static int small_primes(void) {
static int inversion(void) {
int code = RLC_ERR;
- bn_t a, b, c;
+ bn_t a, b, c, d[2];
bn_null(a);
bn_null(b);
bn_null(c);
+ bn_null(d[0]);
+ bn_null(d[1]);
RLC_TRY {
bn_new(a);
bn_new(b);
bn_new(c);
+ bn_new(d[0]);
+ bn_new(d[1]);
bn_gen_prime(a, RLC_BN_BITS);
@@ -1758,6 +1790,17 @@ static int inversion(void) {
bn_mul(c, b, c);
bn_mod(c, c, a);
TEST_ASSERT(bn_cmp_dig(c, 1) == RLC_EQ, end);
+ bn_rand_mod(b, a);
+ bn_rand_mod(c, a);
+ bn_copy(d[0], b);
+ bn_copy(d[1], c);
+ bn_mod_inv_sim(d, d, a, 2);
+ bn_mul(b, b, d[0]);
+ bn_mod(b, b, a);
+ bn_mul(c, c, d[1]);
+ bn_mod(c, c, a);
+ TEST_ASSERT(bn_cmp_dig(b, 1) == RLC_EQ, end);
+ TEST_ASSERT(bn_cmp_dig(c, 1) == RLC_EQ, end);
} TEST_END;
}
RLC_CATCH_ANY {
@@ -1768,6 +1811,8 @@ static int inversion(void) {
bn_free(a);
bn_free(b);
bn_free(c);
+ bn_free(d[0]);
+ bn_free(d[1]);
return code;
}
@@ -1811,7 +1856,7 @@ static int recoding(void) {
bn_t a, b, c, v1[3], v2[3];
int w, k, l;
uint8_t d[RLC_BN_BITS + 1];
- signed char e[2 * (RLC_BN_BITS + 1)];
+ int8_t e[2 * (RLC_BN_BITS + 1)];
bn_null(a);
bn_null(b);
diff --git a/contrib/relic/test/test_core.c b/contrib/relic/test/test_core.c
index 4cdabdb22..a7642f08f 100644
--- a/contrib/relic/test/test_core.c
+++ b/contrib/relic/test/test_core.c
@@ -34,6 +34,7 @@
#include "relic.h"
#include "relic_test.h"
+#if defined(MULTI)
#if MULTI == PTHREAD
void *master(void *ptr) {
@@ -61,6 +62,7 @@ void *tester(void *ptr) {
return NULL;
}
+#endif
#endif
int main(void) {
@@ -100,6 +102,7 @@ int main(void) {
code = RLC_OK;
+#if defined(MULTI)
#if MULTI == OPENMP
TEST_ONCE("library context is thread-safe") {
omp_set_num_threads(CORES);
@@ -158,6 +161,7 @@ int main(void) {
}
TEST_ASSERT(code == RLC_OK, end);
} TEST_END;
+#endif
#endif
util_banner("All tests have passed.\n", 0);
diff --git a/contrib/relic/test/test_cp.c b/contrib/relic/test/test_cp.c
index cdba96433..0a4a15959 100644
--- a/contrib/relic/test/test_cp.c
+++ b/contrib/relic/test/test_cp.c
@@ -462,7 +462,7 @@ static int ecies(void) {
ec_new(q_b);
l = ec_param_level();
- if (l == 128 || l == 192 || l == 256) {
+ if (l == 80 || l == 128 || l == 192 || l == 256) {
TEST_CASE("ecies encryption/decryption is correct") {
TEST_ASSERT(cp_ecies_gen(da, qa) == RLC_OK, end);
in_len = RLC_BC_LEN - 1;
@@ -673,10 +673,520 @@ static int vbnn(void) {
return code;
}
+static int pok(void) {
+ int code = RLC_ERR;
+ bn_t c[2], n, r[2], x;
+ ec_t y[2];
+
+ bn_null(n);
+ bn_null(x);
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(x);
+ for (int i = 0; i < 2; i++) {
+ bn_null(c[i]);
+ bn_null(r[i]);
+ ec_null(y[i]);
+ bn_new(c[i]);
+ bn_new(r[i]);
+ ec_new(y[i]);
+ }
+ ec_curve_get_ord(n);
+
+ TEST_CASE("proof of knowledge of discrete logarithm is correct") {
+ bn_rand_mod(x, n);
+ ec_mul_gen(y[0], x);
+ TEST_ASSERT(cp_pokdl_prv(c[0], r[0], y[0], x) == RLC_OK, end);
+ TEST_ASSERT(cp_pokdl_ver(c[0], r[0], y[0]) == 1, end);
+ ec_dbl(y[0], y[0]);
+ ec_norm(y[0], y[0]);
+ TEST_ASSERT(cp_pokdl_ver(c[0], r[0], y[0]) == 0, end);
+ } TEST_END;
+
+ TEST_CASE("proof of knowledge of disjunction is correct") {
+ bn_rand_mod(x, n);
+ do {
+ ec_rand(y[0]);
+ ec_mul_gen(y[1], x);
+ } while (ec_cmp(y[0], y[1]) == RLC_EQ);
+ TEST_ASSERT(cp_pokor_prv(c, r, y, x) == RLC_OK, end);
+ TEST_ASSERT(cp_pokor_ver(c, r, y) == 1, end);
+ ec_dbl(y[1], y[1]);
+ ec_norm(y[1], y[1]);
+ TEST_ASSERT(cp_pokor_ver(c, r, y) == 0, end);
+ } TEST_END;
+ }
+ RLC_CATCH_ANY {
+ RLC_ERROR(end);
+ }
+ code = RLC_OK;
+
+end:
+ bn_free(n);
+ bn_free(x);
+ for (int i = 0; i < 2; i++) {
+ bn_free(c[i]);
+ bn_free(r[i]);
+ ec_free(y[i]);
+ }
+ return code;
+}
+
+static int sok(void) {
+ int code = RLC_ERR;
+ bn_t c[2], n, r[2], x;
+ ec_t g[2], y[2];
+ uint8_t m[5] = { 0, 1, 2, 3, 4 };
+
+ bn_null(n);
+ bn_null(x);
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(x);
+ for (int i = 0; i < 2; i++) {
+ bn_null(c[i]);
+ bn_null(r[i]);
+ ec_null(g[i]);
+ ec_null(y[i]);
+ bn_new(c[i]);
+ bn_new(r[i]);
+ ec_new(g[i]);
+ ec_new(y[i]);
+ }
+ ec_curve_get_ord(n);
+
+ TEST_CASE("signature of knowledge of discrete logarithm is correct") {
+ bn_rand_mod(x, n);
+ ec_mul_gen(y[0], x);
+ TEST_ASSERT(cp_sokdl_sig(c[0], r[0], m, 5, y[0], x) == RLC_OK, end);
+ TEST_ASSERT(cp_sokdl_ver(c[0], r[0], m, 5, y[0]) == 1, end);
+ ec_dbl(y[0], y[0]);
+ ec_norm(y[0], y[0]);
+ TEST_ASSERT(cp_sokdl_ver(c[0], r[0], m, 5, y[0]) == 0, end);
+ } TEST_END;
+
+ TEST_CASE("signature of knowledge of disjunction is correct") {
+ bn_rand_mod(x, n);
+ do {
+ ec_rand(y[0]);
+ ec_mul_gen(y[1], x);
+ } while (ec_cmp(y[0], y[1]) == RLC_EQ);
+ TEST_ASSERT(cp_sokor_sig(c, r, m, 5, y, NULL, x, 0) == RLC_OK, end);
+ TEST_ASSERT(cp_sokor_ver(c, r, m, 5, y, NULL) == 1, end);
+ ec_dbl(y[1], y[1]);
+ ec_norm(y[1], y[1]);
+ TEST_ASSERT(cp_sokor_ver(c, r, m, 5, y, NULL) == 0, end);
+ do {
+ ec_mul_gen(y[0], x);
+ ec_rand(y[1]);
+ } while (ec_cmp(y[0], y[1]) == RLC_EQ);
+ TEST_ASSERT(cp_sokor_sig(c, r, m, 5, y, NULL, x, 1) == RLC_OK, end);
+ TEST_ASSERT(cp_sokor_ver(c, r, m, 5, y, NULL) == 1, end);
+ ec_dbl(y[0], y[0]);
+ ec_norm(y[0], y[0]);
+ TEST_ASSERT(cp_sokor_ver(c, r, m, 5, y, NULL) == 0, end);
+ do {
+ ec_curve_get_gen(g[0]);
+ ec_rand(g[1]);
+ ec_rand(y[0]);
+ ec_mul(y[1], g[1], x);
+ } while (ec_cmp(y[0], y[1]) == RLC_EQ);
+ TEST_ASSERT(cp_sokor_sig(c, r, m, 5, y, g, x, 0) == RLC_OK, end);
+ TEST_ASSERT(cp_sokor_ver(c, r, m, 5, y, g) == 1, end);
+ ec_dbl(y[1], y[1]);
+ ec_norm(y[1], y[1]);
+ TEST_ASSERT(cp_sokor_ver(c, r, m, 5, y, g) == 0, end);
+ do {
+ ec_rand(g[0]);
+ ec_mul(y[0], g[0], x);
+ ec_curve_get_gen(g[1]);
+ ec_rand(y[1]);
+ } while (ec_cmp(y[0], y[1]) == RLC_EQ);
+ TEST_ASSERT(cp_sokor_sig(c, r, m, 5, y, g, x, 1) == RLC_OK, end);
+ TEST_ASSERT(cp_sokor_ver(c, r, m, 5, y, g) == 1, end);
+ ec_dbl(y[0], y[0]);
+ ec_norm(y[0], y[0]);
+ TEST_ASSERT(cp_sokor_ver(c, r, m, 5, y, g) == 0, end);
+ } TEST_END;
+ }
+ RLC_CATCH_ANY {
+ RLC_ERROR(end);
+ }
+ code = RLC_OK;
+
+end:
+ bn_free(n);
+ bn_free(x);
+ for (int i = 0; i < 2; i++) {
+ bn_free(c[i]);
+ bn_free(r[i]);
+ ec_free(g[i]);
+ ec_free(y[i]);
+ }
+ return code;
+}
+
+static int ers(void) {
+ int size, code = RLC_ERR;
+ ec_t pp, pk[4];
+ bn_t sk[4], td;
+ ers_t ring[4];
+ uint8_t m[5] = { 0, 1, 2, 3, 4 };
+
+ bn_null(td);
+ ec_null(pp);
+
+ RLC_TRY {
+ bn_new(td);
+ ec_new(pp);
+ for (int i = 0; i < 4; i++) {
+ bn_null(sk[i]);
+ bn_new(sk[i]);
+ ec_null(pk[i]);
+ ec_new(pk[i]);
+ ers_null(ring[i]);
+ ers_new(ring[i]);
+ cp_ers_gen_key(sk[i], pk[i]);
+ }
+
+ cp_ers_gen(pp);
+
+ TEST_CASE("extendable ring signature scheme is correct") {
+ TEST_ASSERT(cp_ers_sig(td, ring[0], m, 5, sk[0], pk[0], pp) == RLC_OK, end);
+ TEST_ASSERT(cp_ers_ver(td, ring, 1, m, 5, pp) == 1, end);
+ TEST_ASSERT(cp_ers_ver(td, ring, 1, m, 0, pp) == 0, end);
+ size = 1;
+ for (int j = 1; j < 4; j++) {
+ TEST_ASSERT(cp_ers_ext(td, ring, &size, m, 5, pk[j], pp) == RLC_OK, end);
+ TEST_ASSERT(cp_ers_ver(td, ring, size, m, 5, pp) == 1, end);
+ TEST_ASSERT(cp_ers_ver(td, ring, size, m, 0, pp) == 0, end);
+ }
+ } TEST_END;
+ }
+ RLC_CATCH_ANY {
+ RLC_ERROR(end);
+ }
+ code = RLC_OK;
+
+end:
+ bn_free(td);
+ ec_free(pp);
+ for (int i = 0; i < 4; i++) {
+ bn_free(sk[i]);
+ ec_free(pk[i]);
+ ers_free(ring[i])
+ }
+ return code;
+}
+
+static int smlers(void) {
+ int size, code = RLC_ERR;
+ ec_t pp, pk[4];
+ bn_t sk[4], td;
+ smlers_t ring[4];
+ uint8_t m[5] = { 0, 1, 2, 3, 4 };
+
+ bn_null(td);
+ ec_null(pp);
+
+ RLC_TRY {
+ bn_new(td);
+ ec_new(pp);
+ for (int i = 0; i < 4; i++) {
+ bn_null(sk[i]);
+ bn_new(sk[i]);
+ ec_null(pk[i]);
+ ec_new(pk[i]);
+ smlers_null(ring[i]);
+ smlers_new(ring[i]);
+ cp_ers_gen_key(sk[i], pk[i]);
+ }
+
+ cp_ers_gen(pp);
+
+ TEST_CASE("same-message linkable ext. ring signature scheme is correct") {
+ TEST_ASSERT(cp_smlers_sig(td, ring[0], m, 5, sk[0], pk[0], pp) == RLC_OK, end);
+ TEST_ASSERT(cp_smlers_ver(td, ring, 1, m, 5, pp) == 1, end);
+ TEST_ASSERT(cp_smlers_ver(td, ring, 1, m, 0, pp) == 0, end);
+ size = 1;
+ for (int j = 1; j < 4; j++) {
+ TEST_ASSERT(cp_smlers_ext(td, ring, &size, m, 5, pk[j], pp) == RLC_OK, end);
+ TEST_ASSERT(cp_smlers_ver(td, ring, size, m, 5, pp) == 1, end);
+ TEST_ASSERT(cp_smlers_ver(td, ring, size, m, 0, pp) == 0, end);
+ TEST_ASSERT(ec_cmp(ring[0]->tau, ring[j]->tau) == RLC_EQ, end);
+ }
+ } TEST_END;
+ }
+ RLC_CATCH_ANY {
+ RLC_ERROR(end);
+ }
+ code = RLC_OK;
+
+end:
+ bn_free(td);
+ ec_free(pp);
+ for (int i = 0; i < 4; i++) {
+ bn_free(sk[i]);
+ ec_free(pk[i]);
+ smlers_free(ring[i])
+ }
+ return code;
+}
+
+static int etrs(void) {
+ int size, code = RLC_ERR;
+ ec_t pp, pk[4];
+ bn_t sk[4], td[4], y[4];
+ etrs_t ring[4];
+ uint8_t m[5] = { 0, 1, 2, 3, 4 };
+
+
+ ec_null(pp);
+
+ RLC_TRY {
+ ec_new(pp);
+ for (int i = 0; i < 4; i++) {
+ bn_null(td[i]);
+ bn_new(td[i]);
+ bn_null(y[i]);
+ bn_new(y[i]);
+ bn_null(sk[i]);
+ bn_new(sk[i]);
+ ec_null(pk[i]);
+ ec_new(pk[i]);
+ etrs_null(ring[i]);
+ etrs_new(ring[i]);
+ cp_ers_gen_key(sk[i], pk[i]);
+ }
+
+ cp_ers_gen(pp);
+
+ TEST_CASE("extendable threshold ring signature scheme is correct") {
+ TEST_ASSERT(cp_etrs_sig(td, y, 4, ring[0], m, 5, sk[0], pk[0], pp) == RLC_OK, end);
+ TEST_ASSERT(cp_etrs_ver(0, td, y, 4, ring, 1, m, 5, pp) == 0, end);
+ TEST_ASSERT(cp_etrs_ver(1, td, y, 4, ring, 1, m, 5, pp) == 1, end);
+ TEST_ASSERT(cp_etrs_ver(1, td, y, 4, ring, 1, m, 0, pp) == 0, end);
+ size = 1;
+ for (int j = 1; j < 4; j++) {
+ TEST_ASSERT(cp_etrs_ext(td, y, 4, ring, &size, m, 5, pk[j], pp) == RLC_OK, end);
+ TEST_ASSERT(cp_etrs_ver(0, td+j, y+j, 4-j, ring, size, m, 5, pp) == 0, end);
+ TEST_ASSERT(cp_etrs_ver(1, td+j, y+j, 4-j, ring, size, m, 5, pp) == 1, end);
+ TEST_ASSERT(cp_etrs_ver(1, td+j, y+j, 4-j, ring, size, m, 0, pp) == 0, end);
+ }
+
+ TEST_ASSERT(cp_etrs_sig(td, y, 4, ring[0], m, 5, sk[0], pk[0], pp) == RLC_OK, end);
+ size = 1;
+ TEST_ASSERT(cp_etrs_uni(1, td, y, 4, ring, &size, m, 5, sk[1], pk[1], pp) == RLC_OK, end);
+ TEST_ASSERT(cp_etrs_ver(1, td, y, 4, ring, size, m, 5, pp) == 0, end);
+ TEST_ASSERT(cp_etrs_ver(2, td, y, 4, ring, size, m, 5, pp) == 1, end);
+ TEST_ASSERT(cp_etrs_ver(2, td, y, 4, ring, size, m, 0, pp) == 0, end);
+ for (int j = 2; j < 4; j++) {
+ TEST_ASSERT(cp_etrs_ext(td, y, 4, ring, &size, m, 5, pk[j], pp) == RLC_OK, end);
+ TEST_ASSERT(cp_etrs_ver(1, td+j-1, y+j-1, 4-j+1, ring, size, m, 5, pp) == 0, end);
+ TEST_ASSERT(cp_etrs_ver(2, td+j-1, y+j-1, 4-j+1, ring, size, m, 5, pp) == 1, end);
+ TEST_ASSERT(cp_etrs_ver(2, td+j-1, y+j-1, 4-j+1, ring, size, m, 0, pp) == 0, end);
+ }
+ } TEST_END;
+ }
+ RLC_CATCH_ANY {
+ RLC_ERROR(end);
+ }
+ code = RLC_OK;
+
+end:
+ ec_free(pp);
+ for (int i = 0; i < 4; i++) {
+ bn_free(td[i]);
+ bn_free(y[i]);
+ bn_free(sk[i]);
+ ec_free(pk[i]);
+ etrs_free(ring[i])
+ }
+ return code;
+}
+
#endif /* WITH_EC */
#if defined(WITH_PC)
+static int pdpub(void) {
+ int code = RLC_ERR;
+ bn_t r1, r2;
+ g1_t p, u1, v1;
+ g2_t q, u2, v2, w2;
+ gt_t e, r, g[3];
+
+ bn_null(r1);
+ bn_null(r2);
+ g1_null(p);
+ g1_null(u1);
+ g1_null(v1);
+ g2_null(q);
+ g2_null(u2);
+ g2_null(v2);
+ g2_null(w2);
+ gt_null(e);
+ gt_null(r);
+ gt_null(g[0]);
+ gt_null(g[1]);
+ gt_null(g[2]);
+
+ RLC_TRY {
+ bn_new(r1);
+ bn_new(r2);
+ g1_new(p);
+ g1_new(u1);
+ g1_new(v1);
+ g2_new(q);
+ g2_new(u2);
+ g2_new(v2);
+ g2_new(w2);
+ gt_new(e);
+ gt_new(r);
+ gt_new(g[0]);
+ gt_new(g[1]);
+ gt_new(g[2]);
+
+ TEST_CASE("delegated pairing computation with public inputs is correct") {
+ TEST_ASSERT(cp_pdpub_gen(r1, r2, u1, u2, v2, e) == RLC_OK, end);
+ g1_rand(p);
+ g2_rand(q);
+ TEST_ASSERT(cp_pdpub_ask(v1, w2, p, q, r1, r2, u1, u2, v2) == RLC_OK, end);
+ TEST_ASSERT(cp_pdpub_ans(g, p, q, v1, v2, w2) == RLC_OK, end);
+ TEST_ASSERT(cp_pdpub_ver(r, g, r1, e) == 1, end);
+ pc_map(e, p, q);
+ TEST_ASSERT(gt_cmp(r, e) == RLC_EQ, end);
+ } TEST_END;
+
+ TEST_CASE("faster delegated pairing with public inputs is correct") {
+ TEST_ASSERT(cp_lvpub_gen(r2, u1, u2, v2, e) == RLC_OK, end);
+ g1_rand(p);
+ g2_rand(q);
+ TEST_ASSERT(cp_lvpub_ask(r1, v1, w2, p, q, r2, u1, u2, v2) == RLC_OK, end);
+ TEST_ASSERT(cp_lvpub_ans(g, p, q, v1, v2, w2) == RLC_OK, end);
+ TEST_ASSERT(cp_lvpub_ver(r, g, r1, e) == 1, end);
+ pc_map(e, p, q);
+ TEST_ASSERT(gt_cmp(r, e) == RLC_EQ, end);
+ } TEST_END;
+ } RLC_CATCH_ANY {
+ RLC_ERROR(end);
+ }
+ code = RLC_OK;
+
+ end:
+ bn_free(r1);
+ bn_free(r2);
+ g1_free(p);
+ g1_free(u1);
+ g1_free(v1);
+ g2_free(q);
+ g2_free(u2);
+ g2_free(v2);
+ g2_free(w2);
+ gt_free(e);
+ gt_free(r);
+ gt_free(g[0]);
+ gt_free(g[1]);
+ gt_free(g[2]);
+ return code;
+}
+
+static int pdprv(void) {
+ int code = RLC_ERR;
+ bn_t r1, r2[3];
+ g1_t p, u1[2], v1[3];
+ g2_t q, u2[2], v2[4], w2[4];
+ gt_t e[2], r, g[4];
+
+ bn_null(r1);
+ g1_null(p);
+ g2_null(q);
+ gt_null(r);
+ for (int i = 0; i < 2; i++) {
+ g1_null(u1[i]);
+ g2_null(u2[i]);
+ gt_null(e[i]);
+ }
+ for (int i = 0; i < 3; i++) {
+ g1_null(v1[i]);
+ bn_null(r2[i]);
+ }
+ for (int i = 0; i < 4; i++) {
+ g2_null(v2[i]);
+ g2_null(w2[i]);
+ gt_null(g[i]);
+ }
+
+ RLC_TRY {
+ bn_new(r1);
+ g1_new(p);
+ g2_new(q);
+ gt_new(r);
+ for (int i = 0; i < 2; i++) {
+ g1_new(u1[i]);
+ g2_new(u2[i]);
+ gt_new(e[i]);
+ }
+ for (int i = 0; i < 3; i++) {
+ g1_new(v1[i]);
+ bn_new(r2[i]);
+ }
+ for (int i = 0; i < 4; i++) {
+ g2_new(v2[i]);
+ g2_new(w2[i]);
+ gt_new(g[i]);
+ }
+
+ TEST_CASE("delegated pairing computation with private inputs is correct") {
+ TEST_ASSERT(cp_pdprv_gen(r1, r2, u1, u2, v2, e) == RLC_OK, end);
+ g1_rand(p);
+ g2_rand(q);
+ TEST_ASSERT(cp_pdprv_ask(v1, w2, p, q, r1, r2, u1, u2, v2) == RLC_OK, end);
+ TEST_ASSERT(cp_pdprv_ans(g, v1, w2) == RLC_OK, end);
+ TEST_ASSERT(cp_pdprv_ver(r, g, r1, e) == 1, end);
+ pc_map(e[0], p, q);
+ TEST_ASSERT(gt_cmp(r, e[0]) == RLC_EQ, end);
+ } TEST_END;
+
+ TEST_CASE("faster delegated pairing with private inputs is correct") {
+ TEST_ASSERT(cp_pdprv_gen(r1, r2, u1, u2, v2, e) == RLC_OK, end);
+ g1_rand(p);
+ g2_rand(q);
+ TEST_ASSERT(cp_lvprv_ask(v1, w2, p, q, r1, r2, u1, u2, v2) == RLC_OK, end);
+ TEST_ASSERT(cp_lvprv_ans(g, v1, w2) == RLC_OK, end);
+ TEST_ASSERT(cp_lvprv_ver(r, g, r1, e) == 1, end);
+ pc_map(e[0], p, q);
+ TEST_ASSERT(gt_cmp(r, e[0]) == RLC_EQ, end);
+ } TEST_END;
+ } RLC_CATCH_ANY {
+ RLC_ERROR(end);
+ }
+ code = RLC_OK;
+
+ end:
+ bn_free(r1);
+ g1_free(p);
+ g2_free(q);
+ gt_free(r);
+ for (int i = 0; i < 2; i++) {
+ g1_free(u1[i]);
+ g2_free(u2[i]);
+ gt_free(e[i]);
+ }
+ for (int i = 0; i < 3; i++) {
+ g1_free(v1[i]);
+ bn_free(r2[i]);
+ }
+ for (int i = 0; i < 4; i++) {
+ g2_free(v2[i]);
+ g2_free(w2[i]);
+ gt_free(g[i]);
+ }
+ return code;
+}
+
static int sokaka(void) {
int code = RLC_ERR, l = RLC_MD_LEN;
sokaka_t k;
@@ -1506,36 +2016,115 @@ static int lhs(void) {
code = RLC_OK;
end:
- bn_free(n);
- bn_free(m);
- g1_free(h);
- g1_free(_r);
- g2_free(_s);
- gt_free(vk);
-
- for (int i = 0; i < S; i++) {
- RLC_FREE(f[i]);
- for (int j = 0; j < RLC_TERMS; j++) {
+ bn_free(n);
+ bn_free(m);
+ g1_free(h);
+ g1_free(_r);
+ g2_free(_s);
+ gt_free(vk);
+
+ for (int i = 0; i < S; i++) {
+ RLC_FREE(f[i]);
+ for (int j = 0; j < RLC_TERMS; j++) {
gt_free(hs[i][j]);
- }
- RLC_FREE(hs[i]);
- for (int j = 0; j < L; j++) {
- bn_free(x[i][j]);
- bn_free(msg[i][j]);
- g1_free(a[i][j]);
- g1_free(c[i][j]);
- g1_free(r[i][j]);
- g2_free(s[i][j]);
- }
- bn_free(sk[i]);
- bn_free(d[i]);
- g1_free(sig[i]);
- g1_free(as[i]);
- g1_free(cs[i]);
- g2_free(y[i]);
- g2_free(z[i]);
- g2_free(pk[i]);
- }
+ }
+ RLC_FREE(hs[i]);
+ for (int j = 0; j < L; j++) {
+ bn_free(x[i][j]);
+ bn_free(msg[i][j]);
+ g1_free(a[i][j]);
+ g1_free(c[i][j]);
+ g1_free(r[i][j]);
+ g2_free(s[i][j]);
+ }
+ bn_free(sk[i]);
+ bn_free(d[i]);
+ g1_free(sig[i]);
+ g1_free(as[i]);
+ g1_free(cs[i]);
+ g2_free(y[i]);
+ g2_free(z[i]);
+ g2_free(pk[i]);
+ }
+ return code;
+}
+
+#define M 5 /* Number of server messages (larger). */
+#define N 2 /* Number of client messages. */
+
+static int psi(void) {
+ int len, code = RLC_ERR;
+ bn_t q, r, x[M], y[N], z[M];
+ g1_t d, s[M + 1];
+ g2_t u[M], ss;
+ gt_t t[M];
+
+ bn_null(q);
+ bn_null(r);
+ g1_null(d);
+ g2_null(ss);
+
+ RLC_TRY {
+ bn_new(q);
+ bn_new(r);
+ g1_new(d);
+ g2_new(ss);
+ for (int i = 0; i < M; i++) {
+ bn_null(x[i]);
+ bn_null(z[i]);
+ g1_null(s[i]);
+ bn_new(x[i]);
+ bn_new(z[i]);
+ g1_new(s[i]);
+ }
+ for (int i = 0; i < N; i++) {
+ bn_null(y[i]);
+ g2_null(u[i]);
+ gt_null(t[i]);
+ bn_new(y[i]);
+ g2_new(u[i]);
+ gt_new(t[i]);
+ }
+
+ TEST_CASE("laconic private set intersection is correct") {
+ pc_get_ord(q);
+ for (int j = 0; j < M; j++) {
+ bn_rand_mod(x[j], q);
+ }
+ for (int j = 0; j < N; j++) {
+ bn_rand_mod(y[j], q);
+ }
+ TEST_ASSERT(cp_lapsi_gen(q, ss, s, M) == RLC_OK, end);
+ TEST_ASSERT(cp_lapsi_ask(d, r, x, s, M) == RLC_OK, end);
+ for (int k = 0; k <= N; k++) {
+ for (int j = 0; j < k; j++) {
+ bn_copy(y[j], x[j]);
+ }
+ TEST_ASSERT(cp_lapsi_ans(t, u, d, ss, y, N) == RLC_OK, end);
+ TEST_ASSERT(cp_lapsi_int(z, &len, q, d, x, M, t, u, N) == RLC_OK, end);
+ TEST_ASSERT(len == k, end);
+ }
+ } TEST_END;
+ }
+ RLC_CATCH_ANY {
+ RLC_ERROR(end);
+ }
+ code = RLC_OK;
+ end:
+ bn_free(q);
+ bn_free(r);
+ g1_free(d);
+ g2_free(ss);
+ for (int i = 0; i < M; i++) {
+ bn_free(x[i]);
+ bn_free(z[i]);
+ g1_free(s[i]);
+ }
+ for (int i = 0; i < N; i++) {
+ bn_free(y[i]);
+ g2_free(u[i]);
+ gt_free(t[i]);
+ }
return code;
}
@@ -1609,14 +2198,45 @@ int main(void) {
return 1;
}
- } else {
- RLC_THROW(ERR_NO_CURVE);
+ if (pok() != RLC_OK) {
+ core_clean();
+ return 1;
+ }
+
+ if (sok() != RLC_OK) {
+ core_clean();
+ return 1;
+ }
+
+ if (ers() != RLC_OK) {
+ core_clean();
+ return 1;
+ }
+
+ if (smlers() != RLC_OK) {
+ core_clean();
+ return 1;
+ }
+
+ if (etrs() != RLC_OK) {
+ core_clean();
+ return 1;
+ }
}
#endif
#if defined(WITH_PC)
util_banner("Protocols based on pairings:\n", 0);
if (pc_param_set_any() == RLC_OK) {
+ if (pdpub() != RLC_OK) {
+ core_clean();
+ return 1;
+ }
+
+ if (pdprv() != RLC_OK) {
+ core_clean();
+ return 1;
+ }
if (sokaka() != RLC_OK) {
core_clean();
@@ -1669,8 +2289,11 @@ int main(void) {
core_clean();
return 1;
}
- } else {
- RLC_THROW(ERR_NO_CURVE);
+
+ if (psi() != RLC_OK) {
+ core_clean();
+ return 1;
+ }
}
#endif
diff --git a/contrib/relic/test/test_eb.c b/contrib/relic/test/test_eb.c
index ab58a165e..5b0198302 100644
--- a/contrib/relic/test/test_eb.c
+++ b/contrib/relic/test/test_eb.c
@@ -633,7 +633,7 @@ static int multiplication(void) {
eb_mul_basic(r, p, k);
TEST_ASSERT(eb_cmp(p, r) == RLC_EQ, end);
eb_rand(p);
- eb_mul(r, p, n);
+ eb_mul_basic(r, p, n);
TEST_ASSERT(eb_is_infty(r), end);
bn_rand_mod(k, n);
eb_mul(q, p, k);
@@ -655,7 +655,7 @@ static int multiplication(void) {
eb_mul_lodah(r, p, k);
TEST_ASSERT(eb_cmp(p, r) == RLC_EQ, end);
eb_rand(p);
- eb_mul(r, p, n);
+ eb_mul_lodah(r, p, n);
TEST_ASSERT(eb_is_infty(r), end);
bn_rand_mod(k, n);
eb_mul(q, p, k);
@@ -678,7 +678,7 @@ static int multiplication(void) {
eb_mul_lwnaf(r, p, k);
TEST_ASSERT(eb_cmp(p, r) == RLC_EQ, end);
eb_rand(p);
- eb_mul(r, p, n);
+ eb_mul_lwnaf(r, p, n);
TEST_ASSERT(eb_is_infty(r), end);
bn_rand_mod(k, n);
eb_mul(q, p, k);
@@ -701,7 +701,7 @@ static int multiplication(void) {
eb_mul_rwnaf(r, p, k);
TEST_ASSERT(eb_cmp(p, r) == RLC_EQ, end);
eb_rand(p);
- eb_mul(r, p, n);
+ eb_mul_rwnaf(r, p, n);
TEST_ASSERT(eb_is_infty(r), end);
bn_rand_mod(k, n);
eb_mul(q, p, k);
@@ -724,7 +724,7 @@ static int multiplication(void) {
eb_mul_halve(r, p, k);
TEST_ASSERT(eb_cmp(p, r) == RLC_EQ, end);
eb_rand(p);
- eb_mul(r, p, n);
+ eb_mul_halve(r, p, n);
TEST_ASSERT(eb_is_infty(r), end);
bn_rand_mod(k, n);
eb_mul(q, p, k);
@@ -738,7 +738,7 @@ static int multiplication(void) {
TEST_END;
#endif
- TEST_CASE("multiplication by digit is correct") {
+ TEST_CASE("point multiplication by digit is correct") {
eb_mul_dig(r, p, 0);
TEST_ASSERT(eb_is_infty(r), end);
eb_mul_dig(r, p, 1);
diff --git a/contrib/relic/test/test_ec.c b/contrib/relic/test/test_ec.c
index ba068bf42..63e89d6c7 100644
--- a/contrib/relic/test/test_ec.c
+++ b/contrib/relic/test/test_ec.c
@@ -389,6 +389,18 @@ static int multiplication(void) {
ec_neg(r, r);
TEST_ASSERT(ec_cmp(q, r) == RLC_EQ, end);
} TEST_END;
+
+ TEST_CASE("point multiplication by digit is correct") {
+ ec_mul_dig(r, p, 0);
+ TEST_ASSERT(ec_is_infty(r), end);
+ ec_mul_dig(r, p, 1);
+ TEST_ASSERT(ec_cmp(p, r) == RLC_EQ, end);
+ bn_rand(k, RLC_POS, RLC_DIG);
+ ec_mul(q, p, k);
+ ec_mul_dig(r, p, k->dp[0]);
+ TEST_ASSERT(ec_cmp(q, r) == RLC_EQ, end);
+ }
+ TEST_END;
}
RLC_CATCH_ANY {
util_print("FATAL ERROR!\n");
diff --git a/contrib/relic/test/test_ed.c b/contrib/relic/test/test_ed.c
index 2698075e1..e1e371f26 100644
--- a/contrib/relic/test/test_ed.c
+++ b/contrib/relic/test/test_ed.c
@@ -673,7 +673,7 @@ static int multiplication(void) {
TEST_END;
#endif
- TEST_CASE("multiplication by digit is correct") {
+ TEST_CASE("point multiplication by digit is correct") {
ed_mul_dig(r, p, 0);
TEST_ASSERT(ed_is_infty(r), end);
ed_mul_dig(r, p, 1);
diff --git a/contrib/relic/test/test_ep.c b/contrib/relic/test/test_ep.c
index cde15d20b..2e6e4ed9d 100644
--- a/contrib/relic/test/test_ep.c
+++ b/contrib/relic/test/test_ep.c
@@ -496,28 +496,28 @@ static int endomorphism(void) {
bn_new(v2[k]);
}
- /* Recover lambda parameter. */
- ep_curve_get_v1(v1);
- ep_curve_get_v2(v2);
- ep_curve_get_ord(v2[0]);
- if (bn_cmp_dig(v1[2], 1) == RLC_EQ) {
- bn_gcd_ext(v1[0], v2[1], NULL, v1[1], v2[0]);
- } else {
- bn_gcd_ext(v1[0], v2[1], NULL, v1[2], v2[0]);
- }
- if (bn_sign(v2[1]) == RLC_NEG) {
- /* Negate modulo r. */
- bn_add(v2[1], v2[0], v2[1]);
- }
- bn_mul(v1[0], v2[1], v1[1]);
- bn_mod(l, v1[0], v2[0]);
- bn_sub(v1[1], v2[0], l);
- if (bn_cmp(v1[1], l) == RLC_LT) {
- bn_copy(l, v1[1]);
- }
-
#if defined(EP_ENDOM)
if (ep_curve_is_endom()) {
+ /* Recover lambda parameter. */
+ ep_curve_get_v1(v1);
+ ep_curve_get_v2(v2);
+ ep_curve_get_ord(v2[0]);
+ if (bn_cmp_dig(v1[2], 1) == RLC_EQ) {
+ bn_gcd_ext(v1[0], v2[1], NULL, v1[1], v2[0]);
+ } else {
+ bn_gcd_ext(v1[0], v2[1], NULL, v1[2], v2[0]);
+ }
+ if (bn_sign(v2[1]) == RLC_NEG) {
+ /* Negate modulo r. */
+ bn_add(v2[1], v2[0], v2[1]);
+ }
+ bn_mul(v1[0], v2[1], v1[1]);
+ bn_mod(l, v1[0], v2[0]);
+ bn_sub(v1[1], v2[0], l);
+ if (bn_cmp(v1[1], l) == RLC_LT) {
+ bn_copy(l, v1[1]);
+ }
+
TEST_CASE("endomorphism is correct") {
/* Test if \psi(P) = [l]P. */
ep_rand(a);
@@ -541,6 +541,7 @@ static int endomorphism(void) {
TEST_CASE("endomorphism in projective coordinates is correct") {
ep_rand(a);
ep_dbl_projc(a, a);
+ ep_norm(a, a);
ep_psi(b, a);
ep_mul(c, a, l);
TEST_ASSERT(ep_cmp(b, c) == RLC_EQ, end);
@@ -548,7 +549,7 @@ static int endomorphism(void) {
TEST_END;
#endif
}
-#endif
+#endif /* EP_ENDOM */
(void)a;
(void)b;
(void)c;
@@ -564,8 +565,8 @@ static int endomorphism(void) {
ep_free(b);
ep_free(c);
for (int k = 0; k < 3; k++) {
- bn_null(v1[k]);
- bn_null(v2[k]);
+ bn_free(v1[k]);
+ bn_free(v2[k]);
}
return code;
@@ -608,16 +609,16 @@ static int multiplication(void) {
bn_rand_mod(k, n);
ep_mul(q, p, k);
ep_mul_gen(r, k);
- //TEST_ASSERT(ep_cmp(q, r) == RLC_EQ, end);
+ TEST_ASSERT(ep_cmp(q, r) == RLC_EQ, end);
bn_neg(k, k);
ep_mul_gen(r, k);
ep_neg(r, r);
- //TEST_ASSERT(ep_cmp(q, r) == RLC_EQ, end);
+ TEST_ASSERT(ep_cmp(q, r) == RLC_EQ, end);
bn_rand_mod(k, n);
ep_mul_gen(q, k);
bn_add(k, k, n);
ep_mul_gen(r, k);
- //TEST_ASSERT(ep_cmp(q, r) == RLC_EQ, end);
+ TEST_ASSERT(ep_cmp(q, r) == RLC_EQ, end);
} TEST_END;
#if EP_MUL == BASIC || !defined(STRIP)
@@ -629,7 +630,7 @@ static int multiplication(void) {
ep_mul_basic(r, p, k);
TEST_ASSERT(ep_cmp(p, r) == RLC_EQ, end);
ep_rand(p);
- ep_mul(r, p, n);
+ ep_mul_basic(r, p, n);
TEST_ASSERT(ep_is_infty(r), end);
bn_rand_mod(k, n);
ep_mul(q, p, k);
@@ -656,7 +657,7 @@ static int multiplication(void) {
ep_mul_slide(r, p, k);
TEST_ASSERT(ep_cmp(p, r) == RLC_EQ, end);
ep_rand(p);
- ep_mul(r, p, n);
+ ep_mul_slide(r, p, n);
TEST_ASSERT(ep_is_infty(r), end);
bn_rand_mod(k, n);
ep_mul(q, p, k);
@@ -684,7 +685,7 @@ static int multiplication(void) {
ep_mul_monty(r, p, k);
TEST_ASSERT(ep_cmp(p, r) == RLC_EQ, end);
ep_rand(p);
- ep_mul(r, p, n);
+ ep_mul_monty(r, p, n);
TEST_ASSERT(ep_is_infty(r), end);
bn_rand_mod(k, n);
ep_mul(q, p, k);
@@ -712,7 +713,7 @@ static int multiplication(void) {
ep_mul_lwnaf(r, p, k);
TEST_ASSERT(ep_cmp(p, r) == RLC_EQ, end);
ep_rand(p);
- ep_mul(r, p, n);
+ ep_mul_lwnaf(r, p, n);
TEST_ASSERT(ep_is_infty(r), end);
bn_rand_mod(k, n);
ep_mul(q, p, k);
@@ -740,7 +741,7 @@ static int multiplication(void) {
ep_mul_lwreg(r, p, k);
TEST_ASSERT(ep_cmp(p, r) == RLC_EQ, end);
ep_rand(p);
- ep_mul(r, p, n);
+ ep_mul_lwreg(r, p, n);
TEST_ASSERT(ep_is_infty(r), end);
bn_rand_mod(k, n);
ep_mul(q, p, k);
@@ -759,7 +760,7 @@ static int multiplication(void) {
TEST_END;
#endif
- TEST_CASE("multiplication by digit is correct") {
+ TEST_CASE("point multiplication by digit is correct") {
ep_mul_dig(r, p, 0);
TEST_ASSERT(ep_is_infty(r), end);
ep_mul_dig(r, p, 1);
@@ -831,6 +832,11 @@ static int fixed(void) {
ep_mul_fix(r, (const ep_t *)t, k);
ep_neg(r, r);
TEST_ASSERT(ep_cmp(q, r) == RLC_EQ, end);
+ bn_rand_mod(k, n);
+ ep_mul_fix(q, (const ep_t *)t, k);
+ bn_add(k, k, n);
+ ep_mul_fix(r, (const ep_t *)t, k);
+ TEST_ASSERT(ep_cmp(q, r) == RLC_EQ, end);
} TEST_END;
for (int i = 0; i < RLC_EP_TABLE; i++) {
ep_free(t[i]);
@@ -980,23 +986,21 @@ static int fixed(void) {
static int simultaneous(void) {
int code = RLC_ERR;
- bn_t n, k[2];
- ep_t p[2], r;
+ bn_t n, k[17];
+ ep_t p[17], r;
bn_null(n);
- bn_null(k[0]);
- bn_null(k[1]);
- ep_null(p[0]);
- ep_null(p[1]);
ep_null(r);
RLC_TRY {
bn_new(n);
- bn_new(k[0]);
- bn_new(k[1]);
- ep_new(p[0]);
- ep_new(p[1]);
ep_new(r);
+ for (int i = 0; i <= 16; i++) {
+ bn_null(k[i]);
+ bn_new(k[i]);
+ ep_null(p[i]);
+ ep_new(p[i]);
+ }
ep_curve_get_gen(p[0]);
ep_curve_get_ord(n);
@@ -1031,9 +1035,6 @@ static int simultaneous(void) {
ep_mul(p[1], p[1], k[1]);
ep_add(p[1], p[1], p[0]);
TEST_ASSERT(ep_cmp(p[1], r) == RLC_EQ, end);
- ep_mul_sim(r, p[0], k[0], p[1], k[1]);
- ep_mul_sim_lot(p[1], p, k, 2);
- TEST_ASSERT(ep_cmp(p[1], r) == RLC_EQ, end);
bn_rand_mod(k[0], n);
bn_rand_mod(k[1], n);
bn_add(k[0], k[0], n);
@@ -1043,6 +1044,9 @@ static int simultaneous(void) {
ep_mul(p[1], p[1], k[1]);
ep_add(p[1], p[1], p[0]);
TEST_ASSERT(ep_cmp(p[1], r) == RLC_EQ, end);
+ ep_mul_sim(r, p[0], k[0], p[1], k[1]);
+ ep_mul_sim_lot(p[1], p, k, 2);
+ TEST_ASSERT(ep_cmp(p[1], r) == RLC_EQ, end);
} TEST_END;
#if EP_SIM == BASIC || !defined(STRIP)
@@ -1253,6 +1257,34 @@ static int simultaneous(void) {
ep_mul_sim(p[1], p[0], k[0], p[1], k[1]);
TEST_ASSERT(ep_cmp(p[1], r) == RLC_EQ, end);
} TEST_END;
+
+ TEST_CASE("many simultaneous point multiplications are correct") {
+ ep_set_infty(r);
+ ep_mul_sim_lot(p[16], p, k, 0);
+ TEST_ASSERT(ep_cmp(p[16], r) == RLC_EQ, end);
+ for (int j = 0; j < 16; j++) {
+ bn_rand_mod(k[j], n);
+ ep_rand(p[j]);
+ ep_mul(p[16], p[j], k[j]);
+ ep_add(r, r, p[16]);
+ ep_mul_sim_lot(p[16], p, k, j + 1);
+ TEST_ASSERT(ep_cmp(p[16], r) == RLC_EQ, end);
+ }
+ ep_mul(p[16], p[0], k[0]);
+ ep_sub(r, r, p[16]);
+ bn_zero(k[0]);
+ ep_mul_sim_lot(p[16], p, k, 16);
+ TEST_ASSERT(ep_cmp(p[16], r) == RLC_EQ, end);
+ ep_mul(p[16], p[1], k[1]);
+ ep_sub(r, r, p[16]);
+ ep_sub(r, r, p[16]);
+ bn_neg(k[1], k[1]);
+ ep_mul_sim_lot(p[16], p, k, 16);
+ TEST_ASSERT(ep_cmp(p[16], r) == RLC_EQ, end);
+ bn_add(k[2], k[2], n);
+ ep_mul_sim_lot(p[16], p, k, 16);
+ TEST_ASSERT(ep_cmp(p[16], r) == RLC_EQ, end);
+ } TEST_END;
}
RLC_CATCH_ANY {
util_print("FATAL ERROR!\n");
@@ -1261,10 +1293,10 @@ static int simultaneous(void) {
code = RLC_OK;
end:
bn_free(n);
- bn_free(k[0]);
- bn_free(k[1]);
- ep_free(p[0]);
- ep_free(p[1]);
+ for (int i = 0; i <= 16; i++) {
+ bn_free(k[i]);
+ ep_free(p[i]);
+ }
ep_free(r);
return code;
}
diff --git a/contrib/relic/test/test_epx.c b/contrib/relic/test/test_epx.c
index 574f53aed..34b5d8a18 100644
--- a/contrib/relic/test/test_epx.c
+++ b/contrib/relic/test/test_epx.c
@@ -34,7 +34,7 @@
#include "relic.h"
#include "relic_test.h"
-static int memory(void) {
+static int memory2(void) {
err_t e;
int code = RLC_ERR;
ep2_t a;
@@ -60,7 +60,7 @@ static int memory(void) {
return code;
}
-static int util(void) {
+static int util2(void) {
int l, code = RLC_ERR;
ep2_t a, b, c;
uint8_t bin[4 * RLC_FP_BYTES + 1];
@@ -179,7 +179,7 @@ static int util(void) {
return code;
}
-static int addition(void) {
+static int addition2(void) {
int code = RLC_ERR;
ep2_t a, b, c, d, e;
@@ -295,7 +295,7 @@ static int addition(void) {
return code;
}
-static int subtraction(void) {
+static int subtraction2(void) {
int code = RLC_ERR;
ep2_t a, b, c, d;
@@ -347,7 +347,7 @@ static int subtraction(void) {
return code;
}
-static int doubling(void) {
+static int doubling2(void) {
int code = RLC_ERR;
ep2_t a, b, c;
@@ -407,7 +407,7 @@ static int doubling(void) {
return code;
}
-static int multiplication(void) {
+static int multiplication2(void) {
int code = RLC_ERR;
bn_t n, k;
ep2_t p, q, r;
@@ -449,6 +449,11 @@ static int multiplication(void) {
ep2_mul_gen(r, k);
ep2_neg(r, r);
TEST_ASSERT(ep2_cmp(q, r) == RLC_EQ, end);
+ bn_rand_mod(k, n);
+ ep2_mul_gen(q, k);
+ bn_add(k, k, n);
+ ep2_mul_gen(r, k);
+ TEST_ASSERT(ep2_cmp(q, r) == RLC_EQ, end);
} TEST_END;
#if EP_MUL == BASIC || !defined(STRIP)
@@ -460,7 +465,7 @@ static int multiplication(void) {
ep2_mul_basic(r, p, k);
TEST_ASSERT(ep2_cmp(p, r) == RLC_EQ, end);
ep2_rand(p);
- ep2_mul(r, p, n);
+ ep2_mul_basic(r, p, n);
TEST_ASSERT(ep2_is_infty(r), end);
bn_rand_mod(k, n);
ep2_mul(q, p, k);
@@ -470,6 +475,11 @@ static int multiplication(void) {
ep2_mul_basic(r, p, k);
ep2_neg(r, r);
TEST_ASSERT(ep2_cmp(q, r) == RLC_EQ, end);
+ bn_rand_mod(k, n);
+ ep2_mul_basic(q, p, k);
+ bn_add(k, k, n);
+ ep2_mul_basic(r, p, k);
+ TEST_ASSERT(ep2_cmp(q, r) == RLC_EQ, end);
} TEST_END;
#endif
@@ -482,7 +492,7 @@ static int multiplication(void) {
ep2_mul_slide(r, p, k);
TEST_ASSERT(ep2_cmp(p, r) == RLC_EQ, end);
ep2_rand(p);
- ep2_mul(r, p, n);
+ ep2_mul_slide(r, p, n);
TEST_ASSERT(ep2_is_infty(r), end);
bn_rand_mod(k, n);
ep2_mul(q, p, k);
@@ -492,6 +502,11 @@ static int multiplication(void) {
ep2_mul_slide(r, p, k);
ep2_neg(r, r);
TEST_ASSERT(ep2_cmp(q, r) == RLC_EQ, end);
+ bn_rand_mod(k, n);
+ ep2_mul_slide(q, p, k);
+ bn_add(k, k, n);
+ ep2_mul_slide(r, p, k);
+ TEST_ASSERT(ep2_cmp(q, r) == RLC_EQ, end);
}
TEST_END;
#endif
@@ -505,7 +520,7 @@ static int multiplication(void) {
ep2_mul_monty(r, p, k);
TEST_ASSERT(ep2_cmp(p, r) == RLC_EQ, end);
ep2_rand(p);
- ep2_mul(r, p, n);
+ ep2_mul_monty(r, p, n);
TEST_ASSERT(ep2_is_infty(r), end);
bn_rand_mod(k, n);
ep2_mul(q, p, k);
@@ -515,6 +530,11 @@ static int multiplication(void) {
ep2_mul_monty(r, p, k);
ep2_neg(r, r);
TEST_ASSERT(ep2_cmp(q, r) == RLC_EQ, end);
+ bn_rand_mod(k, n);
+ ep2_mul_monty(q, p, k);
+ bn_add(k, k, n);
+ ep2_mul_monty(r, p, k);
+ TEST_ASSERT(ep2_cmp(q, r) == RLC_EQ, end);
}
TEST_END;
#endif
@@ -528,7 +548,7 @@ static int multiplication(void) {
ep2_mul_lwnaf(r, p, k);
TEST_ASSERT(ep2_cmp(p, r) == RLC_EQ, end);
ep2_rand(p);
- ep2_mul(r, p, n);
+ ep2_mul_lwnaf(r, p, n);
TEST_ASSERT(ep2_is_infty(r), end);
bn_rand_mod(k, n);
ep2_mul(q, p, k);
@@ -538,11 +558,16 @@ static int multiplication(void) {
ep2_mul_lwnaf(r, p, k);
ep2_neg(r, r);
TEST_ASSERT(ep2_cmp(q, r) == RLC_EQ, end);
+ bn_rand_mod(k, n);
+ ep2_mul_lwnaf(q, p, k);
+ bn_add(k, k, n);
+ ep2_mul_lwnaf(r, p, k);
+ TEST_ASSERT(ep2_cmp(q, r) == RLC_EQ, end);
}
TEST_END;
#endif
- TEST_CASE("multiplication by digit is correct") {
+ TEST_CASE("point multiplication by digit is correct") {
ep2_mul_dig(r, p, 0);
TEST_ASSERT(ep2_is_infty(r), end);
ep2_mul_dig(r, p, 1);
@@ -568,7 +593,7 @@ static int multiplication(void) {
return code;
}
-static int fixed(void) {
+static int fixed2(void) {
int code = RLC_ERR;
bn_t n, k;
ep2_t p, q, r, t[RLC_EPX_TABLE_MAX];
@@ -614,6 +639,11 @@ static int fixed(void) {
ep2_mul_fix(r, t, k);
ep2_neg(r, r);
TEST_ASSERT(ep2_cmp(q, r) == RLC_EQ, end);
+ bn_rand_mod(k, n);
+ ep2_mul_fix(q, t, k);
+ bn_add(k, k, n);
+ ep2_mul_fix(r, t, k);
+ TEST_ASSERT(ep2_cmp(q, r) == RLC_EQ, end);
} TEST_END;
for (int i = 0; i < RLC_EP_TABLE; i++) {
ep2_free(t[i]);
@@ -640,6 +670,11 @@ static int fixed(void) {
ep2_mul_fix_basic(r, t, k);
ep2_neg(r, r);
TEST_ASSERT(ep2_cmp(q, r) == RLC_EQ, end);
+ bn_rand_mod(k, n);
+ ep2_mul_fix_basic(q, t, k);
+ bn_add(k, k, n);
+ ep2_mul_fix_basic(r, t, k);
+ TEST_ASSERT(ep2_cmp(q, r) == RLC_EQ, end);
} TEST_END;
for (int i = 0; i < RLC_EP_TABLE_BASIC; i++) {
ep2_free(t[i]);
@@ -667,6 +702,11 @@ static int fixed(void) {
ep2_mul_fix_combs(r, t, k);
ep2_neg(r, r);
TEST_ASSERT(ep2_cmp(q, r) == RLC_EQ, end);
+ bn_rand_mod(k, n);
+ ep2_mul_fix_combs(q, t, k);
+ bn_add(k, k, n);
+ ep2_mul_fix_combs(r, t, k);
+ TEST_ASSERT(ep2_cmp(q, r) == RLC_EQ, end);
} TEST_END;
for (int i = 0; i < RLC_EP_TABLE_COMBS; i++) {
ep2_free(t[i]);
@@ -694,6 +734,11 @@ static int fixed(void) {
ep2_mul_fix_combd(r, t, k);
ep2_neg(r, r);
TEST_ASSERT(ep2_cmp(q, r) == RLC_EQ, end);
+ bn_rand_mod(k, n);
+ ep2_mul_fix_combd(q, t, k);
+ bn_add(k, k, n);
+ ep2_mul_fix_combd(r, t, k);
+ TEST_ASSERT(ep2_cmp(q, r) == RLC_EQ, end);
} TEST_END;
for (int i = 0; i < RLC_EP_TABLE_COMBD; i++) {
ep2_free(t[i]);
@@ -721,6 +766,11 @@ static int fixed(void) {
ep2_mul_fix_lwnaf(r, t, k);
ep2_neg(r, r);
TEST_ASSERT(ep2_cmp(q, r) == RLC_EQ, end);
+ bn_rand_mod(k, n);
+ ep2_mul_fix_lwnaf(q, t, k);
+ bn_add(k, k, n);
+ ep2_mul_fix_lwnaf(r, t, k);
+ TEST_ASSERT(ep2_cmp(q, r) == RLC_EQ, end);
} TEST_END;
for (int i = 0; i < RLC_EP_TABLE_LWNAF; i++) {
ep2_free(t[i]);
@@ -741,25 +791,22 @@ static int fixed(void) {
return code;
}
-static int simultaneous(void) {
+static int simultaneous2(void) {
int code = RLC_ERR;
- bn_t n, k[2];
- ep2_t p[2], r;
+ bn_t n, k[17];
+ ep2_t p[17], r;
bn_null(n);
- bn_null(k[0]);
- bn_null(k[1]);
- ep2_null(p[0]);
- ep2_null(p[1]);
ep2_null(r);
-
RLC_TRY {
bn_new(n);
- bn_new(k[0]);
- bn_new(k[1]);
- ep2_new(p[0]);
- ep2_new(p[1]);
ep2_new(r);
+ for (int i = 0; i <= 16; i++) {
+ bn_null(k[i]);
+ bn_new(k[i]);
+ ep2_null(p[i]);
+ ep2_new(p[i]);
+ }
ep2_curve_get_gen(p[0]);
ep2_curve_get_ord(n);
@@ -794,6 +841,15 @@ static int simultaneous(void) {
ep2_mul(p[1], p[1], k[1]);
ep2_add(p[1], p[1], p[0]);
TEST_ASSERT(ep2_cmp(p[1], r) == RLC_EQ, end);
+ bn_rand_mod(k[0], n);
+ bn_rand_mod(k[1], n);
+ bn_add(k[0], k[0], n);
+ bn_add(k[1], k[1], n);
+ ep2_mul_sim(r, p[0], k[0], p[1], k[1]);
+ ep2_mul(p[0], p[0], k[0]);
+ ep2_mul(p[1], p[1], k[1]);
+ ep2_add(p[1], p[1], p[0]);
+ TEST_ASSERT(ep2_cmp(p[1], r) == RLC_EQ, end);
ep2_mul_sim(r, p[0], k[0], p[1], k[1]);
ep2_mul_sim_lot(p[1], p, k, 2);
TEST_ASSERT(ep2_cmp(p[1], r) == RLC_EQ, end);
@@ -963,6 +1019,32 @@ static int simultaneous(void) {
ep2_mul_sim(p[1], p[0], k[0], p[1], k[1]);
TEST_ASSERT(ep2_cmp(p[1], r) == RLC_EQ, end);
} TEST_END;
+
+ TEST_CASE("many simultaneous point multiplications are correct") {
+ ep2_set_infty(r);
+ for (int j = 0; j < 16; j++) {
+ bn_rand_mod(k[j], n);
+ ep2_rand(p[j]);
+ ep2_mul(p[16], p[j], k[j]);
+ ep2_add(r, r, p[16]);
+ ep2_mul_sim_lot(p[16], p, k, j + 1);
+ TEST_ASSERT(ep2_cmp(p[16], r) == RLC_EQ, end);
+ }
+ ep2_mul(p[16], p[0], k[0]);
+ ep2_sub(r, r, p[16]);
+ bn_zero(k[0]);
+ ep2_mul_sim_lot(p[16], p, k, 16);
+ TEST_ASSERT(ep2_cmp(p[16], r) == RLC_EQ, end);
+ ep2_mul(p[16], p[1], k[1]);
+ ep2_sub(r, r, p[16]);
+ ep2_sub(r, r, p[16]);
+ bn_neg(k[1], k[1]);
+ ep2_mul_sim_lot(p[16], p, k, 16);
+ TEST_ASSERT(ep2_cmp(p[16], r) == RLC_EQ, end);
+ bn_add(k[2], k[2], n);
+ ep2_mul_sim_lot(p[16], p, k, 16);
+ TEST_ASSERT(ep2_cmp(p[16], r) == RLC_EQ, end);
+ } TEST_END;
}
RLC_CATCH_ANY {
util_print("FATAL ERROR!\n");
@@ -971,15 +1053,15 @@ static int simultaneous(void) {
code = RLC_OK;
end:
bn_free(n);
- bn_free(k[0]);
- bn_free(k[1]);
- ep2_free(p[0]);
- ep2_free(p[1]);
ep2_free(r);
+ for (int i = 0; i <= 16; i++) {
+ bn_free(k[i]);
+ ep2_free(p[i]);
+ }
return code;
}
-static int compression(void) {
+static int compression2(void) {
int code = RLC_ERR;
ep2_t a, b, c;
@@ -1011,7 +1093,7 @@ static int compression(void) {
return code;
}
-static int hashing(void) {
+static int hashing2(void) {
int code = RLC_ERR;
bn_t n;
ep2_t p;
@@ -1052,7 +1134,7 @@ static int hashing(void) {
return code;
}
-static int frobenius(void) {
+static int frobenius2(void) {
int code = RLC_ERR;
ep2_t a, b, c;
bn_t d, n;
@@ -1072,7 +1154,7 @@ static int frobenius(void) {
ep2_curve_get_ord(n);
- TEST_CASE("frobenius and scalar multiplication are consistent") {
+ TEST_CASE("frobenius and point multiplication are consistent") {
ep2_rand(a);
ep2_frb(b, a, 1);
d->used = RLC_FP_DIGS;
@@ -1096,85 +1178,1169 @@ static int frobenius(void) {
return code;
}
-int main(void) {
- if (core_init() != RLC_OK) {
- core_clean();
- return 1;
- }
+static int memory4(void) {
+ err_t e;
+ int code = RLC_ERR;
+ ep4_t a;
- util_banner("Tests for the EPX module", 0);
+ ep4_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") {
+ ep4_new(a);
+ ep4_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 (ep2_curve_is_twist() == 0) {
- RLC_THROW(ERR_NO_CURVE);
- core_clean();
- return 0;
- }
+static int util4(void) {
+ int l, code = RLC_ERR;
+ ep4_t a, b, c;
+ uint8_t bin[8 * RLC_FP_BYTES + 1];
- ep_param_print();
+ ep4_null(a);
+ ep4_null(b);
+ ep4_null(c);
- util_banner("Utilities:", 1);
+ RLC_TRY {
+ ep4_new(a);
+ ep4_new(b);
+ ep4_new(c);
- if (memory() != RLC_OK) {
- core_clean();
- return 1;
- }
+ TEST_CASE("copy and comparison are consistent") {
+ ep4_rand(a);
+ ep4_rand(b);
+ ep4_rand(c);
+ /* Compare points in affine coordinates. */
+ if (ep4_cmp(a, c) != RLC_EQ) {
+ ep4_copy(c, a);
+ TEST_ASSERT(ep4_cmp(c, a) == RLC_EQ, end);
+ }
+ if (ep4_cmp(b, c) != RLC_EQ) {
+ ep4_copy(c, b);
+ TEST_ASSERT(ep4_cmp(b, c) == RLC_EQ, end);
+ }
+ /* Compare with one point in projective. */
+ ep4_dbl(c, a);
+ ep4_norm(c, c);
+ ep4_dbl(a, a);
+ TEST_ASSERT(ep4_cmp(c, a) == RLC_EQ, end);
+ TEST_ASSERT(ep4_cmp(a, c) == RLC_EQ, end);
+ /* Compare with two points in projective. */
+ ep4_dbl(c, c);
+ ep4_dbl(a, a);
+ TEST_ASSERT(ep4_cmp(c, a) == RLC_EQ, end);
+ TEST_ASSERT(ep4_cmp(a, c) == RLC_EQ, end);
+ }
+ TEST_END;
- if (util() != RLC_OK) {
- core_clean();
- return 1;
- }
+ TEST_CASE("negation and comparison are consistent") {
+ ep4_rand(a);
+ ep4_neg(b, a);
+ TEST_ASSERT(ep4_cmp(a, b) != RLC_EQ, end);
+ ep4_neg(b, b);
+ TEST_ASSERT(ep4_cmp(a, b) == RLC_EQ, end);
+ ep4_neg(b, a);
+ ep4_add(a, a, b);
+ ep4_set_infty(b);
+ TEST_ASSERT(ep4_cmp(a, b) == RLC_EQ, end);
+ }
+ TEST_END;
- util_banner("Arithmetic:", 1);
+ TEST_CASE("assignment to random and comparison are consistent") {
+ ep4_rand(a);
+ ep4_set_infty(c);
+ TEST_ASSERT(ep4_cmp(a, c) != RLC_EQ, end);
+ TEST_ASSERT(ep4_cmp(c, a) != RLC_EQ, end);
+ }
+ TEST_END;
- if (addition() != RLC_OK) {
- core_clean();
- return 1;
- }
+ TEST_CASE("assignment to infinity and infinity test are consistent") {
+ ep4_set_infty(a);
+ TEST_ASSERT(ep4_is_infty(a), end);
+ }
+ TEST_END;
- if (subtraction() != RLC_OK) {
- core_clean();
- return 1;
- }
+ TEST_CASE("validity test is correct") {
+ ep4_set_infty(a);
+ TEST_ASSERT(ep4_on_curve(a), end);
+ ep4_rand(a);
+ TEST_ASSERT(ep4_on_curve(a), end);
+ fp4_rand(a->x);
+ TEST_ASSERT(!ep4_on_curve(a), end);
+ }
+ TEST_END;
- if (doubling() != RLC_OK) {
- core_clean();
- return 1;
- }
+ TEST_CASE("blinding is consistent") {
+ ep4_rand(a);
+ ep4_blind(a, a);
+ TEST_ASSERT(ep4_on_curve(a), end);
+ } TEST_END;
- if (multiplication() != RLC_OK) {
- core_clean();
- return 1;
+ 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);
+ }
+ TEST_END;
}
-
- if (fixed() != RLC_OK) {
- core_clean();
- return 1;
+ RLC_CATCH_ANY {
+ util_print("FATAL ERROR!\n");
+ RLC_ERROR(end);
}
+ code = RLC_OK;
+ end:
+ ep4_free(a);
+ ep4_free(b);
+ ep4_free(c);
+ return code;
+}
- if (simultaneous() != RLC_OK) {
- core_clean();
- return 1;
+static int addition4(void) {
+ int code = RLC_ERR;
+ ep4_t a, b, c, d, e;
+
+ ep4_null(a);
+ ep4_null(b);
+ ep4_null(c);
+ ep4_null(d);
+ ep4_null(e);
+
+ RLC_TRY {
+ ep4_new(a);
+ ep4_new(b);
+ ep4_new(c);
+ ep4_new(d);
+ ep4_new(e);
+
+ TEST_CASE("point addition is commutative") {
+ ep4_rand(a);
+ ep4_rand(b);
+ ep4_add(d, a, b);
+ ep4_add(e, b, a);
+ TEST_ASSERT(ep4_cmp(d, e) == RLC_EQ, end);
+ } TEST_END;
+
+ TEST_CASE("point addition is associative") {
+ ep4_rand(a);
+ ep4_rand(b);
+ ep4_rand(c);
+ ep4_add(d, a, b);
+ ep4_add(d, d, c);
+ ep4_add(e, b, c);
+ ep4_add(e, e, a);
+ TEST_ASSERT(ep4_cmp(d, e) == RLC_EQ, end);
+ } TEST_END;
+
+ TEST_CASE("point addition has identity") {
+ ep4_rand(a);
+ ep4_set_infty(d);
+ ep4_add(e, a, d);
+ TEST_ASSERT(ep4_cmp(e, a) == RLC_EQ, end);
+ ep4_add(e, d, a);
+ TEST_ASSERT(ep4_cmp(e, a) == RLC_EQ, end);
+ } TEST_END;
+
+ TEST_CASE("point addition has inverse") {
+ ep4_rand(a);
+ ep4_neg(d, a);
+ ep4_add(e, a, d);
+ TEST_ASSERT(ep4_is_infty(e), end);
+ } TEST_END;
+
+#if EP_ADD == BASIC || !defined(STRIP)
+ TEST_CASE("point addition in affine coordinates is correct") {
+ ep4_rand(a);
+ ep4_rand(b);
+ ep4_add(d, a, b);
+ ep4_add_basic(e, a, b);
+ TEST_ASSERT(ep4_cmp(e, d) == RLC_EQ, end);
+ } TEST_END;
+#endif
+
+#if EP_ADD == PROJC || !defined(STRIP)
+#if !defined(EP_MIXED) || !defined(STRIP)
+ TEST_CASE("point addition in projective coordinates is correct") {
+ ep4_rand(a);
+ ep4_rand(b);
+ ep4_rand(c);
+ ep4_add_projc(a, a, b);
+ ep4_add_projc(b, b, c);
+ /* a and b in projective coordinates. */
+ ep4_add_projc(d, a, b);
+ /* normalize before mixing coordinates. */
+ ep4_norm(a, a);
+ ep4_norm(b, b);
+ ep4_add(e, a, b);
+ TEST_ASSERT(ep4_cmp(d, e) == RLC_EQ, end);
+ } TEST_END;
+#endif
+
+ TEST_CASE("point addition in mixed coordinates (z2 = 1) is correct") {
+ ep4_rand(a);
+ ep4_rand(b);
+ /* a in projective, b in affine coordinates. */
+ ep4_add_projc(a, a, b);
+ ep4_add_projc(d, a, b);
+ /* a in affine coordinates. */
+ ep4_norm(a, a);
+ ep4_add(e, a, b);
+ TEST_ASSERT(ep4_cmp(d, e) == RLC_EQ, end);
+ } TEST_END;
+
+ TEST_CASE("point addition in mixed coordinates (z1,z2 = 1) is correct") {
+ ep4_rand(a);
+ ep4_rand(b);
+ /* a and b in affine coordinates. */
+ ep4_add(d, a, b);
+ ep4_add_projc(e, a, b);
+ TEST_ASSERT(ep4_cmp(d, e) == RLC_EQ, end);
+ } TEST_END;
+#endif
+
+ }
+ RLC_CATCH_ANY {
+ RLC_ERROR(end);
}
+ code = RLC_OK;
+ end:
+ ep4_free(a);
+ ep4_free(b);
+ ep4_free(c);
+ ep4_free(d);
+ ep4_free(e);
+ return code;
+}
- if (compression() != RLC_OK) {
- core_clean();
- return 1;
+static int subtraction4(void) {
+ int code = RLC_ERR;
+ ep4_t a, b, c, d;
+
+ ep4_null(a);
+ ep4_null(b);
+ ep4_null(c);
+ ep4_null(d);
+
+ RLC_TRY {
+ ep4_new(a);
+ ep4_new(b);
+ ep4_new(c);
+ ep4_new(d);
+
+ TEST_CASE("point subtraction is anti-commutative") {
+ ep4_rand(a);
+ ep4_rand(b);
+ ep4_sub(c, a, b);
+ ep4_sub(d, b, a);
+ ep4_neg(d, d);
+ TEST_ASSERT(ep4_cmp(c, d) == RLC_EQ, end);
+ }
+ TEST_END;
+
+ TEST_CASE("point subtraction has identity") {
+ ep4_rand(a);
+ ep4_set_infty(c);
+ ep4_sub(d, a, c);
+ TEST_ASSERT(ep4_cmp(d, a) == RLC_EQ, end);
+ }
+ TEST_END;
+
+ TEST_CASE("point subtraction has inverse") {
+ ep4_rand(a);
+ ep4_sub(c, a, a);
+ TEST_ASSERT(ep4_is_infty(c), end);
+ }
+ TEST_END;
+ }
+ RLC_CATCH_ANY {
+ RLC_ERROR(end);
}
+ code = RLC_OK;
+ end:
+ ep4_free(a);
+ ep4_free(b);
+ ep4_free(c);
+ ep4_free(d);
+ return code;
+}
- if (hashing() != RLC_OK) {
- core_clean();
- return 1;
+static int doubling4(void) {
+ int code = RLC_ERR;
+ ep4_t a, b, c;
+
+ ep4_null(a);
+ ep4_null(b);
+ ep4_null(c);
+
+ RLC_TRY {
+ ep4_new(a);
+ ep4_new(b);
+ ep4_new(c);
+
+ TEST_CASE("point doubling is correct") {
+ ep4_rand(a);
+ ep4_add(b, a, a);
+ ep4_dbl(c, a);
+ TEST_ASSERT(ep4_cmp(b, c) == RLC_EQ, end);
+ } TEST_END;
+
+#if EP_ADD == BASIC || !defined(STRIP)
+ TEST_CASE("point doubling in affine coordinates is correct") {
+ ep4_rand(a);
+ ep4_dbl(b, a);
+ ep4_dbl_basic(c, a);
+ TEST_ASSERT(ep4_cmp(b, c) == RLC_EQ, end);
+ } TEST_END;
+#endif
+
+#if EP_ADD == PROJC || !defined(STRIP)
+ TEST_CASE("point doubling in projective coordinates is correct") {
+ ep4_rand(a);
+ /* a in projective coordinates. */
+ ep4_dbl_projc(a, a);
+ ep4_dbl_projc(b, a);
+ ep4_norm(a, a);
+ ep4_dbl(c, a);
+ TEST_ASSERT(ep4_cmp(b, c) == RLC_EQ, end);
+ } TEST_END;
+
+ TEST_CASE("point doubling in mixed coordinates (z1 = 1) is correct") {
+ ep4_rand(a);
+ ep4_dbl_projc(b, a);
+ ep4_norm(b, b);
+ ep4_dbl(c, a);
+ TEST_ASSERT(ep4_cmp(b, c) == RLC_EQ, end);
+ } TEST_END;
+#endif
}
+ RLC_CATCH_ANY {
+ RLC_ERROR(end);
+ }
+ code = RLC_OK;
+ end:
+ ep4_free(a);
+ ep4_free(b);
+ ep4_free(c);
+ return code;
+}
- if (frobenius() != RLC_OK) {
- core_clean();
- return 1;
+static int multiplication4(void) {
+ int code = RLC_ERR;
+ bn_t n, k;
+ ep4_t p, q, r;
+
+ bn_null(n);
+ bn_null(k);
+ ep4_null(p);
+ ep4_null(q);
+ ep4_null(r);
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(k);
+ ep4_new(p);
+ ep4_new(q);
+ ep4_new(r);
+
+ ep4_curve_get_gen(p);
+ ep4_curve_get_ord(n);
+
+ TEST_ONCE("generator has the right order") {
+ TEST_ASSERT(ep4_on_curve(p), end);
+ ep4_mul(r, p, n);
+ TEST_ASSERT(ep4_is_infty(r) == 1, end);
+ } TEST_END;
+
+ TEST_CASE("generator multiplication is correct") {
+ bn_zero(k);
+ ep4_mul_gen(r, k);
+ TEST_ASSERT(ep4_is_infty(r), end);
+ bn_set_dig(k, 1);
+ ep4_mul_gen(r, k);
+ TEST_ASSERT(ep4_cmp(p, r) == RLC_EQ, end);
+ bn_rand_mod(k, n);
+ ep4_mul(q, p, k);
+ ep4_mul_gen(r, k);
+ TEST_ASSERT(ep4_cmp(q, r) == RLC_EQ, end);
+ bn_neg(k, k);
+ ep4_mul_gen(r, k);
+ ep4_neg(r, r);
+ TEST_ASSERT(ep4_cmp(q, r) == RLC_EQ, end);
+ } TEST_END;
+
+#if EP_MUL == BASIC || !defined(STRIP)
+ TEST_CASE("binary point multiplication is correct") {
+ bn_zero(k);
+ ep4_mul_basic(r, p, k);
+ TEST_ASSERT(ep4_is_infty(r), end);
+ bn_set_dig(k, 1);
+ ep4_mul_basic(r, p, k);
+ TEST_ASSERT(ep4_cmp(p, r) == RLC_EQ, end);
+ ep4_rand(p);
+ ep4_mul(r, p, n);
+ TEST_ASSERT(ep4_is_infty(r), end);
+ bn_rand_mod(k, n);
+ ep4_mul(q, p, k);
+ ep4_mul_basic(r, p, k);
+ TEST_ASSERT(ep4_cmp(q, r) == RLC_EQ, end);
+ bn_neg(k, k);
+ ep4_mul_basic(r, p, k);
+ ep4_neg(r, r);
+ TEST_ASSERT(ep4_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);
+ ep4_mul_slide(r, p, k);
+ TEST_ASSERT(ep4_is_infty(r), end);
+ bn_set_dig(k, 1);
+ ep4_mul_slide(r, p, k);
+ TEST_ASSERT(ep4_cmp(p, r) == RLC_EQ, end);
+ ep4_rand(p);
+ ep4_mul(r, p, n);
+ TEST_ASSERT(ep4_is_infty(r), end);
+ bn_rand_mod(k, n);
+ ep4_mul(q, p, k);
+ ep4_mul_slide(r, p, k);
+ TEST_ASSERT(ep4_cmp(q, r) == RLC_EQ, end);
+ bn_neg(k, k);
+ ep4_mul_slide(r, p, k);
+ ep4_neg(r, r);
+ TEST_ASSERT(ep4_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);
+ ep4_mul_monty(r, p, k);
+ TEST_ASSERT(ep4_is_infty(r), end);
+ bn_set_dig(k, 1);
+ ep4_mul_monty(r, p, k);
+ TEST_ASSERT(ep4_cmp(p, r) == RLC_EQ, end);
+ ep4_rand(p);
+ ep4_mul(r, p, n);
+ TEST_ASSERT(ep4_is_infty(r), end);
+ bn_rand_mod(k, n);
+ ep4_mul(q, p, k);
+ ep4_mul_monty(r, p, k);
+ TEST_ASSERT(ep4_cmp(q, r) == RLC_EQ, end);
+ bn_neg(k, k);
+ ep4_mul_monty(r, p, k);
+ ep4_neg(r, r);
+ TEST_ASSERT(ep4_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);
+ ep4_mul_lwnaf(r, p, k);
+ TEST_ASSERT(ep4_is_infty(r), end);
+ bn_set_dig(k, 1);
+ ep4_mul_lwnaf(r, p, k);
+ TEST_ASSERT(ep4_cmp(p, r) == RLC_EQ, end);
+ ep4_rand(p);
+ ep4_mul(r, p, n);
+ TEST_ASSERT(ep4_is_infty(r), end);
+ bn_rand_mod(k, n);
+ ep4_mul(q, p, k);
+ ep4_mul_lwnaf(r, p, k);
+ TEST_ASSERT(ep4_cmp(q, r) == RLC_EQ, end);
+ bn_neg(k, k);
+ ep4_mul_lwnaf(r, p, k);
+ ep4_neg(r, r);
+ TEST_ASSERT(ep4_cmp(q, r) == RLC_EQ, end);
+ }
+ TEST_END;
+#endif
+
+ TEST_CASE("multiplication by digit is correct") {
+ ep4_mul_dig(r, p, 0);
+ TEST_ASSERT(ep4_is_infty(r), end);
+ ep4_mul_dig(r, p, 1);
+ TEST_ASSERT(ep4_cmp(p, r) == RLC_EQ, end);
+ bn_rand(k, RLC_POS, RLC_DIG);
+ ep4_mul(q, p, k);
+ ep4_mul_dig(r, p, k->dp[0]);
+ TEST_ASSERT(ep4_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);
+ ep4_free(p);
+ ep4_free(q);
+ ep4_free(r);
+ return code;
+}
+
+static int fixed4(void) {
+ int code = RLC_ERR;
+ bn_t n, k;
+ ep4_t p, q, r, t[RLC_EPX_TABLE_MAX];
+
+ bn_null(n);
+ bn_null(k);
+ ep4_null(p);
+ ep4_null(q);
+ ep4_null(r);
+
+ for (int i = 0; i < RLC_EPX_TABLE_MAX; i++) {
+ ep4_null(t[i]);
+ }
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(k);
+ ep4_new(p);
+ ep4_new(q);
+ ep4_new(r);
+
+ ep4_curve_get_gen(p);
+ ep4_curve_get_ord(n);
+
+ for (int i = 0; i < RLC_EP_TABLE; i++) {
+ ep4_new(t[i]);
+ }
+ TEST_CASE("fixed point multiplication is correct") {
+ ep4_rand(p);
+ ep4_mul_pre(t, p);
+ bn_zero(k);
+ ep4_mul_fix(r, t, k);
+ TEST_ASSERT(ep4_is_infty(r), end);
+ bn_set_dig(k, 1);
+ ep4_mul_fix(r, t, k);
+ TEST_ASSERT(ep4_cmp(p, r) == RLC_EQ, end);
+ bn_rand_mod(k, n);
+ ep4_mul(q, p, k);
+ ep4_mul_fix(q, t, k);
+ ep4_mul(r, p, k);
+ TEST_ASSERT(ep4_cmp(q, r) == RLC_EQ, end);
+ bn_neg(k, k);
+ ep4_mul_fix(r, t, k);
+ ep4_neg(r, r);
+ TEST_ASSERT(ep4_cmp(q, r) == RLC_EQ, end);
+ } TEST_END;
+ for (int i = 0; i < RLC_EP_TABLE; i++) {
+ ep4_free(t[i]);
+ }
+
+#if EP_FIX == BASIC || !defined(STRIP)
+ for (int i = 0; i < RLC_EP_TABLE_BASIC; i++) {
+ ep4_new(t[i]);
+ }
+ TEST_CASE("binary fixed point multiplication is correct") {
+ ep4_rand(p);
+ ep4_mul_pre_basic(t, p);
+ bn_zero(k);
+ ep4_mul_fix_basic(r, t, k);
+ TEST_ASSERT(ep4_is_infty(r), end);
+ bn_set_dig(k, 1);
+ ep4_mul_fix_basic(r, t, k);
+ TEST_ASSERT(ep4_cmp(p, r) == RLC_EQ, end);
+ bn_rand_mod(k, n);
+ ep4_mul(r, p, k);
+ ep4_mul_fix_basic(q, t, k);
+ TEST_ASSERT(ep4_cmp(q, r) == RLC_EQ, end);
+ bn_neg(k, k);
+ ep4_mul_fix_basic(r, t, k);
+ ep4_neg(r, r);
+ TEST_ASSERT(ep4_cmp(q, r) == RLC_EQ, end);
+ } TEST_END;
+ for (int i = 0; i < RLC_EP_TABLE_BASIC; i++) {
+ ep4_free(t[i]);
+ }
+#endif
+
+#if EP_FIX == COMBS || !defined(STRIP)
+ for (int i = 0; i < RLC_EP_TABLE_COMBS; i++) {
+ ep4_new(t[i]);
+ }
+ TEST_CASE("single-table comb fixed point multiplication is correct") {
+ ep4_rand(p);
+ ep4_mul_pre_combs(t, p);
+ bn_zero(k);
+ ep4_mul_fix_combs(r, t, k);
+ TEST_ASSERT(ep4_is_infty(r), end);
+ bn_set_dig(k, 1);
+ ep4_mul_fix_combs(r, t, k);
+ TEST_ASSERT(ep4_cmp(p, r) == RLC_EQ, end);
+ bn_rand_mod(k, n);
+ ep4_mul(r, p, k);
+ ep4_mul_fix_combs(q, t, k);
+ TEST_ASSERT(ep4_cmp(q, r) == RLC_EQ, end);
+ bn_neg(k, k);
+ ep4_mul_fix_combs(r, t, k);
+ ep4_neg(r, r);
+ TEST_ASSERT(ep4_cmp(q, r) == RLC_EQ, end);
+ } TEST_END;
+ for (int i = 0; i < RLC_EP_TABLE_COMBS; i++) {
+ ep4_free(t[i]);
+ }
+#endif
+
+#if EP_FIX == COMBD || !defined(STRIP)
+ for (int i = 0; i < RLC_EP_TABLE_COMBD; i++) {
+ ep4_new(t[i]);
+ }
+ TEST_CASE("double-table comb fixed point multiplication is correct") {
+ ep4_rand(p);
+ ep4_mul_pre_combd(t, p);
+ bn_zero(k);
+ ep4_mul_fix_combd(r, t, k);
+ TEST_ASSERT(ep4_is_infty(r), end);
+ bn_set_dig(k, 1);
+ ep4_mul_fix_combd(r, t, k);
+ TEST_ASSERT(ep4_cmp(p, r) == RLC_EQ, end);
+ bn_rand_mod(k, n);
+ ep4_mul(r, p, k);
+ ep4_mul_fix_combd(q, t, k);
+ TEST_ASSERT(ep4_cmp(q, r) == RLC_EQ, end);
+ bn_neg(k, k);
+ ep4_mul_fix_combd(r, t, k);
+ ep4_neg(r, r);
+ TEST_ASSERT(ep4_cmp(q, r) == RLC_EQ, end);
+ } TEST_END;
+ for (int i = 0; i < RLC_EP_TABLE_COMBD; i++) {
+ ep4_free(t[i]);
+ }
+#endif
+
+#if EP_FIX == LWNAF || !defined(STRIP)
+ for (int i = 0; i < RLC_EP_TABLE_LWNAF; i++) {
+ ep4_new(t[i]);
+ }
+ TEST_CASE("left-to-right w-naf fixed point multiplication is correct") {
+ ep4_rand(p);
+ ep4_mul_pre_lwnaf(t, p);
+ bn_zero(k);
+ ep4_mul_fix_lwnaf(r, t, k);
+ TEST_ASSERT(ep4_is_infty(r), end);
+ bn_set_dig(k, 1);
+ ep4_mul_fix_lwnaf(r, t, k);
+ TEST_ASSERT(ep4_cmp(p, r) == RLC_EQ, end);
+ bn_rand_mod(k, n);
+ ep4_mul(r, p, k);
+ ep4_mul_fix_lwnaf(q, t, k);
+ TEST_ASSERT(ep4_cmp(q, r) == RLC_EQ, end);
+ bn_neg(k, k);
+ ep4_mul_fix_lwnaf(r, t, k);
+ ep4_neg(r, r);
+ TEST_ASSERT(ep4_cmp(q, r) == RLC_EQ, end);
+ } TEST_END;
+ for (int i = 0; i < RLC_EP_TABLE_LWNAF; i++) {
+ ep4_free(t[i]);
+ }
+#endif
+ }
+ RLC_CATCH_ANY {
+ util_print("FATAL ERROR!\n");
+ RLC_ERROR(end);
+ }
+ code = RLC_OK;
+ end:
+ ep4_free(p);
+ ep4_free(q);
+ ep4_free(r);
+ bn_free(n);
+ bn_free(k);
+ return code;
+}
+
+static int simultaneous4(void) {
+ int code = RLC_ERR;
+ bn_t n, k[2];
+ ep4_t p[2], r;
+
+ bn_null(n);
+ bn_null(k[0]);
+ bn_null(k[1]);
+ ep4_null(p[0]);
+ ep4_null(p[1]);
+ ep4_null(r);
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(k[0]);
+ bn_new(k[1]);
+ ep4_new(p[0]);
+ ep4_new(p[1]);
+ ep4_new(r);
+
+ ep4_curve_get_gen(p[0]);
+ ep4_curve_get_ord(n);
+
+ TEST_CASE("simultaneous point multiplication is correct") {
+ bn_zero(k[0]);
+ bn_rand_mod(k[1], n);
+ ep4_mul(p[1], p[0], k[1]);
+ ep4_mul_sim(r, p[0], k[0], p[0], k[1]);
+ TEST_ASSERT(ep4_cmp(p[1], r) == RLC_EQ, end);
+ bn_rand_mod(k[0], n);
+ bn_zero(k[1]);
+ ep4_mul(p[1], p[0], k[0]);
+ ep4_mul_sim(r, p[0], k[0], p[0], k[1]);
+ TEST_ASSERT(ep4_cmp(p[1], r) == RLC_EQ, end);
+ bn_rand_mod(k[0], n);
+ bn_rand_mod(k[1], n);
+ ep4_mul_sim(r, p[0], k[0], p[1], k[1]);
+ ep4_mul(p[0], p[0], k[0]);
+ ep4_mul(p[1], p[1], k[1]);
+ ep4_add(p[1], p[1], p[0]);
+ TEST_ASSERT(ep4_cmp(p[1], r) == RLC_EQ, end);
+ bn_neg(k[0], k[0]);
+ ep4_mul_sim(r, p[0], k[0], p[1], k[1]);
+ ep4_mul(p[0], p[0], k[0]);
+ ep4_mul(p[1], p[1], k[1]);
+ ep4_add(p[1], p[1], p[0]);
+ TEST_ASSERT(ep4_cmp(p[1], r) == RLC_EQ, end);
+ bn_neg(k[1], k[1]);
+ ep4_mul_sim(r, p[0], k[0], p[1], k[1]);
+ ep4_mul(p[0], p[0], k[0]);
+ ep4_mul(p[1], p[1], k[1]);
+ ep4_add(p[1], p[1], p[0]);
+ TEST_ASSERT(ep4_cmp(p[1], r) == RLC_EQ, end);
+ ep4_mul_sim(r, p[0], k[0], p[1], k[1]);
+ ep4_mul_sim_lot(p[1], p, k, 2);
+ TEST_ASSERT(ep4_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);
+ ep4_mul(p[1], p[0], k[1]);
+ ep4_mul_sim_basic(r, p[0], k[0], p[0], k[1]);
+ TEST_ASSERT(ep4_cmp(p[1], r) == RLC_EQ, end);
+ bn_rand_mod(k[0], n);
+ bn_zero(k[1]);
+ ep4_mul(p[1], p[0], k[0]);
+ ep4_mul_sim_basic(r, p[0], k[0], p[0], k[1]);
+ TEST_ASSERT(ep4_cmp(p[1], r) == RLC_EQ, end);
+ bn_rand_mod(k[0], n);
+ bn_rand_mod(k[1], n);
+ ep4_mul_sim_basic(r, p[0], k[0], p[1], k[1]);
+ ep4_mul(p[0], p[0], k[0]);
+ ep4_mul(p[1], p[1], k[1]);
+ ep4_add(p[1], p[1], p[0]);
+ TEST_ASSERT(ep4_cmp(p[1], r) == RLC_EQ, end);
+ bn_neg(k[0], k[0]);
+ ep4_mul_sim_basic(r, p[0], k[0], p[1], k[1]);
+ ep4_mul(p[0], p[0], k[0]);
+ ep4_mul(p[1], p[1], k[1]);
+ ep4_add(p[1], p[1], p[0]);
+ TEST_ASSERT(ep4_cmp(p[1], r) == RLC_EQ, end);
+ bn_neg(k[1], k[1]);
+ ep4_mul_sim_basic(r, p[0], k[0], p[1], k[1]);
+ ep4_mul(p[0], p[0], k[0]);
+ ep4_mul(p[1], p[1], k[1]);
+ ep4_add(p[1], p[1], p[0]);
+ TEST_ASSERT(ep4_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);
+ ep4_mul(p[1], p[0], k[1]);
+ ep4_mul_sim_trick(r, p[0], k[0], p[0], k[1]);
+ TEST_ASSERT(ep4_cmp(p[1], r) == RLC_EQ, end);
+ bn_rand_mod(k[0], n);
+ bn_zero(k[1]);
+ ep4_mul(p[1], p[0], k[0]);
+ ep4_mul_sim_trick(r, p[0], k[0], p[0], k[1]);
+ TEST_ASSERT(ep4_cmp(p[1], r) == RLC_EQ, end);
+ bn_rand_mod(k[0], n);
+ bn_rand_mod(k[1], n);
+ ep4_mul_sim_trick(r, p[0], k[0], p[1], k[1]);
+ ep4_mul(p[0], p[0], k[0]);
+ ep4_mul(p[1], p[1], k[1]);
+ ep4_add(p[1], p[1], p[0]);
+ TEST_ASSERT(ep4_cmp(p[1], r) == RLC_EQ, end);
+ bn_neg(k[0], k[0]);
+ ep4_mul_sim_trick(r, p[0], k[0], p[1], k[1]);
+ ep4_mul(p[0], p[0], k[0]);
+ ep4_mul(p[1], p[1], k[1]);
+ ep4_add(p[1], p[1], p[0]);
+ TEST_ASSERT(ep4_cmp(p[1], r) == RLC_EQ, end);
+ bn_neg(k[1], k[1]);
+ ep4_mul_sim_trick(r, p[0], k[0], p[1], k[1]);
+ ep4_mul(p[0], p[0], k[0]);
+ ep4_mul(p[1], p[1], k[1]);
+ ep4_add(p[1], p[1], p[0]);
+ TEST_ASSERT(ep4_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);
+ ep4_mul(p[1], p[0], k[1]);
+ ep4_mul_sim_inter(r, p[0], k[0], p[0], k[1]);
+ TEST_ASSERT(ep4_cmp(p[1], r) == RLC_EQ, end);
+ bn_rand_mod(k[0], n);
+ bn_zero(k[1]);
+ ep4_mul(p[1], p[0], k[0]);
+ ep4_mul_sim_inter(r, p[0], k[0], p[0], k[1]);
+ TEST_ASSERT(ep4_cmp(p[1], r) == RLC_EQ, end);
+ bn_rand_mod(k[0], n);
+ bn_rand_mod(k[1], n);
+ ep4_mul_sim_inter(r, p[0], k[0], p[1], k[1]);
+ ep4_mul(p[0], p[0], k[0]);
+ ep4_mul(p[1], p[1], k[1]);
+ ep4_add(p[1], p[1], p[0]);
+ TEST_ASSERT(ep4_cmp(p[1], r) == RLC_EQ, end);
+ bn_neg(k[0], k[0]);
+ ep4_mul_sim_inter(r, p[0], k[0], p[1], k[1]);
+ ep4_mul(p[0], p[0], k[0]);
+ ep4_mul(p[1], p[1], k[1]);
+ ep4_add(p[1], p[1], p[0]);
+ TEST_ASSERT(ep4_cmp(p[1], r) == RLC_EQ, end);
+ bn_neg(k[1], k[1]);
+ ep4_mul_sim_inter(r, p[0], k[0], p[1], k[1]);
+ ep4_mul(p[0], p[0], k[0]);
+ ep4_mul(p[1], p[1], k[1]);
+ ep4_add(p[1], p[1], p[0]);
+ TEST_ASSERT(ep4_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);
+ ep4_mul(p[1], p[0], k[1]);
+ ep4_mul_sim_joint(r, p[0], k[0], p[0], k[1]);
+ TEST_ASSERT(ep4_cmp(p[1], r) == RLC_EQ, end);
+ bn_rand_mod(k[0], n);
+ bn_zero(k[1]);
+ ep4_mul(p[1], p[0], k[0]);
+ ep4_mul_sim_joint(r, p[0], k[0], p[0], k[1]);
+ TEST_ASSERT(ep4_cmp(p[1], r) == RLC_EQ, end);
+ bn_rand_mod(k[0], n);
+ bn_rand_mod(k[1], n);
+ ep4_mul_sim_joint(r, p[0], k[0], p[1], k[1]);
+ ep4_mul(p[0], p[0], k[0]);
+ ep4_mul(p[1], p[1], k[1]);
+ ep4_add(p[1], p[1], p[0]);
+ TEST_ASSERT(ep4_cmp(p[1], r) == RLC_EQ, end);
+ bn_neg(k[0], k[0]);
+ ep4_mul_sim_joint(r, p[0], k[0], p[1], k[1]);
+ ep4_mul(p[0], p[0], k[0]);
+ ep4_mul(p[1], p[1], k[1]);
+ ep4_add(p[1], p[1], p[0]);
+ TEST_ASSERT(ep4_cmp(p[1], r) == RLC_EQ, end);
+ bn_neg(k[1], k[1]);
+ ep4_mul_sim_joint(r, p[0], k[0], p[1], k[1]);
+ ep4_mul(p[0], p[0], k[0]);
+ ep4_mul(p[1], p[1], k[1]);
+ ep4_add(p[1], p[1], p[0]);
+ TEST_ASSERT(ep4_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);
+ ep4_mul(p[1], p[0], k[1]);
+ ep4_mul_sim_gen(r, k[0], p[0], k[1]);
+ TEST_ASSERT(ep4_cmp(p[1], r) == RLC_EQ, end);
+ bn_rand_mod(k[0], n);
+ bn_zero(k[1]);
+ ep4_mul_gen(p[1], k[0]);
+ ep4_mul_sim_gen(r, k[0], p[0], k[1]);
+ TEST_ASSERT(ep4_cmp(p[1], r) == RLC_EQ, end);
+ bn_rand_mod(k[0], n);
+ bn_rand_mod(k[1], n);
+ ep4_mul_sim_gen(r, k[0], p[1], k[1]);
+ ep4_curve_get_gen(p[0]);
+ ep4_mul_sim(p[1], p[0], k[0], p[1], k[1]);
+ TEST_ASSERT(ep4_cmp(p[1], r) == RLC_EQ, end);
+ bn_neg(k[0], k[0]);
+ ep4_mul_sim_gen(r, k[0], p[1], k[1]);
+ ep4_curve_get_gen(p[0]);
+ ep4_mul_sim(p[1], p[0], k[0], p[1], k[1]);
+ TEST_ASSERT(ep4_cmp(p[1], r) == RLC_EQ, end);
+ bn_neg(k[1], k[1]);
+ ep4_mul_sim_gen(r, k[0], p[1], k[1]);
+ ep4_curve_get_gen(p[0]);
+ ep4_mul_sim(p[1], p[0], k[0], p[1], k[1]);
+ TEST_ASSERT(ep4_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]);
+ ep4_free(p[0]);
+ ep4_free(p[1]);
+ ep4_free(r);
+ return code;
+}
+
+static int hashing4(void) {
+ int code = RLC_ERR;
+ bn_t n;
+ ep4_t p;
+ uint8_t msg[5];
+
+ bn_null(n);
+ ep4_null(p);
+
+ RLC_TRY {
+ bn_new(n);
+ ep4_new(p);
+
+ ep4_curve_get_ord(n);
+
+ 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);
+ ep4_mul(p, p, n);
+ TEST_ASSERT(ep4_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);
+ ep4_free(p);
+ return code;
+}
+
+static int frobenius4(void) {
+ int code = RLC_ERR;
+ ep4_t a, b, c;
+ bn_t d, n;
+
+ ep4_null(a);
+ ep4_null(b);
+ ep4_null(c);
+ bn_null(d);
+ bn_null(n);
+
+ RLC_TRY {
+ ep4_new(a);
+ ep4_new(b);
+ ep4_new(c);
+ bn_new(d);
+ bn_new(n);
+
+ ep4_curve_get_ord(n);
+
+ TEST_CASE("frobenius and point multiplication are consistent") {
+ ep4_rand(a);
+ ep4_frb(b, a, 1);
+ d->used = RLC_FP_DIGS;
+ dv_copy(d->dp, fp_prime_get(), RLC_FP_DIGS);
+ bn_mod(d, d, n);
+ ep4_mul(c, a, d);
+ TEST_ASSERT(ep4_cmp(c, b) == RLC_EQ, end);
+ } TEST_END;
+ }
+ RLC_CATCH_ANY {
+ util_print("FATAL ERROR!\n");
+ RLC_ERROR(end);
+ }
+ code = RLC_OK;
+ end:
+ ep4_free(a);
+ ep4_free(b);
+ ep4_free(c);
+ bn_free(d);
+ bn_free(n);
+ return code;
+}
+
+int main(void) {
+ int r0, r1;
+
+ 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 = 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();
+ return 1;
+ }
+
+ if (doubling4() != RLC_OK) {
+ core_clean();
+ return 1;
+ }
+
+ if (multiplication4() != RLC_OK) {
+ core_clean();
+ return 1;
+ }
+
+ if (fixed4() != RLC_OK) {
+ core_clean();
+ return 1;
+ }
+
+ if (simultaneous4() != RLC_OK) {
+ core_clean();
+ return 1;
+ }
+
+ if (hashing4() != RLC_OK) {
+ core_clean();
+ return 1;
+ }
+
+ if (frobenius4() != RLC_OK) {
+ core_clean();
+ return 1;
+ }
+ }
+
+ if (!r0 && !r1) {
+ RLC_THROW(ERR_NO_CURVE);
+ core_clean();
+ return 0;
}
util_banner("All tests have passed.\n", 0);
diff --git a/contrib/relic/test/test_err.c b/contrib/relic/test/test_err.c
index 16c753643..b87ea2c26 100644
--- a/contrib/relic/test/test_err.c
+++ b/contrib/relic/test/test_err.c
@@ -70,6 +70,16 @@ static void dummy3(void) {
}
}
+static void dummy4(void) {
+ RLC_TRY {
+ dummy3();
+ } RLC_CATCH_ANY {
+ RLC_THROW(ERR_CAUGHT);
+ } RLC_FINALLY {
+ }
+}
+
+
int main(void) {
err_t e;
char *msg = NULL;
@@ -115,6 +125,24 @@ int main(void) {
bn_new(a);
dummy3();
}
+ RLC_CATCH(e) {
+ bn_free(a);
+ switch (e) {
+ case ERR_NO_MEMORY:
+ TEST_END;
+ break;
+ }
+ }
+ }
+
+ TEST_ONCE("throw in deep try-catch is correct and functions are printed") {
+ bn_t a;
+ bn_null(a);
+
+ RLC_TRY {
+ bn_new(a);
+ dummy4();
+ }
RLC_CATCH(e) {
bn_free(a);
switch (e) {
@@ -127,14 +155,14 @@ int main(void) {
}
#endif
- util_banner("All tests have passed.\n", 0);
-
code = RLC_OK;
+
end:
core_clean();
- if (code == RLC_ERR)
+ if (code == RLC_ERR) {
+ util_banner("All tests have passed.\n", 0);
return 0;
- else {
+ } else {
return 1;
}
}
diff --git a/contrib/relic/test/test_fb.c b/contrib/relic/test/test_fb.c
index c3c7728a9..4c153f340 100644
--- a/contrib/relic/test/test_fb.c
+++ b/contrib/relic/test/test_fb.c
@@ -847,15 +847,13 @@ static int inversion(void) {
static int exponentiation(void) {
int code = RLC_ERR;
- fb_t a, b, c, t[RLC_FB_TABLE_MAX];
+ fb_t a, b, c;
+ fb_st t[RLC_FB_TABLE_MAX];
bn_t d;
fb_null(a);
fb_null(b);
fb_null(c);
- for (int i = 0; i < RLC_FB_TABLE_MAX; i++) {
- fb_null(t[i]);
- }
bn_null(d);
RLC_TRY {
@@ -913,15 +911,11 @@ static int exponentiation(void) {
} TEST_END;
#endif
- for (int i = 0; i < RLC_FB_TABLE; i++) {
- fb_new(t[i]);
- }
-
TEST_CASE("iterated squaring is correct") {
fb_rand(a);
bn_rand(d, RLC_POS, 4);
fb_itr_pre(t, d->dp[0]);
- fb_itr(b, a, d->dp[0], (const fb_t *)t);
+ fb_itr(b, a, d->dp[0], (const fb_st *)t);
for (int j = 0; j < d->dp[0]; j++) {
fb_sqr(a, a);
}
@@ -932,17 +926,13 @@ static int exponentiation(void) {
fb_rand(a);
bn_rand(d, RLC_POS, 4);
fb_itr_pre(t, -d->dp[0]);
- fb_itr(b, a, -d->dp[0], (const fb_t *)t);
+ fb_itr(b, a, -d->dp[0], (const fb_st *)t);
for (int j = 0; j < d->dp[0]; j++) {
fb_srt(a, a);
}
TEST_ASSERT(fb_cmp(a, b) == RLC_EQ, end);
} TEST_END;
- for (int i = 0; i < RLC_FB_TABLE; i++) {
- fb_free(t[i]);
- }
-
#if FB_ITR == BASIC || !defined(STRIP)
TEST_CASE("basic iterated squaring is correct") {
fb_rand(a);
@@ -966,15 +956,11 @@ static int exponentiation(void) {
#endif
#if FB_ITR == QUICK || !defined(STRIP)
- for (int i = 0; i < RLC_FB_TABLE_QUICK; i++) {
- fb_new(t[i]);
- fb_zero(t[i]);
- }
TEST_CASE("fast iterated squaring is correct") {
fb_rand(a);
bn_rand(d, RLC_POS, 4);
fb_itr_pre_quick(t, d->dp[0]);
- fb_itr_quick(b, a, (const fb_t *)t);
+ fb_itr_quick(b, a, (const fb_st *)t);
for (int j = 0; j < d->dp[0]; j++) {
fb_sqr(a, a);
}
@@ -985,16 +971,12 @@ static int exponentiation(void) {
fb_rand(a);
bn_rand(d, RLC_POS, 4);
fb_itr_pre_quick(t, -d->dp[0]);
- fb_itr_quick(b, a, (const fb_t *)t);
+ fb_itr_quick(b, a, (const fb_st *)t);
for (int j = 0; j < d->dp[0]; j++) {
fb_srt(a, a);
}
TEST_ASSERT(fb_cmp(a, b) == RLC_EQ, end);
} TEST_END;
-
- for (int i = 0; i < RLC_FB_TABLE_QUICK; i++) {
- fb_free(t[i]);
- }
#endif
}
RLC_CATCH_ANY {
diff --git a/contrib/relic/test/test_fp.c b/contrib/relic/test/test_fp.c
index 291829f8b..05ce289e4 100644
--- a/contrib/relic/test/test_fp.c
+++ b/contrib/relic/test/test_fp.c
@@ -856,6 +856,17 @@ static int inversion(void) {
} TEST_END;
#endif
+#if FP_INV == JMPDS || !defined(STRIP)
+ TEST_CASE("jump division step inversion is correct") {
+ do {
+ fp_rand(a);
+ } while (fp_is_zero(a));
+ fp_inv(b, a);
+ fp_inv_jmpds(c, a);
+ TEST_ASSERT(fp_cmp(c, b) == RLC_EQ, end);
+ } TEST_END;
+#endif
+
#if FP_INV == LOWER || !defined(STRIP)
TEST_CASE("lower inversion is correct") {
do {
@@ -894,6 +905,66 @@ static int inversion(void) {
return code;
}
+static int symbol(void) {
+ int code = RLC_ERR;
+ fp_t a, b;
+
+ fp_null(a);
+ fp_null(b);
+
+ RLC_TRY {
+ fp_new(a);
+ fp_new(b);
+
+ TEST_CASE("symbol computation is correct") {
+ fp_zero(a);
+ TEST_ASSERT(fp_smb(a) == 0, end);
+ fp_rand(a);
+ fp_sqr(a, a);
+ TEST_ASSERT(fp_smb(a) == 1, end);
+ do {
+ fp_rand(a);
+ } while(fp_srt(b, a) == 1);
+ TEST_ASSERT(fp_smb(a) == -1, end);
+ }
+ TEST_END;
+
+#if FP_SMB == BASIC || !defined(STRIP)
+ TEST_CASE("basic symbol computation is correct") {
+ fp_rand(a);
+ 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);
+ TEST_ASSERT(fp_smb(a) == fp_smb_divst(a), end);
+ } TEST_END;
+#endif
+#if FP_SMB == JMPDS || !defined(STRIP)
+ TEST_CASE("jump division step symbol computation is correct") {
+ fp_rand(a);
+ TEST_ASSERT(fp_smb(a) == fp_smb_jmpds(a), end);
+ } TEST_END;
+#endif
+#if FP_SMB == LOWER || !defined(STRIP)
+ TEST_CASE("lower symbol computation is correct") {
+ fp_rand(a);
+ TEST_ASSERT(fp_smb(a) == fp_smb_lower(a), end);
+ } TEST_END;
+#endif
+ }
+ RLC_CATCH_ANY {
+ RLC_ERROR(end);
+ }
+ code = RLC_OK;
+ end:
+ fp_free(a);
+ fp_free(b);
+ return code;
+}
+
static int exponentiation(void) {
int code = RLC_ERR;
fp_t a, b, c;
@@ -1147,6 +1218,11 @@ int main(void) {
return 1;
}
+ if (symbol() != RLC_OK) {
+ core_clean();
+ return 1;
+ }
+
if (exponentiation() != RLC_OK) {
core_clean();
return 1;
diff --git a/contrib/relic/test/test_fpx.c b/contrib/relic/test/test_fpx.c
index 3b043d484..a7c8eaa23 100644
--- a/contrib/relic/test/test_fpx.c
+++ b/contrib/relic/test/test_fpx.c
@@ -1915,16 +1915,14 @@ static int squaring4(void) {
static int inversion4(void) {
int code = RLC_ERR;
- fp4_t a, b, c;
-
- fp4_null(a);
- fp4_null(b);
- fp4_null(c);
+ fp4_t a, b, c, d[2];
RLC_TRY {
fp4_new(a);
fp4_new(b);
fp4_new(c);
+ fp4_new(d[0]);
+ fp4_new(d[1]);
TEST_CASE("inversion is correct") {
do {
@@ -1934,6 +1932,20 @@ static int inversion4(void) {
fp4_mul(c, a, b);
TEST_ASSERT(fp4_cmp_dig(c, 1) == RLC_EQ, end);
} TEST_END;
+
+ TEST_CASE("simultaneous inversion is correct") {
+ do {
+ fp4_rand(a);
+ fp4_rand(b);
+ } while (fp4_is_zero(a) || fp4_is_zero(b));
+ fp4_copy(d[0], a);
+ fp4_copy(d[1], b);
+ fp4_inv(a, a);
+ fp4_inv(b, b);
+ fp4_inv_sim(d, d, 2);
+ TEST_ASSERT(fp4_cmp(d[0], a) == RLC_EQ &&
+ fp4_cmp(d[1], b) == RLC_EQ, end);
+ } TEST_END;
}
RLC_CATCH_ANY {
util_print("FATAL ERROR!\n");
@@ -1944,6 +1956,8 @@ static int inversion4(void) {
fp4_free(a);
fp4_free(b);
fp4_free(c);
+ fp4_free(d[0]);
+ fp4_free(d[1]);
return code;
}
@@ -2004,6 +2018,64 @@ static int exponentiation4(void) {
return code;
}
+static int square_root4(void) {
+ int code = RLC_ERR;
+ fp4_t a, b, c;
+ int r;
+
+ fp4_null(a);
+ fp4_null(b);
+ fp4_null(c);
+
+ RLC_TRY {
+ fp4_new(a);
+ fp4_new(b);
+ fp4_new(c);
+
+ TEST_CASE("square root extraction is correct") {
+ fp4_zero(a);
+ fp4_sqr(c, a);
+ r = fp4_srt(b, c);
+ TEST_ASSERT(r, end);
+ TEST_ASSERT(fp4_cmp(b, a) == RLC_EQ ||
+ fp4_cmp(c, a) == RLC_EQ, end);
+ fp2_rand(a[0]);
+ fp2_zero(a[1]);
+ fp4_sqr(c, a);
+ r = fp4_srt(b, c);
+ fp4_neg(c, b);
+ TEST_ASSERT(r, end);
+ TEST_ASSERT(fp4_cmp(b, a) == RLC_EQ ||
+ fp4_cmp(c, a) == RLC_EQ, end);
+ fp2_zero(a[0]);
+ fp2_rand(a[1]);
+ fp4_sqr(c, a);
+ r = fp4_srt(b, c);
+ fp4_neg(c, b);
+ TEST_ASSERT(r, end);
+ TEST_ASSERT(fp4_cmp(b, a) == RLC_EQ ||
+ fp4_cmp(c, a) == RLC_EQ, end);
+ fp4_rand(a);
+ fp4_sqr(c, a);
+ r = fp4_srt(b, c);
+ fp4_neg(c, b);
+ TEST_ASSERT(r, end);
+ TEST_ASSERT(fp4_cmp(b, a) == RLC_EQ ||
+ fp4_cmp(c, a) == RLC_EQ, end);
+ } TEST_END;
+ }
+ RLC_CATCH_ANY {
+ util_print("FATAL ERROR!\n");
+ RLC_ERROR(end);
+ }
+ code = RLC_OK;
+ end:
+ fp4_free(a);
+ fp4_free(b);
+ fp4_free(c);
+ return code;
+}
+
static int memory6(void) {
err_t e;
int code = RLC_ERR;
@@ -4286,6 +4358,7 @@ static int cyclotomic12(void) {
bn_neg(f, f);
fp12_exp_cyc(c, a, f);
fp12_inv_cyc(c, c);
+ TEST_ASSERT(fp12_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);
@@ -5102,7 +5175,7 @@ static int util24(void) {
TEST_CASE("reading and writing a finite field element are consistent") {
fp24_rand(a);
- fp24_write_bin(bin, sizeof(bin), a);
+ fp24_write_bin(bin, sizeof(bin), a, 0);
fp24_read_bin(b, bin, sizeof(bin));
TEST_ASSERT(fp24_cmp(a, b) == RLC_EQ, end);
}
@@ -5110,7 +5183,7 @@ static int util24(void) {
TEST_CASE("getting the size of a finite field element is correct") {
fp24_rand(a);
- TEST_ASSERT(fp24_size_bin(a) == 24 * RLC_FP_BYTES, end);
+ TEST_ASSERT(fp24_size_bin(a, 0) == 24 * RLC_FP_BYTES, end);
}
TEST_END;
}
@@ -5397,6 +5470,198 @@ static int squaring24(void) {
return code;
}
+static int cyclotomic24(void) {
+ int code = RLC_ERR;
+ fp24_t a, b, c, d[2], e[2];
+ bn_t f;
+
+ fp24_null(a);
+ fp24_null(b);
+ fp24_null(c);
+ fp24_null(d[0]);
+ fp24_null(d[1])
+ fp24_null(e[0]);
+ fp24_null(e[1]);
+ bn_null(f);
+
+ RLC_TRY {
+ fp24_new(a);
+ fp24_new(b);
+ fp24_new(c);
+ fp24_new(d[0]);
+ fp24_new(d[1]);
+ fp24_new(e[0]);
+ fp24_new(e[1]);
+ bn_new(f);
+
+ TEST_CASE("cyclotomic test is correct") {
+ fp24_rand(a);
+ fp24_conv_cyc(a, a);
+ TEST_ASSERT(fp24_test_cyc(a) == 1, end);
+ } TEST_END;
+
+ TEST_CASE("compression in cyclotomic subgroup is correct") {
+ fp24_rand(a);
+ fp24_conv_cyc(a, a);
+ fp24_back_cyc(c, a);
+ TEST_ASSERT(fp24_cmp(a, c) == RLC_EQ, end);
+ } TEST_END;
+
+ TEST_CASE("simultaneous decompression in cyclotomic subgroup is correct") {
+ fp24_rand(d[0]);
+ fp24_rand(d[1]);
+ fp24_conv_cyc(d[0], d[0]);
+ fp24_conv_cyc(d[1], d[1]);
+ fp24_back_cyc_sim(e, d, 2);
+ TEST_ASSERT(fp24_cmp(d[0], e[0]) == RLC_EQ &&
+ fp24_cmp(d[1], e[1]) == RLC_EQ, end);
+ } TEST_END;
+
+ TEST_CASE("cyclotomic squaring is correct") {
+ fp24_rand(a);
+ fp24_conv_cyc(a, a);
+ fp24_sqr(b, a);
+ fp24_sqr_cyc(c, a);
+ TEST_ASSERT(fp24_cmp(b, c) == RLC_EQ, end);
+ } TEST_END;
+
+#if FPX_RDC == BASIC || !defined(STRIP)
+ TEST_CASE("basic cyclotomic squaring is correct") {
+ fp24_rand(a);
+ fp24_conv_cyc(a, a);
+ fp24_sqr_cyc(b, a);
+ fp24_sqr_cyc_basic(c, a);
+ TEST_ASSERT(fp24_cmp(b, c) == RLC_EQ, end);
+ } TEST_END;
+#endif
+
+#if FPX_RDC == LAZYR || !defined(STRIP)
+ TEST_CASE("lazy-reduced cyclotomic squaring is correct") {
+ fp24_rand(a);
+ fp24_conv_cyc(a, a);
+ fp24_sqr_cyc(b, a);
+ fp24_sqr_cyc_lazyr(c, a);
+ TEST_ASSERT(fp24_cmp(b, c) == RLC_EQ, end);
+ } TEST_END;
+#endif
+
+ TEST_CASE("compressed squaring is correct") {
+ fp24_rand(a);
+ fp24_conv_cyc(a, a);
+ fp4_zero(b[0][0]);
+ fp4_zero(b[1][1]);
+ fp4_zero(c[0][0]);
+ fp4_zero(c[1][1]);
+ fp24_sqr(b, a);
+ fp24_sqr_pck(c, a);
+ fp24_back_cyc(c, c);
+ TEST_ASSERT(fp24_cmp(b, c) == RLC_EQ, end);
+ } TEST_END;
+
+#if FPX_RDC == BASIC || !defined(STRIP)
+ TEST_CASE("basic compressed squaring is correct") {
+ fp24_rand(a);
+ fp24_conv_cyc(a, a);
+ fp4_zero(b[0][0]);
+ fp4_zero(b[1][1]);
+ fp4_zero(c[0][0]);
+ fp4_zero(c[1][1]);
+ fp24_sqr_pck(b, a);
+ fp24_sqr_pck_basic(c, a);
+ TEST_ASSERT(fp24_cmp(b, c) == RLC_EQ, end);
+ } TEST_END;
+#endif
+
+#if FPX_RDC == LAZYR || !defined(STRIP)
+ TEST_CASE("lazy-reduced compressed squaring is correct") {
+ fp24_rand(a);
+ fp24_conv_cyc(a, a);
+ fp4_zero(b[0][0]);
+ fp4_zero(b[1][1]);
+ fp4_zero(c[0][0]);
+ fp4_zero(c[1][1]);
+ fp24_sqr_pck(b, a);
+ fp24_sqr_pck_lazyr(c, a);
+ TEST_ASSERT(fp24_cmp(b, c) == RLC_EQ, end);
+ } TEST_END;
+#endif
+
+ TEST_CASE("cyclotomic exponentiation is correct") {
+ fp24_rand(a);
+ fp24_conv_cyc(a, a);
+ bn_zero(f);
+ fp24_exp_cyc(c, a, f);
+ TEST_ASSERT(fp24_cmp_dig(c, 1) == RLC_EQ, end);
+ bn_set_dig(f, 1);
+ fp24_exp_cyc(c, a, f);
+ TEST_ASSERT(fp24_cmp(c, a) == RLC_EQ, end);
+ bn_rand(f, RLC_POS, RLC_DIG);
+ fp24_exp(b, a, f);
+ fp24_exp_cyc(c, a, f);
+ TEST_ASSERT(fp24_cmp(b, c) == RLC_EQ, end);
+ bn_rand(f, RLC_POS, RLC_FP_BITS);
+ fp24_exp_cyc(b, a, f);
+ bn_neg(f, f);
+ fp24_exp_cyc(c, a, f);
+ fp24_inv_cyc(c, c);
+ TEST_ASSERT(fp24_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);
+ fp24_rand(a);
+ fp24_conv_cyc(a, a);
+ fp24_exp_cyc(b, a, f);
+ bn_neg(f, f);
+ fp24_exp_cyc(c, a, f);
+ fp24_inv_cyc(c, c);
+ TEST_ASSERT(fp24_cmp(b, c) == RLC_EQ, end);
+ } TEST_END;
+
+ TEST_CASE("sparse cyclotomic exponentiation is correct") {
+ int g[3] = {0, 0, RLC_FP_BITS - 1};
+ do {
+ bn_rand(f, RLC_POS, RLC_DIG);
+ g[1] = f->dp[0] % RLC_FP_BITS;
+ } while (g[1] == 0 || g[1] == RLC_FP_BITS - 1);
+ bn_set_2b(f, RLC_FP_BITS - 1);
+ bn_set_bit(f, g[1], 1);
+ bn_set_bit(f, 0, 1);
+ fp24_rand(a);
+ fp24_conv_cyc(a, a);
+ fp24_exp(b, a, f);
+ fp24_exp_cyc_sps(c, a, g, 3, RLC_POS);
+ TEST_ASSERT(fp24_cmp(b, c) == RLC_EQ, end);
+ g[0] = 0;
+ fp24_exp_cyc_sps(c, a, g, 0, RLC_POS);
+ TEST_ASSERT(fp24_cmp_dig(c, 1) == RLC_EQ, end);
+ g[0] = 0;
+ fp24_exp_cyc_sps(c, a, g, 1, RLC_POS);
+ TEST_ASSERT(fp24_cmp(c, a) == RLC_EQ, end);
+ g[0] = -1;
+ fp24_exp_cyc_sps(b, a, g, 1, RLC_POS);
+ fp24_inv(b, b);
+ fp24_sqr_cyc(c, a);
+ TEST_ASSERT(fp24_cmp(b, c) == RLC_EQ, end);
+ } TEST_END;
+ }
+ RLC_CATCH_ANY {
+ util_print("FATAL ERROR!\n");
+ RLC_ERROR(end);
+ }
+ code = RLC_OK;
+ end:
+ fp24_free(a);
+ fp24_free(b);
+ fp24_free(c);
+ fp24_free(d[0]);
+ fp24_free(d[1]);
+ fp24_free(e[0]);
+ fp24_free(e[1]);
+ bn_free(f);
+ return code;
+}
+
static int inversion24(void) {
int code = RLC_ERR;
fp24_t a, b, c;
@@ -5461,6 +5726,10 @@ static int exponentiation24(void) {
fp24_exp(c, a, d);
fp24_inv(c, c);
TEST_ASSERT(fp24_cmp(b, c) == RLC_EQ, end);
+ bn_rand(d, RLC_POS, RLC_DIG);
+ fp24_exp_dig(b, a, d->dp[0]);
+ fp24_exp(c, a, d);
+ TEST_ASSERT(fp24_cmp(b, c) == RLC_EQ, end);
} TEST_END;
TEST_CASE("frobenius and exponentiation are consistent") {
@@ -5488,6 +5757,61 @@ static int exponentiation24(void) {
return code;
}
+static int compression24(void) {
+ int code = RLC_ERR;
+ uint8_t bin[24 * RLC_FP_BYTES];
+ fp24_t a, b, c;
+
+ fp24_null(a);
+ fp24_null(b);
+ fp24_null(c);
+
+ RLC_TRY {
+ fp24_new(a);
+ fp24_new(b);
+ fp24_new(c);
+
+ TEST_CASE("compression is consistent") {
+ fp24_rand(a);
+ fp24_pck(b, a);
+ TEST_ASSERT(fp24_upk(c, b) == 1, end);
+ TEST_ASSERT(fp24_cmp(a, c) == RLC_EQ, end);
+ fp24_rand(a);
+ fp24_conv_cyc(a, a);
+ fp24_pck(b, a);
+ TEST_ASSERT(fp24_upk(c, b) == 1, end);
+ TEST_ASSERT(fp24_cmp(a, c) == RLC_EQ, end);
+ } TEST_END;
+
+ TEST_CASE("compression is consistent with reading and writing") {
+ fp24_rand(a);
+ fp24_conv_cyc(a, a);
+ fp24_write_bin(bin, 16 * RLC_FP_BYTES, a, 1);
+ fp24_read_bin(b, bin, 16 * RLC_FP_BYTES);
+ TEST_ASSERT(fp24_cmp(a, b) == RLC_EQ, end);
+ }
+ TEST_END;
+
+ TEST_CASE("getting the size of a compressed field element is correct") {
+ fp24_rand(a);
+ TEST_ASSERT(fp24_size_bin(a, 0) == 24 * RLC_FP_BYTES, end);
+ fp24_conv_cyc(a, a);
+ TEST_ASSERT(fp24_size_bin(a, 1) == 16 * RLC_FP_BYTES, end);
+ }
+ TEST_END;
+ }
+ RLC_CATCH_ANY {
+ util_print("FATAL ERROR!\n");
+ RLC_ERROR(end);
+ }
+ code = RLC_OK;
+ end:
+ fp24_free(a);
+ fp24_free(b);
+ fp24_free(c);
+ return code;
+}
+
static int memory48(void) {
err_t e;
int code = RLC_ERR;
@@ -6072,6 +6396,7 @@ static int cyclotomic48(void) {
bn_neg(f, f);
fp48_exp_cyc(c, a, f);
fp48_inv_cyc(c, c);
+ TEST_ASSERT(fp48_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);
@@ -6818,6 +7143,7 @@ static int cyclotomic54(void) {
bn_neg(f, f);
fp54_exp_cyc(c, a, f);
fp54_inv_cyc(c, c);
+ TEST_ASSERT(fp54_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);
@@ -7174,6 +7500,11 @@ int main(void) {
core_clean();
return 1;
}
+
+ if (square_root4() != RLC_OK) {
+ core_clean();
+ return 1;
+ }
}
/* Fp^6 is defined as a cubic extension of Fp^2. */
@@ -7488,6 +7819,16 @@ int main(void) {
return 1;
}
+ if (cyclotomic24() != RLC_OK) {
+ core_clean();
+ return 1;
+ }
+
+ if (compression24() != RLC_OK) {
+ core_clean();
+ return 1;
+ }
+
util_banner("Extension of degree 48:", 0);
util_banner("Utilities:", 1);
diff --git a/contrib/relic/test/test_pc.c b/contrib/relic/test/test_pc.c
index 6aada90ba..01b4b13e0 100644
--- a/contrib/relic/test/test_pc.c
+++ b/contrib/relic/test/test_pc.c
@@ -367,6 +367,18 @@ static int multiplication1(void) {
g1_mul(r, p, n);
TEST_ASSERT(g1_is_infty(r) == 1, end);
} TEST_END;
+
+ TEST_CASE("point multiplication by digit is correct") {
+ g1_mul_dig(r, p, 0);
+ TEST_ASSERT(g1_is_infty(r), end);
+ g1_mul_dig(r, p, 1);
+ TEST_ASSERT(g1_cmp(p, r) == RLC_EQ, end);
+ bn_rand(k, RLC_POS, RLC_DIG);
+ g1_mul(q, p, k);
+ g1_mul_dig(r, p, k->dp[0]);
+ TEST_ASSERT(g1_cmp(q, r) == RLC_EQ, end);
+ }
+ TEST_END;
}
RLC_CATCH_ANY {
util_print("FATAL ERROR!\n");
@@ -641,7 +653,7 @@ static int memory2(void) {
int util2(void) {
int l, code = RLC_ERR;
g2_t a, b, c;
- uint8_t bin[4 * RLC_PC_BYTES + 1];
+ uint8_t bin[8 * RLC_PC_BYTES + 1];
g2_null(a);
g2_null(b);
@@ -945,6 +957,18 @@ static int multiplication2(void) {
g2_mul(r, p, n);
TEST_ASSERT(g2_is_infty(r) == 1, end);
} TEST_END;
+
+ TEST_CASE("point multiplication by digit is correct") {
+ g2_mul_dig(r, p, 0);
+ TEST_ASSERT(g2_is_infty(r), end);
+ g2_mul_dig(r, p, 1);
+ TEST_ASSERT(g2_cmp(p, r) == RLC_EQ, end);
+ bn_rand(k, RLC_POS, RLC_DIG);
+ g2_mul(q, p, k);
+ g2_mul_dig(r, p, k->dp[0]);
+ TEST_ASSERT(g2_cmp(q, r) == RLC_EQ, end);
+ }
+ TEST_END;
}
RLC_CATCH_ANY {
util_print("FATAL ERROR!\n");
@@ -1157,6 +1181,8 @@ static int validity2(void) {
return code;
}
+#if FP_PRIME != 509
+
static int hashing2(void) {
int code = RLC_ERR;
g2_t a;
@@ -1190,6 +1216,8 @@ static int hashing2(void) {
return code;
}
+#endif
+
static int memory(void) {
err_t e;
int code = RLC_ERR;
@@ -1469,6 +1497,14 @@ int exponentiation(void) {
gt_exp(b, b, e);
gt_mul(b, a, b);
TEST_ASSERT(gt_cmp(b, c) == RLC_EQ, end);
+ gt_exp_dig(b, a, 0);
+ TEST_ASSERT(gt_is_unity(b), end);
+ gt_exp_dig(b, a, 1);
+ TEST_ASSERT(gt_cmp(a, b) == RLC_EQ, end);
+ bn_rand(d, RLC_POS, RLC_DIG);
+ gt_exp(b, a, d);
+ gt_exp_dig(c, a, d->dp[0]);
+ TEST_ASSERT(gt_cmp(b, c) == RLC_EQ, end);
} TEST_END;
}
RLC_CATCH_ANY {
@@ -1709,9 +1745,11 @@ int test2(void) {
return RLC_ERR;
}
+#if FP_PRIME != 509
if (hashing2() != RLC_OK) {
return RLC_ERR;
}
+#endif
return RLC_OK;
}
diff --git a/contrib/relic/test/test_pp.c b/contrib/relic/test/test_pp.c
index 0f8f17c0d..e706a2a91 100644
--- a/contrib/relic/test/test_pp.c
+++ b/contrib/relic/test/test_pp.c
@@ -1257,7 +1257,6 @@ static int pairing12(void) {
TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end);
} TEST_END;
-#if 0
TEST_CASE("weil multi-pairing is correct") {
ep_rand(p[i % 2]);
ep2_rand(q[i % 2]);
@@ -1284,7 +1283,6 @@ static int pairing12(void) {
TEST_ASSERT(fp12_cmp(e1, e2) == RLC_EQ, end);
} TEST_END;
#endif
-#endif
#if PP_MAP == OATEP || !defined(STRIP)
TEST_CASE("optimal ate pairing non-degeneracy is correct") {
@@ -1366,6 +1364,303 @@ static int pairing12(void) {
return code;
}
+static int doubling24(void) {
+ int code = RLC_ERR;
+ bn_t k, n;
+ ep_t p;
+ ep4_t q, r, s;
+ fp24_t e1, e2;
+
+ bn_null(k);
+ bn_null(n);
+ ep_null(p);
+ ep4_null(q);
+ ep4_null(r);
+ ep4_null(s);
+ fp24_null(e1);
+ fp24_null(e2);
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(k);
+ ep_new(p);
+ ep4_new(q);
+ ep4_new(r);
+ ep4_new(s);
+ fp24_new(e1);
+ fp24_new(e2);
+
+ ep_curve_get_ord(n);
+
+ TEST_CASE("miller doubling is correct") {
+ ep_rand(p);
+ ep4_rand(q);
+ ep4_rand(r);
+ pp_dbl_k24(e1, r, q, p);
+ pp_norm_k24(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);
+ fp24_zero(e1);
+ fp24_zero(e2);
+ fp_neg(p->y, p->y);
+ pp_dbl_k24_basic(e2, r, q, p);
+ pp_exp_k24(e2, e2);
+#if EP_ADD == PROJC
+ /* Precompute. */
+ fp_dbl(p->z, p->x);
+ fp_add(p->x, p->z, p->x);
+#endif
+ pp_dbl_k24(e1, r, q, p);
+ pp_exp_k24(e1, e1);
+ TEST_ASSERT(fp24_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);
+ fp24_zero(e1);
+ fp24_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_k24_projc(e2, r, q, p);
+ pp_exp_k24(e2, e2);
+#if EP_ADD == BASIC
+ /* Revert precomputing. */
+ fp_hlv(p->x, p->z);
+#endif
+ pp_dbl_k24(e1, r, q, p);
+ pp_exp_k24(e1, e1);
+ TEST_ASSERT(fp24_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);
+ fp24_free(e1);
+ fp24_free(e2);
+ return code;
+}
+
+static int addition24(void) {
+ int code = RLC_ERR;
+ bn_t k, n;
+ ep_t p;
+ ep4_t q, r, s;
+ fp24_t e1, e2;
+
+ bn_null(k);
+ bn_null(n);
+ ep_null(p);
+ ep4_null(q);
+ ep4_null(r);
+ ep4_null(s);
+ fp24_null(e1);
+ fp24_null(e2);
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(k);
+ ep_new(p);
+ ep4_new(q);
+ ep4_new(r);
+ ep4_new(s);
+ fp24_new(e1);
+ fp24_new(e2);
+
+ ep_curve_get_ord(n);
+
+ TEST_CASE("miller addition is correct") {
+ ep_rand(p);
+ ep4_rand(q);
+ ep4_rand(r);
+ ep4_copy(s, r);
+ pp_add_k24(e1, r, q, p);
+ pp_norm_k24(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_rand(q);
+ ep4_rand(r);
+ ep4_copy(s, r);
+ fp24_zero(e1);
+ fp24_zero(e2);
+ pp_add_k24(e1, r, q, p);
+ pp_exp_k24(e1, e1);
+ pp_add_k24_basic(e2, s, q, p);
+ pp_exp_k24(e2, e2);
+ TEST_ASSERT(fp24_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_rand(q);
+ ep4_rand(r);
+ ep4_copy(s, r);
+ fp24_zero(e1);
+ fp24_zero(e2);
+ pp_add_k24(e1, r, q, p);
+ pp_exp_k24(e1, e1);
+ pp_add_k24_projc(e2, s, q, p);
+ pp_exp_k24(e2, e2);
+ TEST_ASSERT(fp24_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);
+ fp24_free(e1);
+ fp24_free(e2);
+ return code;
+}
+
+static int pairing24(void) {
+ int j, code = RLC_ERR;
+ bn_t k, n;
+ ep_t p[2];
+ ep4_t q[2], r;
+ fp24_t e1, e2;
+
+ bn_null(k);
+ bn_null(n);
+ fp24_null(e1);
+ fp24_null(e2);
+ ep4_null(r);
+
+ RLC_TRY {
+ bn_new(n);
+ bn_new(k);
+ fp24_new(e1);
+ fp24_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_k24(e1, p[0], q[0]);
+ TEST_ASSERT(fp24_cmp_dig(e1, 1) != RLC_EQ, end);
+ ep_set_infty(p[0]);
+ pp_map_k24(e1, p[0], q[0]);
+ TEST_ASSERT(fp24_cmp_dig(e1, 1) == RLC_EQ, end);
+ ep_rand(p[0]);
+ ep4_set_infty(q[0]);
+ pp_map_k24(e1, p[0], q[0]);
+ TEST_ASSERT(fp24_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_k24(e1, p[0], r);
+ pp_map_k24(e2, p[0], q[0]);
+ fp24_exp(e2, e2, k);
+ TEST_ASSERT(fp24_cmp(e1, e2) == RLC_EQ, end);
+ ep_mul(p[0], p[0], k);
+ pp_map_k24(e2, p[0], q[0]);
+ TEST_ASSERT(fp24_cmp(e1, e2) == RLC_EQ, end);
+ ep_dbl(p[0], p[0]);
+ pp_map_k24(e2, p[0], q[0]);
+ fp24_sqr(e1, e1);
+ TEST_ASSERT(fp24_cmp(e1, e2) == RLC_EQ, end);
+ ep4_dbl(q[0], q[0]);
+ pp_map_k24(e2, p[0], q[0]);
+ fp24_sqr(e1, e1);
+ TEST_ASSERT(fp24_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_k24(e1, p[i % 2], q[i % 2]);
+ ep_rand(p[1 - (i % 2)]);
+ ep4_set_infty(q[1 - (i % 2)]);
+ pp_map_sim_k24(e2, p, q, 2);
+ TEST_ASSERT(fp24_cmp(e1, e2) == RLC_EQ, end);
+ ep_set_infty(p[1 - (i % 2)]);
+ ep4_rand(q[1 - (i % 2)]);
+ pp_map_sim_k24(e2, p, q, 2);
+ TEST_ASSERT(fp24_cmp(e1, e2) == RLC_EQ, end);
+ ep4_set_infty(q[i % 2]);
+ pp_map_sim_k24(e2, p, q, 2);
+ TEST_ASSERT(fp24_cmp_dig(e2, 1) == RLC_EQ, end);
+ ep_rand(p[0]);
+ ep4_rand(q[0]);
+ pp_map_k24(e1, p[0], q[0]);
+ ep_rand(p[1]);
+ ep4_rand(q[1]);
+ pp_map_k24(e2, p[1], q[1]);
+ fp24_mul(e1, e1, e2);
+ pp_map_sim_k24(e2, p, q, 2);
+ TEST_ASSERT(fp24_cmp(e1, e2) == 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);
+ fp24_free(e1);
+ fp24_free(e2);
+ ep4_free(r);
+
+ for (j = 0; j < 2; j++) {
+ ep_free(p[j]);
+ ep4_free(q[j]);
+ }
+ return code;
+}
+
/* Put test vectors here until we implement E(Fp^8). */
#define QX000 "266A6ACAA4B8DDCFBF97F09DFBEB01999BFBFF872276FA7700114F761E8971C6C25A53CC77E96BCC9579F63D8A39D641B8070B07EF40E93C301A5B49CE87110CC30E044BEE5A2D43"
#define QX001 "5009EEB2A67C52B79D0727B408A193FFCE76B4F80C8DCF4D61ECEE5471601CD7A94341F697CE9D375DB5470EA055B73C256CCC0AC12F52EAD276C26E001DDCE02DE634BEFCB9CC7C"
@@ -2210,6 +2505,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() == 12) {
if (doubling12() != RLC_OK) {
core_clean();
diff --git a/contrib/relic/test/test_rand.c b/contrib/relic/test/test_rand.c
index a1dcf8f2a..e3de369d3 100644
--- a/contrib/relic/test/test_rand.c
+++ b/contrib/relic/test/test_rand.c
@@ -231,7 +231,7 @@ uint8_t result2[] = {
0x2C, 0xE4, 0xAD, 0x78, 0x2E, 0x7B
};
-#elif MD_MAP == BLAKE2S_160
+#elif MD_MAP == B2S160
#define FUNCTION "blake2s-160"
@@ -259,7 +259,7 @@ uint8_t result2[] = {
0x98, 0x7B, 0x11, 0x8D, 0x9F, 0x97, 0xA1, 0x4E, 0x67, 0x82
};
-#elif MD_MAP == BLAKE2S_256
+#elif MD_MAP == B2S256
uint8_t seed1[63];
diff --git a/contrib/relic/tools/git-creation-date.sh b/contrib/relic/tools/git-creation-date.sh
new file mode 100755
index 000000000..ce70f7036
--- /dev/null
+++ b/contrib/relic/tools/git-creation-date.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+for file in $(git ls-files *.c *.h *.in *.s *.S *.tmpl)
+do
+ HASH=$(git rev-list HEAD "$file" | tail -n 1)
+ DATE=$(git show -s --format="%ad" --date=format:'%Y' $HASH --)
+ printf "%-35s %s\n %s\n" "$file" "$DATE"
+ sed -i "s/Copyright (c) 20[0-9][0-9]/Copyright (c) $DATE/g" "$file"
+done
+
+
diff --git a/js-bindings/wrappers/BignumWrapper.cpp b/js-bindings/wrappers/BignumWrapper.cpp
index c99e83a74..5ff4da42f 100644
--- a/js-bindings/wrappers/BignumWrapper.cpp
+++ b/js-bindings/wrappers/BignumWrapper.cpp
@@ -17,7 +17,7 @@
namespace js_wrappers {
Bignum::Bignum() {
- bn_init(&content, 1);
+ bn_make(&content, 1);
}
Bignum::~Bignum() {
diff --git a/js_build.sh b/js_build.sh
index 0fb358946..29928af4a 100755
--- a/js_build.sh
+++ b/js_build.sh
@@ -5,5 +5,5 @@ git submodule update --init --recursive
mkdir js_build
cd js_build
-cmake ../ -DCMAKE_TOOLCHAIN_FILE=$(realpath $(which emcc))/cmake/Modules/Platform/Emscripten.cmake
+cmake ../ -DCMAKE_TOOLCHAIN_FILE=$(dirname $(realpath $(which emcc)))/cmake/Modules/Platform/Emscripten.cmake
cmake --build . --
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 95bd99aa3..2afe56df0 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -7,7 +7,7 @@ include(FetchContent)
if (DEFINED ENV{RELIC_MAIN})
set(RELIC_GIT_TAG "origin/main")
else ()
- set(RELIC_GIT_TAG "1885ae3b681c423c72b65ce1fe70910142cf941c")
+ set(RELIC_GIT_TAG "bf37129789c7897f4144fe2f15d0bd2ef8091807")
endif ()
message(STATUS "Relic will be built from: ${RELIC_GIT_TAG}")
diff --git a/src/elements.cpp b/src/elements.cpp
index 39c0ff3a4..2657118cc 100644
--- a/src/elements.cpp
+++ b/src/elements.cpp
@@ -32,17 +32,11 @@ G1Element G1Element::FromBytes(const Bytes& bytes)
buffer[0] = 0x00;
buffer[1] &= 0x1f; // erase 3 msbs from given input
+ bool fZerosOnly = Util::HasOnlyZeros(Bytes(buffer, G1Element::SIZE + 1));
if ((bytes[0] & 0xc0) == 0xc0) { // representing infinity
// enforce that infinity must be 0xc0000..00
- if (bytes[0] != 0xc0) {
- throw std::invalid_argument(
- "Given G1 infinity element must be canonical");
- }
- for (int i = 1; i < G1Element::SIZE; ++i) {
- if (bytes[i] != 0x00) {
- throw std::invalid_argument(
- "Given G1 infinity element must be canonical");
- }
+ if (bytes[0] != 0xc0 || !fZerosOnly) {
+ throw std::invalid_argument("Given G1 infinity element must be canonical");
}
return ele;
} else {
@@ -51,6 +45,10 @@ G1Element G1Element::FromBytes(const Bytes& bytes)
"Given G1 non-infinity element must start with 0b10");
}
+ if (fZerosOnly) {
+ throw std::invalid_argument("G1 non-infinity element can't have only zeros");
+ }
+
if (bytes[0] & 0x20) { // sign bit
buffer[0] = 0x03;
} else {
@@ -58,6 +56,7 @@ G1Element G1Element::FromBytes(const Bytes& bytes)
}
}
g1_read_bin(ele.p, buffer, G1Element::SIZE + 1);
+ BLS::CheckRelicErrors();
ele.CheckValid();
return ele;
}
@@ -215,24 +214,24 @@ G2Element G2Element::FromBytes(const Bytes& bytes)
throw std::invalid_argument(
"Given G2 element must always have 48th byte start with 0b000");
}
+ bool fZerosOnly = Util::HasOnlyZeros(Bytes(buffer, G2Element::SIZE + 1));
if (((bytes[0] & 0xc0) == 0xc0)) { // infinity
// enforce that infinity must be 0xc0000..00
- if (bytes[0] != 0xc0) {
+ if (bytes[0] != 0xc0 || !fZerosOnly) {
throw std::invalid_argument(
"Given G2 infinity element must be canonical");
}
- for (int i = 1; i < G2Element::SIZE; ++i) {
- if (bytes[i] != 0x00) {
- throw std::invalid_argument(
- "Given G2 infinity element must be canonical");
- }
- }
return ele;
} else {
if (((bytes[0] & 0xc0) != 0x80)) {
throw std::invalid_argument(
"G2 non-inf element must have 0th byte start with 0b10");
}
+
+ if (fZerosOnly) {
+ throw std::invalid_argument("G2 non-infinity element can't have only zeros");
+ }
+
if (bytes[0] & 0x20) {
buffer[0] = 0x03;
} else {
@@ -241,6 +240,7 @@ G2Element G2Element::FromBytes(const Bytes& bytes)
}
g2_read_bin(ele.q, buffer, G2Element::SIZE + 1);
+ BLS::CheckRelicErrors();
ele.CheckValid();
return ele;
}
diff --git a/src/schemes.cpp b/src/schemes.cpp
index fe7d37f2e..5948fd24c 100644
--- a/src/schemes.cpp
+++ b/src/schemes.cpp
@@ -533,7 +533,7 @@ bool AugSchemeMPL::AggregateVerify(const vector& pubkeys,
}
vector> augMessages(nPubKeys);
- for (int i = 0; i < nPubKeys; ++i) {
+ for (size_t i = 0; i < nPubKeys; ++i) {
vector& aug = augMessages[i];
vector&& pubkey = pubkeys[i].Serialize();
aug.reserve(pubkey.size() + messages[i].size());
diff --git a/src/test.cpp b/src/test.cpp
index 8c62c5ba9..f2a671fbf 100644
--- a/src/test.cpp
+++ b/src/test.cpp
@@ -29,7 +29,7 @@ using std::vector;
using namespace bls;
-void TestHKDF(string ikm_hex, string salt_hex, string info_hex, string prk_expected_hex, string okm_expected_hex, int L) {
+void TestHKDF(string ikm_hex, string salt_hex, string info_hex, string prk_expected_hex, string okm_expected_hex, size_t L) {
vector ikm = Util::HexToBytes(ikm_hex);
vector salt = Util::HexToBytes(salt_hex);
vector info = Util::HexToBytes(info_hex);
@@ -471,9 +471,13 @@ TEST_CASE("Error handling")
{
vector buf(G1Element::SIZE, 0);
- for (int i = 0; i < 10; i++) {
+ for (int i = 0; i < 0xFF; i++) {
buf[0] = (uint8_t)i;
- REQUIRE_THROWS(G1Element::FromByteVector(buf));
+ if (i == 0xc0) { // Infinity prefix shouldn't throw here as we have only zero values
+ REQUIRE_NOTHROW(G1Element::FromByteVector(buf));
+ } else {
+ REQUIRE_THROWS(G1Element::FromByteVector(buf));
+ }
}
}
@@ -481,10 +485,17 @@ TEST_CASE("Error handling")
{
vector buf(G2Element::SIZE, 0);
- for (int i = 0; i < 10; i++) {
+ for (int i = 0; i < 0xFF; i++) {
buf[0] = (uint8_t)i;
- REQUIRE_THROWS(G2Element::FromByteVector(buf));
+ if (i == 0xc0) { // Infinity prefix shouldn't throw here as we have only zero values
+ REQUIRE_NOTHROW(G2Element::FromByteVector(buf));
+ } else {
+ REQUIRE_THROWS(G2Element::FromByteVector(buf));
+ }
}
+ // Trigger "G2 element must always have 48th byte start with 0b000" error case
+ buf[48] = 0xFF;
+ REQUIRE_THROWS(G2Element::FromByteVector(buf));
}
SECTION("Error handling should be thread safe")
@@ -630,7 +641,6 @@ TEST_CASE("Signature tests")
SECTION("Should not verify aggregate with same message under BasicScheme")
{
vector message = {100, 2, 254, 88, 90, 45, 23};
- uint8_t hash[BLS::MESSAGE_HASH_LEN];
vector seed(32, 0x50);
vector seed2(32, 0x70);
@@ -651,7 +661,6 @@ TEST_CASE("Signature tests")
SECTION("Should verify aggregate with same message under AugScheme/PopScheme")
{
vector message = {100, 2, 254, 88, 90, 45, 23};
- uint8_t hash[BLS::MESSAGE_HASH_LEN];
vector seed(32, 0x50);
vector seed2(32, 0x70);
@@ -1313,7 +1322,7 @@ TEST_CASE("Threshold Signatures") {
// First create the participants and their secrets
std::vector participants;
- for (int i=0; i < n ; i++) {
+ for (size_t i=0; i < n ; i++) {
Participant participant;
participant.id = getRandomSeed();
participant.sk = randPrivKey();
@@ -1322,7 +1331,7 @@ TEST_CASE("Threshold Signatures") {
// Create the vectors' coefficients
participant.sks.emplace_back(participant.sk);
participant.pks.emplace_back(participant.pk);
- for (int j = 0; j < (m-1); j++) {
+ for (size_t j = 0; j < (m-1); j++) {
auto sk = randPrivKey();
participant.sks.emplace_back(sk);
participant.pks.emplace_back(sk.GetG1Element());
@@ -1332,7 +1341,7 @@ TEST_CASE("Threshold Signatures") {
// Second, create shares for every other participant
for (Participant& participant : participants) {
- for (int j=0; j < n; j++) {
+ for (size_t j=0; j < n; j++) {
RawData id = participants[j].id;
participant.sksShares.emplace(id, bls::Threshold::PrivateKeyShare(participant.sks, Bytes(id)));
participant.pksShares.emplace(id, bls::Threshold::PublicKeyShare(participant.pks, Bytes(id)));
@@ -1342,7 +1351,7 @@ TEST_CASE("Threshold Signatures") {
// Third, send shares and verification vectors
for (Participant& participant : participants) {
- for (int j=0; j < n; j++) {
+ for (size_t j=0; j < n; j++) {
auto& recipient = participants[j];
RawData destId = recipient.id;
// S(x) evaluated in participant1.id.
@@ -1381,8 +1390,8 @@ TEST_CASE("Threshold Signatures") {
// Let's aggregate all the verification vectors to obtain Pa():
std::vector finalVerifVector(participants[0].pks);
- for (int j = 1; j < participants.size(); j++) {
- for (int i = 0; i < finalVerifVector.size(); i++) {
+ for (size_t j = 1; j < participants.size(); j++) {
+ for (size_t i = 0; i < finalVerifVector.size(); i++) {
finalVerifVector[i] += participants[j].pks.at(i);
}
}
@@ -1408,7 +1417,7 @@ TEST_CASE("Threshold Signatures") {
// Let's aggregate all the SIG(0) values to obtain SIGa(0)
// This will be checked for equality against the recovered threshold signature
G2Element finalSIG = participants[0].sig;
- for (int j = 1; j < participants.size(); j++) {
+ for (size_t j = 1; j < participants.size(); j++) {
finalSIG += participants[j].sig;
}
diff --git a/src/util.hpp b/src/util.hpp
index 16f26b432..43ad6ae6b 100644
--- a/src/util.hpp
+++ b/src/util.hpp
@@ -15,6 +15,7 @@
#ifndef SRC_BLSUTIL_HPP_
#define SRC_BLSUTIL_HPP_
+#include
#include
#include
#include
@@ -138,6 +139,10 @@ class Util {
return sum;
}
+ static bool HasOnlyZeros(const Bytes& bytes) {
+ return std::all_of(bytes.begin(), bytes.end(), [](uint8_t byte){ return byte == 0x00; });
+ }
+
private:
friend class BLS;
static SecureAllocCallback secureAllocCallback;