diff --git a/.gitignore b/.gitignore index 4de281a3..551b03ae 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,11 @@ include/hotstuff/config.h /test/test_secp256k1 /test/test_concurrent_queue core + +.idea/ + +hotstuff-keygen_bls + +hotstuff.cbp + +log* diff --git a/CMakeLists.txt b/CMakeLists.txt index c6af4bd5..245e03a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,16 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/salticidae/cmake add_subdirectory(salticidae) include_directories(salticidae/include) +INCLUDE_DIRECTORIES(bls/src) +INCLUDE_DIRECTORIES(bls/build/contrib/relic/include) +INCLUDE_DIRECTORIES(bls/contrib/relic/include) + +add_library( blstmp STATIC IMPORTED ) +set_target_properties( blstmp PROPERTIES IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/bls/build/src/libblstmp.a ) + +add_library( relic_s STATIC IMPORTED ) +set_target_properties( relic_s PROPERTIES IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/bls/build/contrib/relic/lib/librelic_s.a ) + find_package(OpenSSL REQUIRED) find_package(Threads REQUIRED) @@ -91,11 +101,16 @@ endif() # build tools add_executable(hotstuff-keygen src/hotstuff_keygen.cpp) -target_link_libraries(hotstuff-keygen hotstuff_static) +target_link_libraries(hotstuff-keygen hotstuff_static blstmp relic_s) + +add_executable(hotstuff-keygen_bls + src/hotstuff_keygen_bls.cpp) +target_link_libraries(hotstuff-keygen_bls hotstuff_static blstmp relic_s) + add_executable(hotstuff-tls-keygen src/hotstuff_tls_keygen.cpp) -target_link_libraries(hotstuff-tls-keygen hotstuff_static) +target_link_libraries(hotstuff-tls-keygen hotstuff_static blstmp relic_s) find_package(Doxygen) if (DOXYGEN_FOUND) diff --git a/bls/build/contrib/relic/include/relic_conf.h b/bls/build/contrib/relic/include/relic_conf.h new file mode 100644 index 00000000..9930e104 --- /dev/null +++ b/bls/build/contrib/relic/include/relic_conf.h @@ -0,0 +1,722 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 + * + * Project configuration. + * + * @version $Id: relic_conf.h.in 45 2009-07-04 23:45:48Z dfaranha $ + * @ingroup relic + */ + +#ifndef RLC_CONF_H +#define RLC_CONF_H + +/** Project version. */ +#define RLC_VERSION "0.5.0" + +/** Debugging support. */ +/* #undef DEBUG */ +/** Profiling support. */ +/* #undef PROFL */ +/** Error handling support. */ +/* #undef CHECK */ +/** Verbose error messages. */ +/* #undef VERBS */ +/** Build with overhead estimation. */ +/* #undef OVERH */ +/** Build documentation. */ +#define DOCUM +/** Build only the selected algorithms. */ +/* #undef STRIP */ +/** Build with printing disabled. */ +#define QUIET +/** Build with colored output. */ +#define COLOR +/** Build with big-endian support. */ +/* #undef BIGED */ +/** Build shared library. */ +/* #undef SHLIB */ +/** Build static library. */ +#define STLIB + +/** Number of times each test is ran. */ +#define TESTS 0 +/** Number of times each benchmark is ran. */ +#define BENCH 0 + +/** Number of available cores. */ +#define CORES 1 + +/** Atmel AVR ATMega128 8-bit architecture. */ +#define AVR 1 +/** MSP430 16-bit architecture. */ +#define MSP 2 +/** ARM 32-bit architecture. */ +#define ARM 3 +/** Intel x86-compatible 32-bit architecture. */ +#define X86 4 +/** AMD64-compatible 64-bit architecture. */ +#define X64 5 +/** Architecture. */ +#define ARCH X64 + +/** Size of word in this architecture. */ +#define WSIZE 64 + +/** Byte boundary to align digit vectors. */ +#define ALIGN 1 + +/** Build multiple precision integer module. */ +#define WITH_BN +/** Build prime field module. */ +#define WITH_FP +/** Build prime field extension module. */ +#define WITH_FPX +/** Build binary field module. */ +#define WITH_FB +/** Build prime elliptic curve module. */ +#define WITH_EP +/** Build prime field extension elliptic curve module. */ +#define WITH_EPX +/** Build binary elliptic curve module. */ +#define WITH_EB +/** Build elliptic Edwards curve module. */ +#define WITH_ED +/** Build elliptic curve cryptography module. */ +#define WITH_EC +/** Build pairings over prime curves module. */ +#define WITH_PP +/** Build pairing-based cryptography module. */ +#define WITH_PC +/** Build block ciphers. */ +#define WITH_BC +/** Build hash functions. */ +#define WITH_MD +/** Build cryptographic protocols. */ +#define WITH_CP + +/** Easy C-only backend. */ +#define EASY 1 +/** GMP backend. */ +#define GMP 2 +/** Arithmetic backend. */ +#define ARITH EASY + +/** Required precision in bits. */ +#define BN_PRECI 1024 +/** A multiple precision integer can store w words. */ +#define SINGLE 0 +/** A multiple precision integer can store the result of an addition. */ +#define CARRY 1 +/** A multiple precision integer can store the result of a multiplication. */ +#define DOUBLE 2 +/** Effective size of a multiple precision integer. */ +#define BN_MAGNI DOUBLE +/** Number of Karatsuba steps. */ +#define BN_KARAT 0 + +/** Schoolbook multiplication. */ +#define BASIC 1 +/** Comba multiplication. */ +#define COMBA 2 +/** Chosen multiple precision multiplication method. */ +#define BN_MUL COMBA + +/** Schoolbook squaring. */ +#define BASIC 1 +/** Comba squaring. */ +#define COMBA 2 +/** Reuse multiplication for squaring. */ +#define MULTP 4 +/** Chosen multiple precision multiplication method. */ +#define BN_SQR COMBA + +/** Division modular reduction. */ +#define BASIC 1 +/** Barrett modular reduction. */ +#define BARRT 2 +/** Montgomery modular reduction. */ +#define MONTY 3 +/** Pseudo-Mersenne modular reduction. */ +#define PMERS 4 +/** Chosen multiple precision modular reduction method. */ +#define BN_MOD MONTY + +/** Binary modular exponentiation. */ +#define BASIC 1 +/** Sliding window modular exponentiation. */ +#define SLIDE 2 +/** Montgomery powering ladder. */ +#define MONTY 3 +/** Chosen multiple precision modular exponentiation method. */ +#define BN_MXP SLIDE + +/** Basic Euclidean GCD Algorithm. */ +#define BASIC 1 +/** Lehmer's fast GCD Algorithm. */ +#define LEHME 2 +/** Stein's binary GCD Algorithm. */ +#define STEIN 3 +/** Chosen multiple precision greatest common divisor method. */ +#define BN_GCD BASIC + +/** Basic prime generation. */ +#define BASIC 1 +/** Safe prime generation. */ +#define SAFEP 2 +/** Strong prime generation. */ +#define STRON 3 +/** Chosen prime generation algorithm. */ +#define BN_GEN BASIC + +/** Multiple precision arithmetic method */ +#define BN_METHD "COMBA;COMBA;MONTY;SLIDE;BASIC;BASIC" + +/** Prime field size in bits. */ +#define FP_PRIME 381 +/** Number of Karatsuba steps. */ +#define FP_KARAT 0 +/** Prefer Pseudo-Mersenne primes over random primes. */ +/* #undef FP_PMERS */ +/** Use -1 as quadratic non-residue. */ +#define FP_QNRES +/** Width of window processing for exponentiation methods. */ +#define FP_WIDTH 4 + +/** Schoolbook addition. */ +#define BASIC 1 +/** Integrated modular addtion. */ +#define INTEG 3 +/** Chosen prime field multiplication method. */ +#define FP_ADD INTEG + +/** Schoolbook multiplication. */ +#define BASIC 1 +/** Comba multiplication. */ +#define COMBA 2 +/** Integrated modular multiplication. */ +#define INTEG 3 +/** Chosen prime field multiplication method. */ +#define FP_MUL INTEG + +/** Schoolbook squaring. */ +#define BASIC 1 +/** Comba squaring. */ +#define COMBA 2 +/** Integrated modular squaring. */ +#define INTEG 3 +/** Reuse multiplication for squaring. */ +#define MULTP 4 +/** Chosen prime field multiplication method. */ +#define FP_SQR INTEG + +/** Division-based reduction. */ +#define BASIC 1 +/** Fast reduction modulo special form prime. */ +#define QUICK 2 +/** Montgomery modular reduction. */ +#define MONTY 3 +/** Chosen prime field reduction method. */ +#define FP_RDC MONTY + +/** Inversion by Fermat's Little Theorem. */ +#define BASIC 1 +/** Binary inversion. */ +#define BINAR 2 +/** Integrated modular multiplication. */ +#define MONTY 3 +/** Extended Euclidean algorithm. */ +#define EXGCD 4 +/** Constant-time inversion by Bernstein-Yang division steps. */ +#define DIVST 5 +/** Use implementation provided by the lower layer. */ +#define LOWER 8 +/** Chosen prime field inversion method. */ +#define FP_INV LOWER + +/** Binary modular exponentiation. */ +#define BASIC 1 +/** Sliding window modular exponentiation. */ +#define SLIDE 2 +/** Constant-time Montgomery powering ladder. */ +#define MONTY 3 +/** Chosen multiple precision modular exponentiation method. */ +#define FP_EXP SLIDE + +/** Prime field arithmetic method */ +#define FP_METHD "INTEG;INTEG;INTEG;MONTY;LOWER;SLIDE" + +/** Basic quadratic extension field arithmetic. */ +#define BASIC 1 +/** Integrated extension field arithmetic. */ +#define INTEG 3 +/* Chosen extension field arithmetic method. */ +#define FPX_QDR INTEG + +/** Basic cubic extension field arithmetic. */ +#define BASIC 1 +/** Integrated extension field arithmetic. */ +#define INTEG 3 +/* Chosen extension field arithmetic method. */ +#define FPX_CBC INTEG + +/** Basic quadratic extension field arithmetic. */ +#define BASIC 1 +/** Lazy-reduced extension field arithmetic. */ +#define LAZYR 2 +/* Chosen extension field arithmetic method. */ +#define FPX_RDC LAZYR + +/** Prime extension field arithmetic method */ +#define FPX_METHD "INTEG;INTEG;LAZYR" + +/** Irreducible polynomial size in bits. */ +#define FB_POLYN 283 +/** Number of Karatsuba steps. */ +#define FB_KARAT 0 +/** Prefer trinomials over pentanomials. */ +#define FB_TRINO +/** Prefer square-root friendly polynomials. */ +/* #undef FB_SQRTF */ +/** Precompute multiplication table for sqrt(z). */ +#define FB_PRECO +/** Width of window processing for exponentiation methods. */ +#define FB_WIDTH 4 + +/** Shift-and-add multiplication. */ +#define BASIC 1 +/** Lopez-Dahab multiplication. */ +#define LODAH 2 +/** Integrated modular multiplication. */ +#define INTEG 3 +/** Chosen binary field multiplication method. */ +#define FB_MUL LODAH + +/** Basic squaring. */ +#define BASIC 1 +/** Table-based squaring. */ +#define QUICK 2 +/** Integrated modular squaring. */ +#define INTEG 3 +/** Chosen binary field squaring method. */ +#define FB_SQR QUICK + +/** Shift-and-add modular reduction. */ +#define BASIC 1 +/** Fast reduction modulo a trinomial or pentanomial. */ +#define QUICK 2 +/** Chosen binary field modular reduction method. */ +#define FB_RDC QUICK + +/** Square root by repeated squaring. */ +#define BASIC 1 +/** Fast square root extraction. */ +#define QUICK 2 +/** Chosen binary field modular reduction method. */ +#define FB_SRT QUICK + +/** Trace by repeated squaring. */ +#define BASIC 1 +/** Fast trace computation. */ +#define QUICK 2 +/** Chosen trace computation method. */ +#define FB_TRC QUICK + +/** Solve by half-trace computation. */ +#define BASIC 1 +/** Solve with precomputed half-traces. */ +#define QUICK 2 +/** Chosen method to solve a quadratic equation. */ +#define FB_SLV QUICK + +/** Inversion by Fermat's Little Theorem. */ +#define BASIC 1 +/** Binary inversion. */ +#define BINAR 2 +/** Almost inverse algorithm. */ +#define ALMOS 3 +/** Extended Euclidean algorithm. */ +#define EXGCD 4 +/** Itoh-Tsuji inversion. */ +#define ITOHT 5 +/** Hardware-friendly inversion by Brunner-Curiger-Hofstetter.*/ +#define BRUCH 6 +/** Constant-time version of almost inverse. */ +#define CTAIA 7 +/** Use implementation provided by the lower layer. */ +#define LOWER 8 +/** Chosen binary field inversion method. */ +#define FB_INV EXGCD + +/** Binary modular exponentiation. */ +#define BASIC 1 +/** Sliding window modular exponentiation. */ +#define SLIDE 2 +/** Constant-time Montgomery powering ladder. */ +#define MONTY 3 +/** Chosen multiple precision modular exponentiation method. */ +#define FB_EXP SLIDE + +/** Iterated squaring/square-root by consecutive squaring/square-root. */ +#define BASIC 1 +/** Iterated squaring/square-root by table-based method. */ +#define QUICK 2 +/** Chosen method to solve a quadratic equation. */ +#define FB_ITR QUICK + +/** Binary field arithmetic method */ +#define FB_METHD "LODAH;QUICK;QUICK;QUICK;QUICK;QUICK;EXGCD;SLIDE;QUICK" + +/** Support for ordinary curves. */ +/* #undef EP_PLAIN */ +/** Support for supersingular curves. */ +/* #undef EP_SUPER */ +/** Support for prime curves with efficient endormorphisms. */ +#define EP_ENDOM +/** Use mixed coordinates. */ +#define EP_MIXED +/** Build precomputation table for generator. */ +#define EP_PRECO +/** Enable isogeny map for SSWU map-to-curve. */ +#define EP_CTMAP +/** Width of precomputation table for fixed point methods. */ +#define EP_DEPTH 4 +/** Width of window processing for unknown point methods. */ +#define EP_WIDTH 4 + +/** Affine coordinates. */ +#define BASIC 1 +/** Projective coordinates. */ +#define PROJC 2 +/** Chosen prime elliptic curve coordinate method. */ +#define EP_ADD PROJC + +/** Binary point multiplication. */ +#define BASIC 1 +/** Sliding window. */ +#define SLIDE 2 +/** Montgomery powering ladder. */ +#define MONTY 3 +/** Left-to-right Width-w NAF. */ +#define LWNAF 4 +/** Left-to-right Width-w NAF. */ +#define LWREG 5 +/** Chosen prime elliptic curve point multiplication method. */ +#define EP_MUL LWNAF + +/** Binary point multiplication. */ +#define BASIC 1 +/** Single-table comb method. */ +#define COMBS 2 +/** Double-table comb method. */ +#define COMBD 3 +/** Left-to-right Width-w NAF. */ +#define LWNAF 4 +/** Chosen prime elliptic curve point multiplication method. */ +#define EP_FIX COMBS + +/** Basic simultaneouns point multiplication. */ +#define BASIC 1 +/** Shamir's trick. */ +#define TRICK 2 +/** Interleaving of w-(T)NAFs. */ +#define INTER 3 +/** Joint sparse form. */ +#define JOINT 4 +/** Chosen prime elliptic curve simulteanous point multiplication method. */ +#define EP_SIM INTER + +/** Prime elliptic curve arithmetic method. */ +#define EP_METHD "PROJC;LWNAF;COMBS;INTER" + +/** Support for ordinary curves without endormorphisms. */ +#define EB_PLAIN +/** Support for Koblitz anomalous binary curves. */ +#define EB_KBLTZ +/** Use mixed coordinates. */ +#define EB_MIXED +/** Build precomputation table for generator. */ +#define EB_PRECO +/** Width of precomputation table for fixed point methods. */ +#define EB_DEPTH 4 +/** Width of window processing for unknown point methods. */ +#define EB_WIDTH 4 + +/** Binary elliptic curve arithmetic method. */ +#define EB_METHD "PROJC;LWNAF;COMBS;INTER" + +/** Affine coordinates. */ +#define BASIC 1 +/** López-Dahab Projective coordinates. */ +#define PROJC 2 +/** Chosen binary elliptic curve coordinate method. */ +#define EB_ADD PROJC + +/** Binary point multiplication. */ +#define BASIC 1 +/** López-Dahab point multiplication. */ +#define LODAH 2 +/** Halving. */ +#define HALVE 3 +/** Left-to-right width-w (T)NAF. */ +#define LWNAF 4 +/** Right-to-left width-w (T)NAF. */ +#define RWNAF 5 +/** Chosen binary elliptic curve point multiplication method. */ +#define EB_MUL LWNAF + +/** Binary point multiplication. */ +#define BASIC 1 +/** Single-table comb method. */ +#define COMBS 2 +/** Double-table comb method. */ +#define COMBD 3 +/** Left-to-right Width-w NAF. */ +#define LWNAF 4 +/** Chosen binary elliptic curve point multiplication method. */ +#define EB_FIX COMBS + +/** Basic simultaneouns point multiplication. */ +#define BASIC 1 +/** Shamir's trick. */ +#define TRICK 2 +/** Interleaving of w-(T)NAFs. */ +#define INTER 3 +/** Joint sparse form. */ +#define JOINT 4 +/** Chosen binary elliptic curve simulteanous point multiplication method. */ +#define EB_SIM INTER + +/** Build precomputation table for generator. */ +#define ED_PRECO +/** Width of precomputation table for fixed point methods. */ +#define ED_DEPTH 4 +/** Width of window processing for unknown point methods. */ +#define ED_WIDTH 4 + +/** Edwards elliptic curve arithmetic method. */ +#define ED_METHD "PROJC;LWNAF;COMBS;INTER" + +/** Affine coordinates. */ +#define BASIC 1 +/** Simple projective twisted Edwards coordinates */ +#define PROJC 2 +/** Extended projective twisted Edwards coordinates */ +#define EXTND 3 +/** Chosen binary elliptic curve coordinate method. */ +#define ED_ADD PROJC + +/** Binary point multiplication. */ +#define BASIC 1 +/** Sliding window. */ +#define SLIDE 2 +/** Montgomery powering ladder. */ +#define MONTY 3 +/** Left-to-right Width-w NAF. */ +#define LWNAF 4 +/** Left-to-right Width-w NAF. */ +#define LWREG 5 +/** Chosen prime elliptic twisted Edwards curve point multiplication method. */ +#define ED_MUL LWNAF + +/** Binary point multiplication. */ +#define BASIC 1 +/** Single-table comb method. */ +#define COMBS 2 +/** Double-table comb method. */ +#define COMBD 3 +/** Left-to-right Width-w NAF. */ +#define LWNAF 4 +/** Chosen prime elliptic twisted Edwards curve point multiplication method. */ +#define ED_FIX COMBS + +/** Basic simultaneouns point multiplication. */ +#define BASIC 1 +/** Shamir's trick. */ +#define TRICK 2 +/** Interleaving of w-(T)NAFs. */ +#define INTER 3 +/** Joint sparse form. */ +#define JOINT 4 +/** Chosen prime elliptic curve simulteanous point multiplication method. */ +#define ED_SIM INTER + +/** Prime curves. */ +#define PRIME 1 +/** Binary curves. */ +#define CHAR2 2 +/** Edwards curves */ +#define EDDIE 3 +/** Chosen elliptic curve type. */ +#define EC_CUR PRIME + +/** Chosen elliptic curve cryptography method. */ +#define EC_METHD "PRIME" +/** Prefer curves with efficient endomorphisms. */ +/* #undef EC_ENDOM */ + +/** Basic quadratic extension field arithmetic. */ +#define BASIC 1 +/** Lazy-reduced extension field arithmetic. */ +#define LAZYR 2 +/* Chosen extension field arithmetic method. */ +#define PP_EXT LAZYR + +/** Bilinear pairing method. */ +#define PP_METHD "LAZYR;OATEP" + +/** Tate pairing. */ +#define TATEP 1 +/** Weil pairing. */ +#define WEILP 2 +/** Optimal ate pairing. */ +#define OATEP 3 +/** Chosen pairing method over prime elliptic curves. */ +#define PP_MAP OATEP + +/** SHA-224 hash function. */ +#define SH224 2 +/** SHA-256 hash function. */ +#define SH256 3 +/** SHA-384 hash function. */ +#define SH384 4 +/** SHA-512 hash function. */ +#define SH512 5 +/** BLAKE2s-160 hash function. */ +#define B2S160 6 +/** BLAKE2s-256 hash function. */ +#define B2S256 7 +/** Chosen hash function. */ +#define MD_MAP SH256 + +/** Choice of hash function. */ +#define MD_METHD "SH256" + +/** RSA without padding. */ +#define BASIC 1 +/** RSA PKCS#1 v1.5 padding. */ +#define PKCS1 2 +/** RSA PKCS#1 v2.1 padding. */ +#define PKCS2 3 +/** Chosen RSA padding method. */ +#define CP_RSAPD PKCS1 + +/** Slow RSA decryption/signature. */ +#define BASIC 1 +/** Fast RSA decryption/signature with CRT. */ +#define QUICK 2 +/** Chosen RSA method. */ +#define CP_RSA QUICK + +/** Standard ECDSA. */ +#define BASIC 1 +/** ECDSA with fast verification. */ +#define QUICK 2 +/** Chosen ECDSA method. */ +#define CP_ECDSA + +/** Automatic memory allocation. */ +#define AUTO 1 +/** Dynamic memory allocation. */ +#define DYNAMIC 2 +/** Stack memory allocation. */ +#define STACK 3 +/** Chosen memory allocation policy. */ +#define ALLOC AUTO + +/** NIST HASH-DRBG generator. */ +#define HASHD 1 +/** Intel RdRand instruction. */ +#define RDRND 2 +/** Operating system underlying generator. */ +#define UDEV 3 +/** Override library generator with the callback. */ +#define CALL 4 +/** Chosen random generator. */ +#define RAND HASHD + +/** Standard C library generator. */ +#define LIBC 1 +/** Intel RdRand instruction. */ +#define RDRND 2 +/** Device node generator. */ +#define UDEV 3 +/** Use Windows' CryptGenRandom. */ +#define WCGR 4 +/** Chosen random generator seeder. */ +#define SEED UDEV + +/** GNU/Linux operating system. */ +#define LINUX 1 +/** FreeBSD operating system. */ +#define FREEBSD 2 +/** Windows operating system. */ +#define MACOSX 3 +/** Windows operating system. */ +#define WINDOWS 4 +/** Android operating system. */ +#define DROID 5 +/* Arduino platform. */ +#define DUINO 6 +/** Detected operation system. */ +#define OPSYS LINUX + +/** OpenMP multithreading support. */ +#define OPENMP 1 +/** POSIX multithreading support. */ +#define PTHREAD 2 +/** Chosen multithreading API. */ +#define MULTI PTHREAD + +/** Per-process high-resolution timer. */ +#define HREAL 1 +/** Per-process high-resolution timer. */ +#define HPROC 2 +/** Per-thread high-resolution timer. */ +#define HTHRD 3 +/** POSIX-compatible timer. */ +#define POSIX 4 +/** ANSI-compatible timer. */ +#define ANSI 5 +/** Cycle-counting timer. */ +#define CYCLE 6 +/** Chosen timer. */ +#define TIMER CYCLE + +/** Prefix to identity this build of the library. */ +/* #undef LABEL */ + +#ifndef ASM + +#include "relic_label.h" + +/** + * Prints the project options selected at build time. + */ +void conf_print(void); + +#endif /* ASM */ + +#endif /* !RLC_CONF_H */ diff --git a/bls/build/contrib/relic/lib/librelic_s.a b/bls/build/contrib/relic/lib/librelic_s.a new file mode 100644 index 00000000..f41c2d2b Binary files /dev/null and b/bls/build/contrib/relic/lib/librelic_s.a differ diff --git a/bls/build/libbls.a b/bls/build/libbls.a new file mode 100644 index 00000000..bb1d83fb Binary files /dev/null and b/bls/build/libbls.a differ diff --git a/bls/build/src/libbls.a b/bls/build/src/libbls.a new file mode 100644 index 00000000..f49fee19 Binary files /dev/null and b/bls/build/src/libbls.a differ diff --git a/bls/build/src/libblstmp.a b/bls/build/src/libblstmp.a new file mode 100644 index 00000000..12b7349d Binary files /dev/null and b/bls/build/src/libblstmp.a differ diff --git a/bls/contrib/catch/catch.hpp b/bls/contrib/catch/catch.hpp new file mode 100644 index 00000000..aacc5601 --- /dev/null +++ b/bls/contrib/catch/catch.hpp @@ -0,0 +1,13286 @@ +/* + * Catch v2.2.3 + * Generated: 2018-06-06 23:11:57.601416 + * ---------------------------------------------------------- + * This file has been merged from multiple headers. Please don't edit it directly + * Copyright (c) 2018 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +// start catch.hpp + + +#define CATCH_VERSION_MAJOR 2 +#define CATCH_VERSION_MINOR 2 +#define CATCH_VERSION_PATCH 3 + +#ifdef __clang__ +# pragma clang system_header +#elif defined __GNUC__ +# pragma GCC system_header +#endif + +// start catch_suppress_warnings.h + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(push) +# pragma warning(disable: 161 1682) +# else // __ICC +# pragma clang diagnostic ignored "-Wunused-variable" +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wswitch-enum" +# pragma clang diagnostic ignored "-Wcovered-switch-default" +# endif +#elif defined __GNUC__ +# pragma GCC diagnostic ignored "-Wparentheses" +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunused-variable" +# pragma GCC diagnostic ignored "-Wpadded" +#endif +// end catch_suppress_warnings.h +#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) +# define CATCH_IMPL +# define CATCH_CONFIG_ALL_PARTS +#endif + +// In the impl file, we want to have access to all parts of the headers +// Can also be used to sanely support PCHs +#if defined(CATCH_CONFIG_ALL_PARTS) +# define CATCH_CONFIG_EXTERNAL_INTERFACES +# if defined(CATCH_CONFIG_DISABLE_MATCHERS) +# undef CATCH_CONFIG_DISABLE_MATCHERS +# endif +# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER +#endif + +#if !defined(CATCH_CONFIG_IMPL_ONLY) +// start catch_platform.h + +#ifdef __APPLE__ +# include +# if TARGET_OS_OSX == 1 +# define CATCH_PLATFORM_MAC +# elif TARGET_OS_IPHONE == 1 +# define CATCH_PLATFORM_IPHONE +# endif + +#elif defined(linux) || defined(__linux) || defined(__linux__) +# define CATCH_PLATFORM_LINUX + +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) +# define CATCH_PLATFORM_WINDOWS +#endif + +// end catch_platform.h + +#ifdef CATCH_IMPL +# ifndef CLARA_CONFIG_MAIN +# define CLARA_CONFIG_MAIN_NOT_DEFINED +# define CLARA_CONFIG_MAIN +# endif +#endif + +// start catch_user_interfaces.h + +namespace Catch { + unsigned int rngSeed(); +} + +// end catch_user_interfaces.h +// start catch_tag_alias_autoregistrar.h + +// start catch_common.h + +// start catch_compiler_capabilities.h + +// Detect a number of compiler features - by compiler +// The following features are defined: +// +// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? +// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? +// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? +// **************** +// Note to maintainers: if new toggles are added please document them +// in configuration.md, too +// **************** + +// In general each macro has a _NO_ form +// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +#ifdef __cplusplus + +# if __cplusplus >= 201402L +# define CATCH_CPP14_OR_GREATER +# endif + +# if __cplusplus >= 201703L +# define CATCH_CPP17_OR_GREATER +# endif + +#endif + +#if defined(CATCH_CPP17_OR_GREATER) +# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +#endif + +#ifdef __clang__ + +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + _Pragma( "clang diagnostic push" ) \ + _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ + _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") +# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ + _Pragma( "clang diagnostic pop" ) + +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + _Pragma( "clang diagnostic push" ) \ + _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) +# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ + _Pragma( "clang diagnostic pop" ) + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// Assume that non-Windows platforms support posix signals by default +#if !defined(CATCH_PLATFORM_WINDOWS) + #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS +#endif + +//////////////////////////////////////////////////////////////////////////////// +// We know some environments not to support full POSIX signals +#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) + #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS +#endif + +#ifdef __OS400__ +# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS +# define CATCH_CONFIG_COLOUR_NONE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Android somehow still does not support std::to_string +#if defined(__ANDROID__) +# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Not all Windows environments support SEH properly +#if defined(__MINGW32__) +# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Cygwin +#ifdef __CYGWIN__ + +// Required for some versions of Cygwin to declare gettimeofday +// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin +# define _BSD_SOURCE + +#endif // __CYGWIN__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#ifdef _MSC_VER + +# if _MSC_VER >= 1900 // Visual Studio 2015 or newer +# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +# endif + +// Universal Windows platform does not support SEH +// Or console colours (or console at all...) +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) +# define CATCH_CONFIG_COLOUR_NONE +# else +# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH +# endif + +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// + +// DJGPP +#ifdef __DJGPP__ +# define CATCH_INTERNAL_CONFIG_NO_WCHAR +#endif // __DJGPP__ + +//////////////////////////////////////////////////////////////////////////////// + +// Use of __COUNTER__ is suppressed during code analysis in +// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly +// handled by it. +// Otherwise all supported compilers support COUNTER macro, +// but user still might want to turn it off +#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) + #define CATCH_INTERNAL_CONFIG_COUNTER +#endif + +#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) +# define CATCH_CONFIG_COUNTER +#endif +#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH) +# define CATCH_CONFIG_WINDOWS_SEH +#endif +// This is set by default, because we assume that unix compilers are posix-signal-compatible by default. +#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS) +# define CATCH_CONFIG_POSIX_SIGNALS +#endif +// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions. +#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) +# define CATCH_CONFIG_WCHAR +#endif + +#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) +# define CATCH_CONFIG_CPP11_TO_STRING +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) +# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +#endif + +#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS +# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS +# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS +#endif + +// end catch_compiler_capabilities.h +#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line +#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) +#ifdef CATCH_CONFIG_COUNTER +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) +#else +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) +#endif + +#include +#include +#include + +namespace Catch { + + struct CaseSensitive { enum Choice { + Yes, + No + }; }; + + class NonCopyable { + NonCopyable( NonCopyable const& ) = delete; + NonCopyable( NonCopyable && ) = delete; + NonCopyable& operator = ( NonCopyable const& ) = delete; + NonCopyable& operator = ( NonCopyable && ) = delete; + + protected: + NonCopyable(); + virtual ~NonCopyable(); + }; + + struct SourceLineInfo { + + SourceLineInfo() = delete; + SourceLineInfo( char const* _file, std::size_t _line ) noexcept + : file( _file ), + line( _line ) + {} + + SourceLineInfo( SourceLineInfo const& other ) = default; + SourceLineInfo( SourceLineInfo && ) = default; + SourceLineInfo& operator = ( SourceLineInfo const& ) = default; + SourceLineInfo& operator = ( SourceLineInfo && ) = default; + + bool empty() const noexcept; + bool operator == ( SourceLineInfo const& other ) const noexcept; + bool operator < ( SourceLineInfo const& other ) const noexcept; + + char const* file; + std::size_t line; + }; + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); + + // Use this in variadic streaming macros to allow + // >> +StreamEndStop + // as well as + // >> stuff +StreamEndStop + struct StreamEndStop { + std::string operator+() const; + }; + template + T const& operator + ( T const& value, StreamEndStop ) { + return value; + } +} + +#define CATCH_INTERNAL_LINEINFO \ + ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) + +// end catch_common.h +namespace Catch { + + struct RegistrarForTagAliases { + RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + }; + +} // end namespace Catch + +#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS + +// end catch_tag_alias_autoregistrar.h +// start catch_test_registry.h + +// start catch_interfaces_testcase.h + +#include +#include + +namespace Catch { + + class TestSpec; + + struct ITestInvoker { + virtual void invoke () const = 0; + virtual ~ITestInvoker(); + }; + + using ITestCasePtr = std::shared_ptr; + + class TestCase; + struct IConfig; + + struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector const& getAllTests() const = 0; + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; + }; + + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); + std::vector const& getAllTestCasesSorted( IConfig const& config ); + +} + +// end catch_interfaces_testcase.h +// start catch_stringref.h + +#include +#include +#include + +namespace Catch { + + class StringData; + + /// A non-owning string class (similar to the forthcoming std::string_view) + /// Note that, because a StringRef may be a substring of another string, + /// it may not be null terminated. c_str() must return a null terminated + /// string, however, and so the StringRef will internally take ownership + /// (taking a copy), if necessary. In theory this ownership is not externally + /// visible - but it does mean (substring) StringRefs should not be shared between + /// threads. + class StringRef { + public: + using size_type = std::size_t; + + private: + friend struct StringRefTestAccess; + + char const* m_start; + size_type m_size; + + char* m_data = nullptr; + + void takeOwnership(); + + static constexpr char const* const s_empty = ""; + + public: // construction/ assignment + StringRef() noexcept + : StringRef( s_empty, 0 ) + {} + + StringRef( StringRef const& other ) noexcept + : m_start( other.m_start ), + m_size( other.m_size ) + {} + + StringRef( StringRef&& other ) noexcept + : m_start( other.m_start ), + m_size( other.m_size ), + m_data( other.m_data ) + { + other.m_data = nullptr; + } + + StringRef( char const* rawChars ) noexcept; + + StringRef( char const* rawChars, size_type size ) noexcept + : m_start( rawChars ), + m_size( size ) + {} + + StringRef( std::string const& stdString ) noexcept + : m_start( stdString.c_str() ), + m_size( stdString.size() ) + {} + + ~StringRef() noexcept { + delete[] m_data; + } + + auto operator = ( StringRef const &other ) noexcept -> StringRef& { + delete[] m_data; + m_data = nullptr; + m_start = other.m_start; + m_size = other.m_size; + return *this; + } + + operator std::string() const; + + void swap( StringRef& other ) noexcept; + + public: // operators + auto operator == ( StringRef const& other ) const noexcept -> bool; + auto operator != ( StringRef const& other ) const noexcept -> bool; + + auto operator[] ( size_type index ) const noexcept -> char; + + public: // named queries + auto empty() const noexcept -> bool { + return m_size == 0; + } + auto size() const noexcept -> size_type { + return m_size; + } + + auto numberOfCharacters() const noexcept -> size_type; + auto c_str() const -> char const*; + + public: // substrings and searches + auto substr( size_type start, size_type size ) const noexcept -> StringRef; + + // Returns the current start pointer. + // Note that the pointer can change when if the StringRef is a substring + auto currentData() const noexcept -> char const*; + + private: // ownership queries - may not be consistent between calls + auto isOwned() const noexcept -> bool; + auto isSubstring() const noexcept -> bool; + }; + + auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string; + auto operator + ( StringRef const& lhs, char const* rhs ) -> std::string; + auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string; + + auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; + auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; + + inline auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { + return StringRef( rawChars, size ); + } + +} // namespace Catch + +// end catch_stringref.h +namespace Catch { + +template +class TestInvokerAsMethod : public ITestInvoker { + void (C::*m_testAsMethod)(); +public: + TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {} + + void invoke() const override { + C obj; + (obj.*m_testAsMethod)(); + } +}; + +auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker*; + +template +auto makeTestInvoker( void (C::*testAsMethod)() ) noexcept -> ITestInvoker* { + return new(std::nothrow) TestInvokerAsMethod( testAsMethod ); +} + +struct NameAndTags { + NameAndTags( StringRef const& name_ = StringRef(), StringRef const& tags_ = StringRef() ) noexcept; + StringRef name; + StringRef tags; +}; + +struct AutoReg : NonCopyable { + AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept; + ~AutoReg(); +}; + +} // end namespace Catch + +#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) +#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__ +#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ +#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF + +#if defined(CATCH_CONFIG_DISABLE) + #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \ + static void TestName() + #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \ + namespace{ \ + struct TestName : INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF ClassName) { \ + void test(); \ + }; \ + } \ + void TestName::test() + +#endif + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ + static void TestName(); \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ + static void TestName() + #define INTERNAL_CATCH_TESTCASE( ... ) \ + INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace{ \ + struct TestName : INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF ClassName) { \ + void test(); \ + }; \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ + } \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ + void TestName::test() + #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ + INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) + + /////////////////////////////////////////////////////////////////////////////// + #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, "", Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS + +// end catch_test_registry.h +// start catch_capture.hpp + +// start catch_assertionhandler.h + +// start catch_assertioninfo.h + +// start catch_result_type.h + +namespace Catch { + + // ResultWas::OfType enum + struct ResultWas { enum OfType { + Unknown = -1, + Ok = 0, + Info = 1, + Warning = 2, + + FailureBit = 0x10, + + ExpressionFailed = FailureBit | 1, + ExplicitFailure = FailureBit | 2, + + Exception = 0x100 | FailureBit, + + ThrewException = Exception | 1, + DidntThrowException = Exception | 2, + + FatalErrorCondition = 0x200 | FailureBit + + }; }; + + bool isOk( ResultWas::OfType resultType ); + bool isJustInfo( int flags ); + + // ResultDisposition::Flags enum + struct ResultDisposition { enum Flags { + Normal = 0x01, + + ContinueOnFailure = 0x02, // Failures fail test, but execution continues + FalseTest = 0x04, // Prefix expression with ! + SuppressFail = 0x08 // Failures are reported but do not fail the test + }; }; + + ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ); + + bool shouldContinueOnFailure( int flags ); + inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } + bool shouldSuppressFailure( int flags ); + +} // end namespace Catch + +// end catch_result_type.h +namespace Catch { + + struct AssertionInfo + { + StringRef macroName; + SourceLineInfo lineInfo; + StringRef capturedExpression; + ResultDisposition::Flags resultDisposition; + + // We want to delete this constructor but a compiler bug in 4.8 means + // the struct is then treated as non-aggregate + //AssertionInfo() = delete; + }; + +} // end namespace Catch + +// end catch_assertioninfo.h +// start catch_decomposer.h + +// start catch_tostring.h + +#include +#include +#include +#include +// start catch_stream.h + +#include +#include +#include + +namespace Catch { + + std::ostream& cout(); + std::ostream& cerr(); + std::ostream& clog(); + + class StringRef; + + struct IStream { + virtual ~IStream(); + virtual std::ostream& stream() const = 0; + }; + + auto makeStream( StringRef const &filename ) -> IStream const*; + + class ReusableStringStream { + std::size_t m_index; + std::ostream* m_oss; + public: + ReusableStringStream(); + ~ReusableStringStream(); + + auto str() const -> std::string; + + template + auto operator << ( T const& value ) -> ReusableStringStream& { + *m_oss << value; + return *this; + } + auto get() -> std::ostream& { return *m_oss; } + + static void cleanup(); + }; +} + +// end catch_stream.h + +#ifdef __OBJC__ +// start catch_objc_arc.hpp + +#import + +#ifdef __has_feature +#define CATCH_ARC_ENABLED __has_feature(objc_arc) +#else +#define CATCH_ARC_ENABLED 0 +#endif + +void arcSafeRelease( NSObject* obj ); +id performOptionalSelector( id obj, SEL sel ); + +#if !CATCH_ARC_ENABLED +inline void arcSafeRelease( NSObject* obj ) { + [obj release]; +} +inline id performOptionalSelector( id obj, SEL sel ) { + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; + return nil; +} +#define CATCH_UNSAFE_UNRETAINED +#define CATCH_ARC_STRONG +#else +inline void arcSafeRelease( NSObject* ){} +inline id performOptionalSelector( id obj, SEL sel ) { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" +#endif + if( [obj respondsToSelector: sel] ) + return [obj performSelector: sel]; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + return nil; +} +#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained +#define CATCH_ARC_STRONG __strong +#endif + +// end catch_objc_arc.hpp +#endif + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless +#endif + +// We need a dummy global operator<< so we can bring it into Catch namespace later +struct Catch_global_namespace_dummy {}; +std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); + +namespace Catch { + // Bring in operator<< from global namespace into Catch namespace + using ::operator<<; + + namespace Detail { + + extern const std::string unprintableString; + + std::string rawMemoryToString( const void *object, std::size_t size ); + + template + std::string rawMemoryToString( const T& object ) { + return rawMemoryToString( &object, sizeof(object) ); + } + + template + class IsStreamInsertable { + template + static auto test(int) + -> decltype(std::declval() << std::declval(), std::true_type()); + + template + static auto test(...)->std::false_type; + + public: + static const bool value = decltype(test(0))::value; + }; + + template + std::string convertUnknownEnumToString( E e ); + + template + typename std::enable_if< + !std::is_enum::value && !std::is_base_of::value, + std::string>::type convertUnstreamable( T const& ) { + return Detail::unprintableString; + } + template + typename std::enable_if< + !std::is_enum::value && std::is_base_of::value, + std::string>::type convertUnstreamable(T const& ex) { + return ex.what(); + } + + template + typename std::enable_if< + std::is_enum::value + , std::string>::type convertUnstreamable( T const& value ) { + return convertUnknownEnumToString( value ); + } + +#if defined(_MANAGED) + //! Convert a CLR string to a utf8 std::string + template + std::string clrReferenceToString( T^ ref ) { + if (ref == nullptr) + return std::string("null"); + auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString()); + cli::pin_ptr p = &bytes[0]; + return std::string(reinterpret_cast(p), bytes->Length); + } +#endif + + } // namespace Detail + + // If we decide for C++14, change these to enable_if_ts + template + struct StringMaker { + template + static + typename std::enable_if<::Catch::Detail::IsStreamInsertable::value, std::string>::type + convert(const Fake& value) { + ReusableStringStream rss; + // NB: call using the function-like syntax to avoid ambiguity with + // user-defined templated operator<< under clang. + rss.operator<<(value); + return rss.str(); + } + + template + static + typename std::enable_if::value, std::string>::type + convert( const Fake& value ) { +#if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER) + return Detail::convertUnstreamable(value); +#else + return CATCH_CONFIG_FALLBACK_STRINGIFIER(value); +#endif + } + }; + + namespace Detail { + + // This function dispatches all stringification requests inside of Catch. + // Should be preferably called fully qualified, like ::Catch::Detail::stringify + template + std::string stringify(const T& e) { + return ::Catch::StringMaker::type>::type>::convert(e); + } + + template + std::string convertUnknownEnumToString( E e ) { + return ::Catch::Detail::stringify(static_cast::type>(e)); + } + +#if defined(_MANAGED) + template + std::string stringify( T^ e ) { + return ::Catch::StringMaker::convert(e); + } +#endif + + } // namespace Detail + + // Some predefined specializations + + template<> + struct StringMaker { + static std::string convert(const std::string& str); + }; +#ifdef CATCH_CONFIG_WCHAR + template<> + struct StringMaker { + static std::string convert(const std::wstring& wstr); + }; +#endif + + template<> + struct StringMaker { + static std::string convert(char const * str); + }; + template<> + struct StringMaker { + static std::string convert(char * str); + }; + +#ifdef CATCH_CONFIG_WCHAR + template<> + struct StringMaker { + static std::string convert(wchar_t const * str); + }; + template<> + struct StringMaker { + static std::string convert(wchar_t * str); + }; +#endif + + // TBD: Should we use `strnlen` to ensure that we don't go out of the buffer, + // while keeping string semantics? + template + struct StringMaker { + static std::string convert(char const* str) { + return ::Catch::Detail::stringify(std::string{ str }); + } + }; + template + struct StringMaker { + static std::string convert(signed char const* str) { + return ::Catch::Detail::stringify(std::string{ reinterpret_cast(str) }); + } + }; + template + struct StringMaker { + static std::string convert(unsigned char const* str) { + return ::Catch::Detail::stringify(std::string{ reinterpret_cast(str) }); + } + }; + + template<> + struct StringMaker { + static std::string convert(int value); + }; + template<> + struct StringMaker { + static std::string convert(long value); + }; + template<> + struct StringMaker { + static std::string convert(long long value); + }; + template<> + struct StringMaker { + static std::string convert(unsigned int value); + }; + template<> + struct StringMaker { + static std::string convert(unsigned long value); + }; + template<> + struct StringMaker { + static std::string convert(unsigned long long value); + }; + + template<> + struct StringMaker { + static std::string convert(bool b); + }; + + template<> + struct StringMaker { + static std::string convert(char c); + }; + template<> + struct StringMaker { + static std::string convert(signed char c); + }; + template<> + struct StringMaker { + static std::string convert(unsigned char c); + }; + + template<> + struct StringMaker { + static std::string convert(std::nullptr_t); + }; + + template<> + struct StringMaker { + static std::string convert(float value); + }; + template<> + struct StringMaker { + static std::string convert(double value); + }; + + template + struct StringMaker { + template + static std::string convert(U* p) { + if (p) { + return ::Catch::Detail::rawMemoryToString(p); + } else { + return "nullptr"; + } + } + }; + + template + struct StringMaker { + static std::string convert(R C::* p) { + if (p) { + return ::Catch::Detail::rawMemoryToString(p); + } else { + return "nullptr"; + } + } + }; + +#if defined(_MANAGED) + template + struct StringMaker { + static std::string convert( T^ ref ) { + return ::Catch::Detail::clrReferenceToString(ref); + } + }; +#endif + + namespace Detail { + template + std::string rangeToString(InputIterator first, InputIterator last) { + ReusableStringStream rss; + rss << "{ "; + if (first != last) { + rss << ::Catch::Detail::stringify(*first); + for (++first; first != last; ++first) + rss << ", " << ::Catch::Detail::stringify(*first); + } + rss << " }"; + return rss.str(); + } + } + +#ifdef __OBJC__ + template<> + struct StringMaker { + static std::string convert(NSString * nsstring) { + if (!nsstring) + return "nil"; + return std::string("@") + [nsstring UTF8String]; + } + }; + template<> + struct StringMaker { + static std::string convert(NSObject* nsObject) { + return ::Catch::Detail::stringify([nsObject description]); + } + + }; + namespace Detail { + inline std::string stringify( NSString* nsstring ) { + return StringMaker::convert( nsstring ); + } + + } // namespace Detail +#endif // __OBJC__ + +} // namespace Catch + +////////////////////////////////////////////////////// +// Separate std-lib types stringification, so it can be selectively enabled +// This means that we do not bring in + +#if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS) +# define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER +# define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER +# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER +#endif + +// Separate std::pair specialization +#if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER) +#include +namespace Catch { + template + struct StringMaker > { + static std::string convert(const std::pair& pair) { + ReusableStringStream rss; + rss << "{ " + << ::Catch::Detail::stringify(pair.first) + << ", " + << ::Catch::Detail::stringify(pair.second) + << " }"; + return rss.str(); + } + }; +} +#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER + +// Separate std::tuple specialization +#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER) +#include +namespace Catch { + namespace Detail { + template< + typename Tuple, + std::size_t N = 0, + bool = (N < std::tuple_size::value) + > + struct TupleElementPrinter { + static void print(const Tuple& tuple, std::ostream& os) { + os << (N ? ", " : " ") + << ::Catch::Detail::stringify(std::get(tuple)); + TupleElementPrinter::print(tuple, os); + } + }; + + template< + typename Tuple, + std::size_t N + > + struct TupleElementPrinter { + static void print(const Tuple&, std::ostream&) {} + }; + + } + + template + struct StringMaker> { + static std::string convert(const std::tuple& tuple) { + ReusableStringStream rss; + rss << '{'; + Detail::TupleElementPrinter>::print(tuple, rss.get()); + rss << " }"; + return rss.str(); + } + }; +} +#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER + +namespace Catch { + struct not_this_one {}; // Tag type for detecting which begin/ end are being selected + + // Import begin/ end from std here so they are considered alongside the fallback (...) overloads in this namespace + using std::begin; + using std::end; + + not_this_one begin( ... ); + not_this_one end( ... ); + + template + struct is_range { + static const bool value = + !std::is_same())), not_this_one>::value && + !std::is_same())), not_this_one>::value; + }; + +#if defined(_MANAGED) // Managed types are never ranges + template + struct is_range { + static const bool value = false; + }; +#endif + + template + std::string rangeToString( Range const& range ) { + return ::Catch::Detail::rangeToString( begin( range ), end( range ) ); + } + + // Handle vector specially + template + std::string rangeToString( std::vector const& v ) { + ReusableStringStream rss; + rss << "{ "; + bool first = true; + for( bool b : v ) { + if( first ) + first = false; + else + rss << ", "; + rss << ::Catch::Detail::stringify( b ); + } + rss << " }"; + return rss.str(); + } + + template + struct StringMaker::value && !::Catch::Detail::IsStreamInsertable::value>::type> { + static std::string convert( R const& range ) { + return rangeToString( range ); + } + }; + + template + struct StringMaker { + static std::string convert(T const(&arr)[SZ]) { + return rangeToString(arr); + } + }; + +} // namespace Catch + +// Separate std::chrono::duration specialization +#if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) +#include +#include +#include + +namespace Catch { + +template +struct ratio_string { + static std::string symbol(); +}; + +template +std::string ratio_string::symbol() { + Catch::ReusableStringStream rss; + rss << '[' << Ratio::num << '/' + << Ratio::den << ']'; + return rss.str(); +} +template <> +struct ratio_string { + static std::string symbol(); +}; +template <> +struct ratio_string { + static std::string symbol(); +}; +template <> +struct ratio_string { + static std::string symbol(); +}; +template <> +struct ratio_string { + static std::string symbol(); +}; +template <> +struct ratio_string { + static std::string symbol(); +}; +template <> +struct ratio_string { + static std::string symbol(); +}; + + //////////// + // std::chrono::duration specializations + template + struct StringMaker> { + static std::string convert(std::chrono::duration const& duration) { + ReusableStringStream rss; + rss << duration.count() << ' ' << ratio_string::symbol() << 's'; + return rss.str(); + } + }; + template + struct StringMaker>> { + static std::string convert(std::chrono::duration> const& duration) { + ReusableStringStream rss; + rss << duration.count() << " s"; + return rss.str(); + } + }; + template + struct StringMaker>> { + static std::string convert(std::chrono::duration> const& duration) { + ReusableStringStream rss; + rss << duration.count() << " m"; + return rss.str(); + } + }; + template + struct StringMaker>> { + static std::string convert(std::chrono::duration> const& duration) { + ReusableStringStream rss; + rss << duration.count() << " h"; + return rss.str(); + } + }; + + //////////// + // std::chrono::time_point specialization + // Generic time_point cannot be specialized, only std::chrono::time_point + template + struct StringMaker> { + static std::string convert(std::chrono::time_point const& time_point) { + return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch"; + } + }; + // std::chrono::time_point specialization + template + struct StringMaker> { + static std::string convert(std::chrono::time_point const& time_point) { + auto converted = std::chrono::system_clock::to_time_t(time_point); + +#ifdef _MSC_VER + std::tm timeInfo = {}; + gmtime_s(&timeInfo, &converted); +#else + std::tm* timeInfo = std::gmtime(&converted); +#endif + + auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); + char timeStamp[timeStampSize]; + const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; + +#ifdef _MSC_VER + std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); +#else + std::strftime(timeStamp, timeStampSize, fmt, timeInfo); +#endif + return std::string(timeStamp); + } + }; +} +#endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +// end catch_tostring.h +#include + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4389) // '==' : signed/unsigned mismatch +#pragma warning(disable:4018) // more "signed/unsigned mismatch" +#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) +#pragma warning(disable:4180) // qualifier applied to function type has no meaning +#endif + +namespace Catch { + + struct ITransientExpression { + auto isBinaryExpression() const -> bool { return m_isBinaryExpression; } + auto getResult() const -> bool { return m_result; } + virtual void streamReconstructedExpression( std::ostream &os ) const = 0; + + ITransientExpression( bool isBinaryExpression, bool result ) + : m_isBinaryExpression( isBinaryExpression ), + m_result( result ) + {} + + // We don't actually need a virtual destructor, but many static analysers + // complain if it's not here :-( + virtual ~ITransientExpression(); + + bool m_isBinaryExpression; + bool m_result; + + }; + + void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ); + + template + class BinaryExpr : public ITransientExpression { + LhsT m_lhs; + StringRef m_op; + RhsT m_rhs; + + void streamReconstructedExpression( std::ostream &os ) const override { + formatReconstructedExpression + ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) ); + } + + public: + BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs ) + : ITransientExpression{ true, comparisonResult }, + m_lhs( lhs ), + m_op( op ), + m_rhs( rhs ) + {} + }; + + template + class UnaryExpr : public ITransientExpression { + LhsT m_lhs; + + void streamReconstructedExpression( std::ostream &os ) const override { + os << Catch::Detail::stringify( m_lhs ); + } + + public: + explicit UnaryExpr( LhsT lhs ) + : ITransientExpression{ false, lhs ? true : false }, + m_lhs( lhs ) + {} + }; + + // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int) + template + auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return static_cast(lhs == rhs); } + template + auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast( rhs ); } + template + auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast( rhs ); } + template + auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; } + template + auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) == rhs; } + + template + auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return static_cast(lhs != rhs); } + template + auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast( rhs ); } + template + auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast( rhs ); } + template + auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; } + template + auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast( lhs ) != rhs; } + + template + class ExprLhs { + LhsT m_lhs; + public: + explicit ExprLhs( LhsT lhs ) : m_lhs( lhs ) {} + + template + auto operator == ( RhsT const& rhs ) -> BinaryExpr const { + return { compareEqual( m_lhs, rhs ), m_lhs, "==", rhs }; + } + auto operator == ( bool rhs ) -> BinaryExpr const { + return { m_lhs == rhs, m_lhs, "==", rhs }; + } + + template + auto operator != ( RhsT const& rhs ) -> BinaryExpr const { + return { compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs }; + } + auto operator != ( bool rhs ) -> BinaryExpr const { + return { m_lhs != rhs, m_lhs, "!=", rhs }; + } + + template + auto operator > ( RhsT const& rhs ) -> BinaryExpr const { + return { static_cast(m_lhs > rhs), m_lhs, ">", rhs }; + } + template + auto operator < ( RhsT const& rhs ) -> BinaryExpr const { + return { static_cast(m_lhs < rhs), m_lhs, "<", rhs }; + } + template + auto operator >= ( RhsT const& rhs ) -> BinaryExpr const { + return { static_cast(m_lhs >= rhs), m_lhs, ">=", rhs }; + } + template + auto operator <= ( RhsT const& rhs ) -> BinaryExpr const { + return { static_cast(m_lhs <= rhs), m_lhs, "<=", rhs }; + } + + auto makeUnaryExpr() const -> UnaryExpr { + return UnaryExpr{ m_lhs }; + } + }; + + void handleExpression( ITransientExpression const& expr ); + + template + void handleExpression( ExprLhs const& expr ) { + handleExpression( expr.makeUnaryExpr() ); + } + + struct Decomposer { + template + auto operator <= ( T const& lhs ) -> ExprLhs { + return ExprLhs{ lhs }; + } + + auto operator <=( bool value ) -> ExprLhs { + return ExprLhs{ value }; + } + }; + +} // end namespace Catch + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +// end catch_decomposer.h +// start catch_interfaces_capture.h + +#include + +namespace Catch { + + class AssertionResult; + struct AssertionInfo; + struct SectionInfo; + struct SectionEndInfo; + struct MessageInfo; + struct Counts; + struct BenchmarkInfo; + struct BenchmarkStats; + struct AssertionReaction; + + struct ITransientExpression; + + struct IResultCapture { + + virtual ~IResultCapture(); + + virtual bool sectionStarted( SectionInfo const& sectionInfo, + Counts& assertions ) = 0; + virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; + virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; + + virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0; + virtual void benchmarkEnded( BenchmarkStats const& stats ) = 0; + + virtual void pushScopedMessage( MessageInfo const& message ) = 0; + virtual void popScopedMessage( MessageInfo const& message ) = 0; + + virtual void handleFatalErrorCondition( StringRef message ) = 0; + + virtual void handleExpr + ( AssertionInfo const& info, + ITransientExpression const& expr, + AssertionReaction& reaction ) = 0; + virtual void handleMessage + ( AssertionInfo const& info, + ResultWas::OfType resultType, + StringRef const& message, + AssertionReaction& reaction ) = 0; + virtual void handleUnexpectedExceptionNotThrown + ( AssertionInfo const& info, + AssertionReaction& reaction ) = 0; + virtual void handleUnexpectedInflightException + ( AssertionInfo const& info, + std::string const& message, + AssertionReaction& reaction ) = 0; + virtual void handleIncomplete + ( AssertionInfo const& info ) = 0; + virtual void handleNonExpr + ( AssertionInfo const &info, + ResultWas::OfType resultType, + AssertionReaction &reaction ) = 0; + + virtual bool lastAssertionPassed() = 0; + virtual void assertionPassed() = 0; + + // Deprecated, do not use: + virtual std::string getCurrentTestName() const = 0; + virtual const AssertionResult* getLastResult() const = 0; + virtual void exceptionEarlyReported() = 0; + }; + + IResultCapture& getResultCapture(); +} + +// end catch_interfaces_capture.h +namespace Catch { + + struct TestFailureException{}; + struct AssertionResultData; + struct IResultCapture; + class RunContext; + + class LazyExpression { + friend class AssertionHandler; + friend struct AssertionStats; + friend class RunContext; + + ITransientExpression const* m_transientExpression = nullptr; + bool m_isNegated; + public: + LazyExpression( bool isNegated ); + LazyExpression( LazyExpression const& other ); + LazyExpression& operator = ( LazyExpression const& ) = delete; + + explicit operator bool() const; + + friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&; + }; + + struct AssertionReaction { + bool shouldDebugBreak = false; + bool shouldThrow = false; + }; + + class AssertionHandler { + AssertionInfo m_assertionInfo; + AssertionReaction m_reaction; + bool m_completed = false; + IResultCapture& m_resultCapture; + + public: + AssertionHandler + ( StringRef macroName, + SourceLineInfo const& lineInfo, + StringRef capturedExpression, + ResultDisposition::Flags resultDisposition ); + ~AssertionHandler() { + if ( !m_completed ) { + m_resultCapture.handleIncomplete( m_assertionInfo ); + } + } + + template + void handleExpr( ExprLhs const& expr ) { + handleExpr( expr.makeUnaryExpr() ); + } + void handleExpr( ITransientExpression const& expr ); + + void handleMessage(ResultWas::OfType resultType, StringRef const& message); + + void handleExceptionThrownAsExpected(); + void handleUnexpectedExceptionNotThrown(); + void handleExceptionNotThrownAsExpected(); + void handleThrowingCallSkipped(); + void handleUnexpectedInflightException(); + + void complete(); + void setCompleted(); + + // query + auto allowThrows() const -> bool; + }; + + void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString ); + +} // namespace Catch + +// end catch_assertionhandler.h +// start catch_message.h + +#include + +namespace Catch { + + struct MessageInfo { + MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ); + + std::string macroName; + std::string message; + SourceLineInfo lineInfo; + ResultWas::OfType type; + unsigned int sequence; + + bool operator == ( MessageInfo const& other ) const; + bool operator < ( MessageInfo const& other ) const; + private: + static unsigned int globalCount; + }; + + struct MessageStream { + + template + MessageStream& operator << ( T const& value ) { + m_stream << value; + return *this; + } + + ReusableStringStream m_stream; + }; + + struct MessageBuilder : MessageStream { + MessageBuilder( std::string const& macroName, + SourceLineInfo const& lineInfo, + ResultWas::OfType type ); + + template + MessageBuilder& operator << ( T const& value ) { + m_stream << value; + return *this; + } + + MessageInfo m_info; + }; + + class ScopedMessage { + public: + explicit ScopedMessage( MessageBuilder const& builder ); + ~ScopedMessage(); + + MessageInfo m_info; + }; + +} // end namespace Catch + +// end catch_message.h +#if !defined(CATCH_CONFIG_DISABLE) + +#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION) + #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__ +#else + #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION" +#endif + +#if defined(CATCH_CONFIG_FAST_COMPILE) + +/////////////////////////////////////////////////////////////////////////////// +// Another way to speed-up compilation is to omit local try-catch for REQUIRE* +// macros. +#define INTERNAL_CATCH_TRY +#define INTERNAL_CATCH_CATCH( capturer ) + +#else // CATCH_CONFIG_FAST_COMPILE + +#define INTERNAL_CATCH_TRY try +#define INTERNAL_CATCH_CATCH( handler ) catch(...) { handler.handleUnexpectedInflightException(); } + +#endif + +#define INTERNAL_CATCH_REACT( handler ) handler.complete(); + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ + INTERNAL_CATCH_TRY { \ + CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \ + CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ + } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( (void)0, false && static_cast( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look + // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \ + INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ + if( Catch::getResultCapture().lastAssertionPassed() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \ + INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \ + if( !Catch::getResultCapture().lastAssertionPassed() ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ + try { \ + static_cast(__VA_ARGS__); \ + catchAssertionHandler.handleExceptionNotThrownAsExpected(); \ + } \ + catch( ... ) { \ + catchAssertionHandler.handleUnexpectedInflightException(); \ + } \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( false ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \ + if( catchAssertionHandler.allowThrows() ) \ + try { \ + static_cast(__VA_ARGS__); \ + catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ + } \ + catch( ... ) { \ + catchAssertionHandler.handleExceptionThrownAsExpected(); \ + } \ + else \ + catchAssertionHandler.handleThrowingCallSkipped(); \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( false ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \ + if( catchAssertionHandler.allowThrows() ) \ + try { \ + static_cast(expr); \ + catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ + } \ + catch( exceptionType const& ) { \ + catchAssertionHandler.handleExceptionThrownAsExpected(); \ + } \ + catch( ... ) { \ + catchAssertionHandler.handleUnexpectedInflightException(); \ + } \ + else \ + catchAssertionHandler.handleThrowingCallSkipped(); \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( false ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ + catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( false ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_INFO( macroName, log ) \ + Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log ); + +/////////////////////////////////////////////////////////////////////////////// +// Although this is matcher-based, it can be used with just a string +#define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ + if( catchAssertionHandler.allowThrows() ) \ + try { \ + static_cast(__VA_ARGS__); \ + catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ + } \ + catch( ... ) { \ + Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher ); \ + } \ + else \ + catchAssertionHandler.handleThrowingCallSkipped(); \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( false ) + +#endif // CATCH_CONFIG_DISABLE + +// end catch_capture.hpp +// start catch_section.h + +// start catch_section_info.h + +// start catch_totals.h + +#include + +namespace Catch { + + struct Counts { + Counts operator - ( Counts const& other ) const; + Counts& operator += ( Counts const& other ); + + std::size_t total() const; + bool allPassed() const; + bool allOk() const; + + std::size_t passed = 0; + std::size_t failed = 0; + std::size_t failedButOk = 0; + }; + + struct Totals { + + Totals operator - ( Totals const& other ) const; + Totals& operator += ( Totals const& other ); + + Totals delta( Totals const& prevTotals ) const; + + int error = 0; + Counts assertions; + Counts testCases; + }; +} + +// end catch_totals.h +#include + +namespace Catch { + + struct SectionInfo { + SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description = std::string() ); + + std::string name; + std::string description; + SourceLineInfo lineInfo; + }; + + struct SectionEndInfo { + SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ); + + SectionInfo sectionInfo; + Counts prevAssertions; + double durationInSeconds; + }; + +} // end namespace Catch + +// end catch_section_info.h +// start catch_timer.h + +#include + +namespace Catch { + + auto getCurrentNanosecondsSinceEpoch() -> uint64_t; + auto getEstimatedClockResolution() -> uint64_t; + + class Timer { + uint64_t m_nanoseconds = 0; + public: + void start(); + auto getElapsedNanoseconds() const -> uint64_t; + auto getElapsedMicroseconds() const -> uint64_t; + auto getElapsedMilliseconds() const -> unsigned int; + auto getElapsedSeconds() const -> double; + }; + +} // namespace Catch + +// end catch_timer.h +#include + +namespace Catch { + + class Section : NonCopyable { + public: + Section( SectionInfo const& info ); + ~Section(); + + // This indicates whether the section should be executed or not + explicit operator bool() const; + + private: + SectionInfo m_info; + + std::string m_name; + Counts m_assertions; + bool m_sectionIncluded; + Timer m_timer; + }; + +} // end namespace Catch + + #define INTERNAL_CATCH_SECTION( ... ) \ + if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) + +// end catch_section.h +// start catch_benchmark.h + +#include +#include + +namespace Catch { + + class BenchmarkLooper { + + std::string m_name; + std::size_t m_count = 0; + std::size_t m_iterationsToRun = 1; + uint64_t m_resolution; + Timer m_timer; + + static auto getResolution() -> uint64_t; + public: + // Keep most of this inline as it's on the code path that is being timed + BenchmarkLooper( StringRef name ) + : m_name( name ), + m_resolution( getResolution() ) + { + reportStart(); + m_timer.start(); + } + + explicit operator bool() { + if( m_count < m_iterationsToRun ) + return true; + return needsMoreIterations(); + } + + void increment() { + ++m_count; + } + + void reportStart(); + auto needsMoreIterations() -> bool; + }; + +} // end namespace Catch + +#define BENCHMARK( name ) \ + for( Catch::BenchmarkLooper looper( name ); looper; looper.increment() ) + +// end catch_benchmark.h +// start catch_interfaces_exception.h + +// start catch_interfaces_registry_hub.h + +#include +#include + +namespace Catch { + + class TestCase; + struct ITestCaseRegistry; + struct IExceptionTranslatorRegistry; + struct IExceptionTranslator; + struct IReporterRegistry; + struct IReporterFactory; + struct ITagAliasRegistry; + class StartupExceptionRegistry; + + using IReporterFactoryPtr = std::shared_ptr; + + struct IRegistryHub { + virtual ~IRegistryHub(); + + virtual IReporterRegistry const& getReporterRegistry() const = 0; + virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; + virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0; + + virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; + + virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0; + }; + + struct IMutableRegistryHub { + virtual ~IMutableRegistryHub(); + virtual void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) = 0; + virtual void registerListener( IReporterFactoryPtr const& factory ) = 0; + virtual void registerTest( TestCase const& testInfo ) = 0; + virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; + virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; + virtual void registerStartupException() noexcept = 0; + }; + + IRegistryHub& getRegistryHub(); + IMutableRegistryHub& getMutableRegistryHub(); + void cleanUp(); + std::string translateActiveException(); + +} + +// end catch_interfaces_registry_hub.h +#if defined(CATCH_CONFIG_DISABLE) + #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \ + static std::string translatorName( signature ) +#endif + +#include +#include +#include + +namespace Catch { + using exceptionTranslateFunction = std::string(*)(); + + struct IExceptionTranslator; + using ExceptionTranslators = std::vector>; + + struct IExceptionTranslator { + virtual ~IExceptionTranslator(); + virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; + }; + + struct IExceptionTranslatorRegistry { + virtual ~IExceptionTranslatorRegistry(); + + virtual std::string translateActiveException() const = 0; + }; + + class ExceptionTranslatorRegistrar { + template + class ExceptionTranslator : public IExceptionTranslator { + public: + + ExceptionTranslator( std::string(*translateFunction)( T& ) ) + : m_translateFunction( translateFunction ) + {} + + std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override { + try { + if( it == itEnd ) + std::rethrow_exception(std::current_exception()); + else + return (*it)->translate( it+1, itEnd ); + } + catch( T& ex ) { + return m_translateFunction( ex ); + } + } + + protected: + std::string(*m_translateFunction)( T& ); + }; + + public: + template + ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { + getMutableRegistryHub().registerTranslator + ( new ExceptionTranslator( translateFunction ) ); + } + }; +} + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ + static std::string translatorName( signature ); \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ + static std::string translatorName( signature ) + +#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) + +// end catch_interfaces_exception.h +// start catch_approx.h + +#include +#include + +namespace Catch { +namespace Detail { + + class Approx { + private: + bool equalityComparisonImpl(double other) const; + + public: + explicit Approx ( double value ); + + static Approx custom(); + + template ::value>::type> + Approx operator()( T const& value ) { + Approx approx( static_cast(value) ); + approx.epsilon( m_epsilon ); + approx.margin( m_margin ); + approx.scale( m_scale ); + return approx; + } + + template ::value>::type> + explicit Approx( T const& value ): Approx(static_cast(value)) + {} + + template ::value>::type> + friend bool operator == ( const T& lhs, Approx const& rhs ) { + auto lhs_v = static_cast(lhs); + return rhs.equalityComparisonImpl(lhs_v); + } + + template ::value>::type> + friend bool operator == ( Approx const& lhs, const T& rhs ) { + return operator==( rhs, lhs ); + } + + template ::value>::type> + friend bool operator != ( T const& lhs, Approx const& rhs ) { + return !operator==( lhs, rhs ); + } + + template ::value>::type> + friend bool operator != ( Approx const& lhs, T const& rhs ) { + return !operator==( rhs, lhs ); + } + + template ::value>::type> + friend bool operator <= ( T const& lhs, Approx const& rhs ) { + return static_cast(lhs) < rhs.m_value || lhs == rhs; + } + + template ::value>::type> + friend bool operator <= ( Approx const& lhs, T const& rhs ) { + return lhs.m_value < static_cast(rhs) || lhs == rhs; + } + + template ::value>::type> + friend bool operator >= ( T const& lhs, Approx const& rhs ) { + return static_cast(lhs) > rhs.m_value || lhs == rhs; + } + + template ::value>::type> + friend bool operator >= ( Approx const& lhs, T const& rhs ) { + return lhs.m_value > static_cast(rhs) || lhs == rhs; + } + + template ::value>::type> + Approx& epsilon( T const& newEpsilon ) { + double epsilonAsDouble = static_cast(newEpsilon); + if( epsilonAsDouble < 0 || epsilonAsDouble > 1.0 ) { + throw std::domain_error + ( "Invalid Approx::epsilon: " + + Catch::Detail::stringify( epsilonAsDouble ) + + ", Approx::epsilon has to be between 0 and 1" ); + } + m_epsilon = epsilonAsDouble; + return *this; + } + + template ::value>::type> + Approx& margin( T const& newMargin ) { + double marginAsDouble = static_cast(newMargin); + if( marginAsDouble < 0 ) { + throw std::domain_error + ( "Invalid Approx::margin: " + + Catch::Detail::stringify( marginAsDouble ) + + ", Approx::Margin has to be non-negative." ); + + } + m_margin = marginAsDouble; + return *this; + } + + template ::value>::type> + Approx& scale( T const& newScale ) { + m_scale = static_cast(newScale); + return *this; + } + + std::string toString() const; + + private: + double m_epsilon; + double m_margin; + double m_scale; + double m_value; + }; +} + +template<> +struct StringMaker { + static std::string convert(Catch::Detail::Approx const& value); +}; + +} // end namespace Catch + +// end catch_approx.h +// start catch_string_manip.h + +#include +#include + +namespace Catch { + + bool startsWith( std::string const& s, std::string const& prefix ); + bool startsWith( std::string const& s, char prefix ); + bool endsWith( std::string const& s, std::string const& suffix ); + bool endsWith( std::string const& s, char suffix ); + bool contains( std::string const& s, std::string const& infix ); + void toLowerInPlace( std::string& s ); + std::string toLower( std::string const& s ); + std::string trim( std::string const& str ); + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); + + struct pluralise { + pluralise( std::size_t count, std::string const& label ); + + friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); + + std::size_t m_count; + std::string m_label; + }; +} + +// end catch_string_manip.h +#ifndef CATCH_CONFIG_DISABLE_MATCHERS +// start catch_capture_matchers.h + +// start catch_matchers.h + +#include +#include + +namespace Catch { +namespace Matchers { + namespace Impl { + + template struct MatchAllOf; + template struct MatchAnyOf; + template struct MatchNotOf; + + class MatcherUntypedBase { + public: + MatcherUntypedBase() = default; + MatcherUntypedBase ( MatcherUntypedBase const& ) = default; + MatcherUntypedBase& operator = ( MatcherUntypedBase const& ) = delete; + std::string toString() const; + + protected: + virtual ~MatcherUntypedBase(); + virtual std::string describe() const = 0; + mutable std::string m_cachedToString; + }; + + template + struct MatcherMethod { + virtual bool match( ObjectT const& arg ) const = 0; + }; + template + struct MatcherMethod { + virtual bool match( PtrT* arg ) const = 0; + }; + + template + struct MatcherBase : MatcherUntypedBase, MatcherMethod { + + MatchAllOf operator && ( MatcherBase const& other ) const; + MatchAnyOf operator || ( MatcherBase const& other ) const; + MatchNotOf operator ! () const; + }; + + template + struct MatchAllOf : MatcherBase { + bool match( ArgT const& arg ) const override { + for( auto matcher : m_matchers ) { + if (!matcher->match(arg)) + return false; + } + return true; + } + std::string describe() const override { + std::string description; + description.reserve( 4 + m_matchers.size()*32 ); + description += "( "; + bool first = true; + for( auto matcher : m_matchers ) { + if( first ) + first = false; + else + description += " and "; + description += matcher->toString(); + } + description += " )"; + return description; + } + + MatchAllOf& operator && ( MatcherBase const& other ) { + m_matchers.push_back( &other ); + return *this; + } + + std::vector const*> m_matchers; + }; + template + struct MatchAnyOf : MatcherBase { + + bool match( ArgT const& arg ) const override { + for( auto matcher : m_matchers ) { + if (matcher->match(arg)) + return true; + } + return false; + } + std::string describe() const override { + std::string description; + description.reserve( 4 + m_matchers.size()*32 ); + description += "( "; + bool first = true; + for( auto matcher : m_matchers ) { + if( first ) + first = false; + else + description += " or "; + description += matcher->toString(); + } + description += " )"; + return description; + } + + MatchAnyOf& operator || ( MatcherBase const& other ) { + m_matchers.push_back( &other ); + return *this; + } + + std::vector const*> m_matchers; + }; + + template + struct MatchNotOf : MatcherBase { + + MatchNotOf( MatcherBase const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {} + + bool match( ArgT const& arg ) const override { + return !m_underlyingMatcher.match( arg ); + } + + std::string describe() const override { + return "not " + m_underlyingMatcher.toString(); + } + MatcherBase const& m_underlyingMatcher; + }; + + template + MatchAllOf MatcherBase::operator && ( MatcherBase const& other ) const { + return MatchAllOf() && *this && other; + } + template + MatchAnyOf MatcherBase::operator || ( MatcherBase const& other ) const { + return MatchAnyOf() || *this || other; + } + template + MatchNotOf MatcherBase::operator ! () const { + return MatchNotOf( *this ); + } + + } // namespace Impl + +} // namespace Matchers + +using namespace Matchers; +using Matchers::Impl::MatcherBase; + +} // namespace Catch + +// end catch_matchers.h +// start catch_matchers_floating.h + +#include +#include + +namespace Catch { +namespace Matchers { + + namespace Floating { + + enum class FloatingPointKind : uint8_t; + + struct WithinAbsMatcher : MatcherBase { + WithinAbsMatcher(double target, double margin); + bool match(double const& matchee) const override; + std::string describe() const override; + private: + double m_target; + double m_margin; + }; + + struct WithinUlpsMatcher : MatcherBase { + WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType); + bool match(double const& matchee) const override; + std::string describe() const override; + private: + double m_target; + int m_ulps; + FloatingPointKind m_type; + }; + + } // namespace Floating + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + Floating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff); + Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff); + Floating::WithinAbsMatcher WithinAbs(double target, double margin); + +} // namespace Matchers +} // namespace Catch + +// end catch_matchers_floating.h +// start catch_matchers_generic.hpp + +#include +#include + +namespace Catch { +namespace Matchers { +namespace Generic { + +namespace Detail { + std::string finalizeDescription(const std::string& desc); +} + +template +class PredicateMatcher : public MatcherBase { + std::function m_predicate; + std::string m_description; +public: + + PredicateMatcher(std::function const& elem, std::string const& descr) + :m_predicate(std::move(elem)), + m_description(Detail::finalizeDescription(descr)) + {} + + bool match( T const& item ) const override { + return m_predicate(item); + } + + std::string describe() const override { + return m_description; + } +}; + +} // namespace Generic + + // The following functions create the actual matcher objects. + // The user has to explicitly specify type to the function, because + // infering std::function is hard (but possible) and + // requires a lot of TMP. + template + Generic::PredicateMatcher Predicate(std::function const& predicate, std::string const& description = "") { + return Generic::PredicateMatcher(predicate, description); + } + +} // namespace Matchers +} // namespace Catch + +// end catch_matchers_generic.hpp +// start catch_matchers_string.h + +#include + +namespace Catch { +namespace Matchers { + + namespace StdString { + + struct CasedString + { + CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ); + std::string adjustString( std::string const& str ) const; + std::string caseSensitivitySuffix() const; + + CaseSensitive::Choice m_caseSensitivity; + std::string m_str; + }; + + struct StringMatcherBase : MatcherBase { + StringMatcherBase( std::string const& operation, CasedString const& comparator ); + std::string describe() const override; + + CasedString m_comparator; + std::string m_operation; + }; + + struct EqualsMatcher : StringMatcherBase { + EqualsMatcher( CasedString const& comparator ); + bool match( std::string const& source ) const override; + }; + struct ContainsMatcher : StringMatcherBase { + ContainsMatcher( CasedString const& comparator ); + bool match( std::string const& source ) const override; + }; + struct StartsWithMatcher : StringMatcherBase { + StartsWithMatcher( CasedString const& comparator ); + bool match( std::string const& source ) const override; + }; + struct EndsWithMatcher : StringMatcherBase { + EndsWithMatcher( CasedString const& comparator ); + bool match( std::string const& source ) const override; + }; + + struct RegexMatcher : MatcherBase { + RegexMatcher( std::string regex, CaseSensitive::Choice caseSensitivity ); + bool match( std::string const& matchee ) const override; + std::string describe() const override; + + private: + std::string m_regex; + CaseSensitive::Choice m_caseSensitivity; + }; + + } // namespace StdString + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + + StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); + StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); + StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); + StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); + StdString::RegexMatcher Matches( std::string const& regex, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); + +} // namespace Matchers +} // namespace Catch + +// end catch_matchers_string.h +// start catch_matchers_vector.h + +#include + +namespace Catch { +namespace Matchers { + + namespace Vector { + namespace Detail { + template + size_t count(InputIterator first, InputIterator last, T const& item) { + size_t cnt = 0; + for (; first != last; ++first) { + if (*first == item) { + ++cnt; + } + } + return cnt; + } + template + bool contains(InputIterator first, InputIterator last, T const& item) { + for (; first != last; ++first) { + if (*first == item) { + return true; + } + } + return false; + } + } + + template + struct ContainsElementMatcher : MatcherBase> { + + ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {} + + bool match(std::vector const &v) const override { + for (auto const& el : v) { + if (el == m_comparator) { + return true; + } + } + return false; + } + + std::string describe() const override { + return "Contains: " + ::Catch::Detail::stringify( m_comparator ); + } + + T const& m_comparator; + }; + + template + struct ContainsMatcher : MatcherBase> { + + ContainsMatcher(std::vector const &comparator) : m_comparator( comparator ) {} + + bool match(std::vector const &v) const override { + // !TBD: see note in EqualsMatcher + if (m_comparator.size() > v.size()) + return false; + for (auto const& comparator : m_comparator) { + auto present = false; + for (const auto& el : v) { + if (el == comparator) { + present = true; + break; + } + } + if (!present) { + return false; + } + } + return true; + } + std::string describe() const override { + return "Contains: " + ::Catch::Detail::stringify( m_comparator ); + } + + std::vector const& m_comparator; + }; + + template + struct EqualsMatcher : MatcherBase> { + + EqualsMatcher(std::vector const &comparator) : m_comparator( comparator ) {} + + bool match(std::vector const &v) const override { + // !TBD: This currently works if all elements can be compared using != + // - a more general approach would be via a compare template that defaults + // to using !=. but could be specialised for, e.g. std::vector etc + // - then just call that directly + if (m_comparator.size() != v.size()) + return false; + for (std::size_t i = 0; i < v.size(); ++i) + if (m_comparator[i] != v[i]) + return false; + return true; + } + std::string describe() const override { + return "Equals: " + ::Catch::Detail::stringify( m_comparator ); + } + std::vector const& m_comparator; + }; + + template + struct UnorderedEqualsMatcher : MatcherBase> { + UnorderedEqualsMatcher(std::vector const& target) : m_target(target) {} + bool match(std::vector const& vec) const override { + // Note: This is a reimplementation of std::is_permutation, + // because I don't want to include inside the common path + if (m_target.size() != vec.size()) { + return false; + } + auto lfirst = m_target.begin(), llast = m_target.end(); + auto rfirst = vec.begin(), rlast = vec.end(); + // Cut common prefix to optimize checking of permuted parts + while (lfirst != llast && *lfirst != *rfirst) { + ++lfirst; ++rfirst; + } + if (lfirst == llast) { + return true; + } + + for (auto mid = lfirst; mid != llast; ++mid) { + // Skip already counted items + if (Detail::contains(lfirst, mid, *mid)) { + continue; + } + size_t num_vec = Detail::count(rfirst, rlast, *mid); + if (num_vec == 0 || Detail::count(lfirst, llast, *mid) != num_vec) { + return false; + } + } + + return true; + } + + std::string describe() const override { + return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target); + } + private: + std::vector const& m_target; + }; + + } // namespace Vector + + // The following functions create the actual matcher objects. + // This allows the types to be inferred + + template + Vector::ContainsMatcher Contains( std::vector const& comparator ) { + return Vector::ContainsMatcher( comparator ); + } + + template + Vector::ContainsElementMatcher VectorContains( T const& comparator ) { + return Vector::ContainsElementMatcher( comparator ); + } + + template + Vector::EqualsMatcher Equals( std::vector const& comparator ) { + return Vector::EqualsMatcher( comparator ); + } + + template + Vector::UnorderedEqualsMatcher UnorderedEquals(std::vector const& target) { + return Vector::UnorderedEqualsMatcher(target); + } + +} // namespace Matchers +} // namespace Catch + +// end catch_matchers_vector.h +namespace Catch { + + template + class MatchExpr : public ITransientExpression { + ArgT const& m_arg; + MatcherT m_matcher; + StringRef m_matcherString; + public: + MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString ) + : ITransientExpression{ true, matcher.match( arg ) }, + m_arg( arg ), + m_matcher( matcher ), + m_matcherString( matcherString ) + {} + + void streamReconstructedExpression( std::ostream &os ) const override { + auto matcherAsString = m_matcher.toString(); + os << Catch::Detail::stringify( m_arg ) << ' '; + if( matcherAsString == Detail::unprintableString ) + os << m_matcherString; + else + os << matcherAsString; + } + }; + + using StringMatcher = Matchers::Impl::MatcherBase; + + void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ); + + template + auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef matcherString ) -> MatchExpr { + return MatchExpr( arg, matcher, matcherString ); + } + +} // namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ + INTERNAL_CATCH_TRY { \ + catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher ) ); \ + } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( false ) + +/////////////////////////////////////////////////////////////////////////////// +#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \ + do { \ + Catch::AssertionHandler catchAssertionHandler( macroName, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \ + if( catchAssertionHandler.allowThrows() ) \ + try { \ + static_cast(__VA_ARGS__ ); \ + catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \ + } \ + catch( exceptionType const& ex ) { \ + catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher ) ); \ + } \ + catch( ... ) { \ + catchAssertionHandler.handleUnexpectedInflightException(); \ + } \ + else \ + catchAssertionHandler.handleThrowingCallSkipped(); \ + INTERNAL_CATCH_REACT( catchAssertionHandler ) \ + } while( false ) + +// end catch_capture_matchers.h +#endif + +// These files are included here so the single_include script doesn't put them +// in the conditionally compiled sections +// start catch_test_case_info.h + +#include +#include +#include + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +namespace Catch { + + struct ITestInvoker; + + struct TestCaseInfo { + enum SpecialProperties{ + None = 0, + IsHidden = 1 << 1, + ShouldFail = 1 << 2, + MayFail = 1 << 3, + Throws = 1 << 4, + NonPortable = 1 << 5, + Benchmark = 1 << 6 + }; + + TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::vector const& _tags, + SourceLineInfo const& _lineInfo ); + + friend void setTags( TestCaseInfo& testCaseInfo, std::vector tags ); + + bool isHidden() const; + bool throws() const; + bool okToFail() const; + bool expectedToFail() const; + + std::string tagsAsString() const; + + std::string name; + std::string className; + std::string description; + std::vector tags; + std::vector lcaseTags; + SourceLineInfo lineInfo; + SpecialProperties properties; + }; + + class TestCase : public TestCaseInfo { + public: + + TestCase( ITestInvoker* testCase, TestCaseInfo&& info ); + + TestCase withName( std::string const& _newName ) const; + + void invoke() const; + + TestCaseInfo const& getTestCaseInfo() const; + + bool operator == ( TestCase const& other ) const; + bool operator < ( TestCase const& other ) const; + + private: + std::shared_ptr test; + }; + + TestCase makeTestCase( ITestInvoker* testCase, + std::string const& className, + NameAndTags const& nameAndTags, + SourceLineInfo const& lineInfo ); +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// end catch_test_case_info.h +// start catch_interfaces_runner.h + +namespace Catch { + + struct IRunner { + virtual ~IRunner(); + virtual bool aborting() const = 0; + }; +} + +// end catch_interfaces_runner.h + +#ifdef __OBJC__ +// start catch_objc.hpp + +#import + +#include + +// NB. Any general catch headers included here must be included +// in catch.hpp first to make sure they are included by the single +// header for non obj-usage + +/////////////////////////////////////////////////////////////////////////////// +// This protocol is really only here for (self) documenting purposes, since +// all its methods are optional. +@protocol OcFixture + +@optional + +-(void) setUp; +-(void) tearDown; + +@end + +namespace Catch { + + class OcMethod : public ITestInvoker { + + public: + OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} + + virtual void invoke() const { + id obj = [[m_cls alloc] init]; + + performOptionalSelector( obj, @selector(setUp) ); + performOptionalSelector( obj, m_sel ); + performOptionalSelector( obj, @selector(tearDown) ); + + arcSafeRelease( obj ); + } + private: + virtual ~OcMethod() {} + + Class m_cls; + SEL m_sel; + }; + + namespace Detail{ + + inline std::string getAnnotation( Class cls, + std::string const& annotationName, + std::string const& testCaseName ) { + NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; + SEL sel = NSSelectorFromString( selStr ); + arcSafeRelease( selStr ); + id value = performOptionalSelector( cls, sel ); + if( value ) + return [(NSString*)value UTF8String]; + return ""; + } + } + + inline std::size_t registerTestMethods() { + std::size_t noTestMethods = 0; + int noClasses = objc_getClassList( nullptr, 0 ); + + Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); + objc_getClassList( classes, noClasses ); + + for( int c = 0; c < noClasses; c++ ) { + Class cls = classes[c]; + { + u_int count; + Method* methods = class_copyMethodList( cls, &count ); + for( u_int m = 0; m < count ; m++ ) { + SEL selector = method_getName(methods[m]); + std::string methodName = sel_getName(selector); + if( startsWith( methodName, "Catch_TestCase_" ) ) { + std::string testCaseName = methodName.substr( 15 ); + std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); + std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); + const char* className = class_getName( cls ); + + getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo("",0) ) ); + noTestMethods++; + } + } + free(methods); + } + } + return noTestMethods; + } + +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) + + namespace Matchers { + namespace Impl { + namespace NSStringMatchers { + + struct StringHolder : MatcherBase{ + StringHolder( NSString* substr ) : m_substr( [substr copy] ){} + StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} + StringHolder() { + arcSafeRelease( m_substr ); + } + + bool match( NSString* arg ) const override { + return false; + } + + NSString* CATCH_ARC_STRONG m_substr; + }; + + struct Equals : StringHolder { + Equals( NSString* substr ) : StringHolder( substr ){} + + bool match( NSString* str ) const override { + return (str != nil || m_substr == nil ) && + [str isEqualToString:m_substr]; + } + + std::string describe() const override { + return "equals string: " + Catch::Detail::stringify( m_substr ); + } + }; + + struct Contains : StringHolder { + Contains( NSString* substr ) : StringHolder( substr ){} + + bool match( NSString* str ) const { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location != NSNotFound; + } + + std::string describe() const override { + return "contains string: " + Catch::Detail::stringify( m_substr ); + } + }; + + struct StartsWith : StringHolder { + StartsWith( NSString* substr ) : StringHolder( substr ){} + + bool match( NSString* str ) const override { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == 0; + } + + std::string describe() const override { + return "starts with: " + Catch::Detail::stringify( m_substr ); + } + }; + struct EndsWith : StringHolder { + EndsWith( NSString* substr ) : StringHolder( substr ){} + + bool match( NSString* str ) const override { + return (str != nil || m_substr == nil ) && + [str rangeOfString:m_substr].location == [str length] - [m_substr length]; + } + + std::string describe() const override { + return "ends with: " + Catch::Detail::stringify( m_substr ); + } + }; + + } // namespace NSStringMatchers + } // namespace Impl + + inline Impl::NSStringMatchers::Equals + Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } + + inline Impl::NSStringMatchers::Contains + Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } + + inline Impl::NSStringMatchers::StartsWith + StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } + + inline Impl::NSStringMatchers::EndsWith + EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } + + } // namespace Matchers + + using namespace Matchers; + +#endif // CATCH_CONFIG_DISABLE_MATCHERS + +} // namespace Catch + +/////////////////////////////////////////////////////////////////////////////// +#define OC_MAKE_UNIQUE_NAME( root, uniqueSuffix ) root##uniqueSuffix +#define OC_TEST_CASE2( name, desc, uniqueSuffix ) \ ++(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Name_test_, uniqueSuffix ) \ +{ \ +return @ name; \ +} \ ++(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Description_test_, uniqueSuffix ) \ +{ \ +return @ desc; \ +} \ +-(void) OC_MAKE_UNIQUE_NAME( Catch_TestCase_test_, uniqueSuffix ) + +#define OC_TEST_CASE( name, desc ) OC_TEST_CASE2( name, desc, __LINE__ ) + +// end catch_objc.hpp +#endif + +#ifdef CATCH_CONFIG_EXTERNAL_INTERFACES +// start catch_external_interfaces.h + +// start catch_reporter_bases.hpp + +// start catch_interfaces_reporter.h + +// start catch_config.hpp + +// start catch_test_spec_parser.h + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +// start catch_test_spec.h + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpadded" +#endif + +// start catch_wildcard_pattern.h + +namespace Catch +{ + class WildcardPattern { + enum WildcardPosition { + NoWildcard = 0, + WildcardAtStart = 1, + WildcardAtEnd = 2, + WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd + }; + + public: + + WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ); + virtual ~WildcardPattern() = default; + virtual bool matches( std::string const& str ) const; + + private: + std::string adjustCase( std::string const& str ) const; + CaseSensitive::Choice m_caseSensitivity; + WildcardPosition m_wildcard = NoWildcard; + std::string m_pattern; + }; +} + +// end catch_wildcard_pattern.h +#include +#include +#include + +namespace Catch { + + class TestSpec { + struct Pattern { + virtual ~Pattern(); + virtual bool matches( TestCaseInfo const& testCase ) const = 0; + }; + using PatternPtr = std::shared_ptr; + + class NamePattern : public Pattern { + public: + NamePattern( std::string const& name ); + virtual ~NamePattern(); + virtual bool matches( TestCaseInfo const& testCase ) const override; + private: + WildcardPattern m_wildcardPattern; + }; + + class TagPattern : public Pattern { + public: + TagPattern( std::string const& tag ); + virtual ~TagPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const override; + private: + std::string m_tag; + }; + + class ExcludedPattern : public Pattern { + public: + ExcludedPattern( PatternPtr const& underlyingPattern ); + virtual ~ExcludedPattern(); + virtual bool matches( TestCaseInfo const& testCase ) const override; + private: + PatternPtr m_underlyingPattern; + }; + + struct Filter { + std::vector m_patterns; + + bool matches( TestCaseInfo const& testCase ) const; + }; + + public: + bool hasFilters() const; + bool matches( TestCaseInfo const& testCase ) const; + + private: + std::vector m_filters; + + friend class TestSpecParser; + }; +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// end catch_test_spec.h +// start catch_interfaces_tag_alias_registry.h + +#include + +namespace Catch { + + struct TagAlias; + + struct ITagAliasRegistry { + virtual ~ITagAliasRegistry(); + // Nullptr if not present + virtual TagAlias const* find( std::string const& alias ) const = 0; + virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; + + static ITagAliasRegistry const& get(); + }; + +} // end namespace Catch + +// end catch_interfaces_tag_alias_registry.h +namespace Catch { + + class TestSpecParser { + enum Mode{ None, Name, QuotedName, Tag, EscapedName }; + Mode m_mode = None; + bool m_exclusion = false; + std::size_t m_start = std::string::npos, m_pos = 0; + std::string m_arg; + std::vector m_escapeChars; + TestSpec::Filter m_currentFilter; + TestSpec m_testSpec; + ITagAliasRegistry const* m_tagAliases = nullptr; + + public: + TestSpecParser( ITagAliasRegistry const& tagAliases ); + + TestSpecParser& parse( std::string const& arg ); + TestSpec testSpec(); + + private: + void visitChar( char c ); + void startNewMode( Mode mode, std::size_t start ); + void escape(); + std::string subString() const; + + template + void addPattern() { + std::string token = subString(); + for( std::size_t i = 0; i < m_escapeChars.size(); ++i ) + token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 ); + m_escapeChars.clear(); + if( startsWith( token, "exclude:" ) ) { + m_exclusion = true; + token = token.substr( 8 ); + } + if( !token.empty() ) { + TestSpec::PatternPtr pattern = std::make_shared( token ); + if( m_exclusion ) + pattern = std::make_shared( pattern ); + m_currentFilter.m_patterns.push_back( pattern ); + } + m_exclusion = false; + m_mode = None; + } + + void addFilter(); + }; + TestSpec parseTestSpec( std::string const& arg ); + +} // namespace Catch + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// end catch_test_spec_parser.h +// start catch_interfaces_config.h + +#include +#include +#include +#include + +namespace Catch { + + enum class Verbosity { + Quiet = 0, + Normal, + High + }; + + struct WarnAbout { enum What { + Nothing = 0x00, + NoAssertions = 0x01, + NoTests = 0x02 + }; }; + + struct ShowDurations { enum OrNot { + DefaultForReporter, + Always, + Never + }; }; + struct RunTests { enum InWhatOrder { + InDeclarationOrder, + InLexicographicalOrder, + InRandomOrder + }; }; + struct UseColour { enum YesOrNo { + Auto, + Yes, + No + }; }; + struct WaitForKeypress { enum When { + Never, + BeforeStart = 1, + BeforeExit = 2, + BeforeStartAndExit = BeforeStart | BeforeExit + }; }; + + class TestSpec; + + struct IConfig : NonCopyable { + + virtual ~IConfig(); + + virtual bool allowThrows() const = 0; + virtual std::ostream& stream() const = 0; + virtual std::string name() const = 0; + virtual bool includeSuccessfulResults() const = 0; + virtual bool shouldDebugBreak() const = 0; + virtual bool warnAboutMissingAssertions() const = 0; + virtual bool warnAboutNoTests() const = 0; + virtual int abortAfter() const = 0; + virtual bool showInvisibles() const = 0; + virtual ShowDurations::OrNot showDurations() const = 0; + virtual TestSpec const& testSpec() const = 0; + virtual bool hasTestFilters() const = 0; + virtual RunTests::InWhatOrder runOrder() const = 0; + virtual unsigned int rngSeed() const = 0; + virtual int benchmarkResolutionMultiple() const = 0; + virtual UseColour::YesOrNo useColour() const = 0; + virtual std::vector const& getSectionsToRun() const = 0; + virtual Verbosity verbosity() const = 0; + }; + + using IConfigPtr = std::shared_ptr; +} + +// end catch_interfaces_config.h +// Libstdc++ doesn't like incomplete classes for unique_ptr + +#include +#include +#include + +#ifndef CATCH_CONFIG_CONSOLE_WIDTH +#define CATCH_CONFIG_CONSOLE_WIDTH 80 +#endif + +namespace Catch { + + struct IStream; + + struct ConfigData { + bool listTests = false; + bool listTags = false; + bool listReporters = false; + bool listTestNamesOnly = false; + + bool showSuccessfulTests = false; + bool shouldDebugBreak = false; + bool noThrow = false; + bool showHelp = false; + bool showInvisibles = false; + bool filenamesAsTags = false; + bool libIdentify = false; + + int abortAfter = -1; + unsigned int rngSeed = 0; + int benchmarkResolutionMultiple = 100; + + Verbosity verbosity = Verbosity::Normal; + WarnAbout::What warnings = WarnAbout::Nothing; + ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter; + RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder; + UseColour::YesOrNo useColour = UseColour::Auto; + WaitForKeypress::When waitForKeypress = WaitForKeypress::Never; + + std::string outputFilename; + std::string name; + std::string processName; +#ifndef CATCH_CONFIG_DEFAULT_REPORTER +#define CATCH_CONFIG_DEFAULT_REPORTER "console" +#endif + std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER; +#undef CATCH_CONFIG_DEFAULT_REPORTER + + std::vector testsOrTags; + std::vector sectionsToRun; + }; + + class Config : public IConfig { + public: + + Config() = default; + Config( ConfigData const& data ); + virtual ~Config() = default; + + std::string const& getFilename() const; + + bool listTests() const; + bool listTestNamesOnly() const; + bool listTags() const; + bool listReporters() const; + + std::string getProcessName() const; + std::string const& getReporterName() const; + + std::vector const& getTestsOrTags() const; + std::vector const& getSectionsToRun() const override; + + virtual TestSpec const& testSpec() const override; + bool hasTestFilters() const override; + + bool showHelp() const; + + // IConfig interface + bool allowThrows() const override; + std::ostream& stream() const override; + std::string name() const override; + bool includeSuccessfulResults() const override; + bool warnAboutMissingAssertions() const override; + bool warnAboutNoTests() const override; + ShowDurations::OrNot showDurations() const override; + RunTests::InWhatOrder runOrder() const override; + unsigned int rngSeed() const override; + int benchmarkResolutionMultiple() const override; + UseColour::YesOrNo useColour() const override; + bool shouldDebugBreak() const override; + int abortAfter() const override; + bool showInvisibles() const override; + Verbosity verbosity() const override; + + private: + + IStream const* openStream(); + ConfigData m_data; + + std::unique_ptr m_stream; + TestSpec m_testSpec; + bool m_hasTestFilters = false; + }; + +} // end namespace Catch + +// end catch_config.hpp +// start catch_assertionresult.h + +#include + +namespace Catch { + + struct AssertionResultData + { + AssertionResultData() = delete; + + AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression ); + + std::string message; + mutable std::string reconstructedExpression; + LazyExpression lazyExpression; + ResultWas::OfType resultType; + + std::string reconstructExpression() const; + }; + + class AssertionResult { + public: + AssertionResult() = delete; + AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); + + bool isOk() const; + bool succeeded() const; + ResultWas::OfType getResultType() const; + bool hasExpression() const; + bool hasMessage() const; + std::string getExpression() const; + std::string getExpressionInMacro() const; + bool hasExpandedExpression() const; + std::string getExpandedExpression() const; + std::string getMessage() const; + SourceLineInfo getSourceInfo() const; + StringRef getTestMacroName() const; + + //protected: + AssertionInfo m_info; + AssertionResultData m_resultData; + }; + +} // end namespace Catch + +// end catch_assertionresult.h +// start catch_option.hpp + +namespace Catch { + + // An optional type + template + class Option { + public: + Option() : nullableValue( nullptr ) {} + Option( T const& _value ) + : nullableValue( new( storage ) T( _value ) ) + {} + Option( Option const& _other ) + : nullableValue( _other ? new( storage ) T( *_other ) : nullptr ) + {} + + ~Option() { + reset(); + } + + Option& operator= ( Option const& _other ) { + if( &_other != this ) { + reset(); + if( _other ) + nullableValue = new( storage ) T( *_other ); + } + return *this; + } + Option& operator = ( T const& _value ) { + reset(); + nullableValue = new( storage ) T( _value ); + return *this; + } + + void reset() { + if( nullableValue ) + nullableValue->~T(); + nullableValue = nullptr; + } + + T& operator*() { return *nullableValue; } + T const& operator*() const { return *nullableValue; } + T* operator->() { return nullableValue; } + const T* operator->() const { return nullableValue; } + + T valueOr( T const& defaultValue ) const { + return nullableValue ? *nullableValue : defaultValue; + } + + bool some() const { return nullableValue != nullptr; } + bool none() const { return nullableValue == nullptr; } + + bool operator !() const { return nullableValue == nullptr; } + explicit operator bool() const { + return some(); + } + + private: + T *nullableValue; + alignas(alignof(T)) char storage[sizeof(T)]; + }; + +} // end namespace Catch + +// end catch_option.hpp +#include +#include +#include +#include +#include + +namespace Catch { + + struct ReporterConfig { + explicit ReporterConfig( IConfigPtr const& _fullConfig ); + + ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream ); + + std::ostream& stream() const; + IConfigPtr fullConfig() const; + + private: + std::ostream* m_stream; + IConfigPtr m_fullConfig; + }; + + struct ReporterPreferences { + bool shouldRedirectStdOut = false; + }; + + template + struct LazyStat : Option { + LazyStat& operator=( T const& _value ) { + Option::operator=( _value ); + used = false; + return *this; + } + void reset() { + Option::reset(); + used = false; + } + bool used = false; + }; + + struct TestRunInfo { + TestRunInfo( std::string const& _name ); + std::string name; + }; + struct GroupInfo { + GroupInfo( std::string const& _name, + std::size_t _groupIndex, + std::size_t _groupsCount ); + + std::string name; + std::size_t groupIndex; + std::size_t groupsCounts; + }; + + struct AssertionStats { + AssertionStats( AssertionResult const& _assertionResult, + std::vector const& _infoMessages, + Totals const& _totals ); + + AssertionStats( AssertionStats const& ) = default; + AssertionStats( AssertionStats && ) = default; + AssertionStats& operator = ( AssertionStats const& ) = default; + AssertionStats& operator = ( AssertionStats && ) = default; + virtual ~AssertionStats(); + + AssertionResult assertionResult; + std::vector infoMessages; + Totals totals; + }; + + struct SectionStats { + SectionStats( SectionInfo const& _sectionInfo, + Counts const& _assertions, + double _durationInSeconds, + bool _missingAssertions ); + SectionStats( SectionStats const& ) = default; + SectionStats( SectionStats && ) = default; + SectionStats& operator = ( SectionStats const& ) = default; + SectionStats& operator = ( SectionStats && ) = default; + virtual ~SectionStats(); + + SectionInfo sectionInfo; + Counts assertions; + double durationInSeconds; + bool missingAssertions; + }; + + struct TestCaseStats { + TestCaseStats( TestCaseInfo const& _testInfo, + Totals const& _totals, + std::string const& _stdOut, + std::string const& _stdErr, + bool _aborting ); + + TestCaseStats( TestCaseStats const& ) = default; + TestCaseStats( TestCaseStats && ) = default; + TestCaseStats& operator = ( TestCaseStats const& ) = default; + TestCaseStats& operator = ( TestCaseStats && ) = default; + virtual ~TestCaseStats(); + + TestCaseInfo testInfo; + Totals totals; + std::string stdOut; + std::string stdErr; + bool aborting; + }; + + struct TestGroupStats { + TestGroupStats( GroupInfo const& _groupInfo, + Totals const& _totals, + bool _aborting ); + TestGroupStats( GroupInfo const& _groupInfo ); + + TestGroupStats( TestGroupStats const& ) = default; + TestGroupStats( TestGroupStats && ) = default; + TestGroupStats& operator = ( TestGroupStats const& ) = default; + TestGroupStats& operator = ( TestGroupStats && ) = default; + virtual ~TestGroupStats(); + + GroupInfo groupInfo; + Totals totals; + bool aborting; + }; + + struct TestRunStats { + TestRunStats( TestRunInfo const& _runInfo, + Totals const& _totals, + bool _aborting ); + + TestRunStats( TestRunStats const& ) = default; + TestRunStats( TestRunStats && ) = default; + TestRunStats& operator = ( TestRunStats const& ) = default; + TestRunStats& operator = ( TestRunStats && ) = default; + virtual ~TestRunStats(); + + TestRunInfo runInfo; + Totals totals; + bool aborting; + }; + + struct BenchmarkInfo { + std::string name; + }; + struct BenchmarkStats { + BenchmarkInfo info; + std::size_t iterations; + uint64_t elapsedTimeInNanoseconds; + }; + + struct IStreamingReporter { + virtual ~IStreamingReporter() = default; + + // Implementing class must also provide the following static methods: + // static std::string getDescription(); + // static std::set getSupportedVerbosities() + + virtual ReporterPreferences getPreferences() const = 0; + + virtual void noMatchingTestCases( std::string const& spec ) = 0; + + virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; + virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; + + virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; + virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; + + // *** experimental *** + virtual void benchmarkStarting( BenchmarkInfo const& ) {} + + virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; + + // The return value indicates if the messages buffer should be cleared: + virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; + + // *** experimental *** + virtual void benchmarkEnded( BenchmarkStats const& ) {} + + virtual void sectionEnded( SectionStats const& sectionStats ) = 0; + virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; + virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; + virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; + + virtual void skipTest( TestCaseInfo const& testInfo ) = 0; + + // Default empty implementation provided + virtual void fatalErrorEncountered( StringRef name ); + + virtual bool isMulti() const; + }; + using IStreamingReporterPtr = std::unique_ptr; + + struct IReporterFactory { + virtual ~IReporterFactory(); + virtual IStreamingReporterPtr create( ReporterConfig const& config ) const = 0; + virtual std::string getDescription() const = 0; + }; + using IReporterFactoryPtr = std::shared_ptr; + + struct IReporterRegistry { + using FactoryMap = std::map; + using Listeners = std::vector; + + virtual ~IReporterRegistry(); + virtual IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const = 0; + virtual FactoryMap const& getFactories() const = 0; + virtual Listeners const& getListeners() const = 0; + }; + +} // end namespace Catch + +// end catch_interfaces_reporter.h +#include +#include +#include +#include +#include +#include +#include + +namespace Catch { + void prepareExpandedExpression(AssertionResult& result); + + // Returns double formatted as %.3f (format expected on output) + std::string getFormattedDuration( double duration ); + + template + struct StreamingReporterBase : IStreamingReporter { + + StreamingReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = false; + if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) ) + throw std::domain_error( "Verbosity level not supported by this reporter" ); + } + + ReporterPreferences getPreferences() const override { + return m_reporterPrefs; + } + + static std::set getSupportedVerbosities() { + return { Verbosity::Normal }; + } + + ~StreamingReporterBase() override = default; + + void noMatchingTestCases(std::string const&) override {} + + void testRunStarting(TestRunInfo const& _testRunInfo) override { + currentTestRunInfo = _testRunInfo; + } + void testGroupStarting(GroupInfo const& _groupInfo) override { + currentGroupInfo = _groupInfo; + } + + void testCaseStarting(TestCaseInfo const& _testInfo) override { + currentTestCaseInfo = _testInfo; + } + void sectionStarting(SectionInfo const& _sectionInfo) override { + m_sectionStack.push_back(_sectionInfo); + } + + void sectionEnded(SectionStats const& /* _sectionStats */) override { + m_sectionStack.pop_back(); + } + void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override { + currentTestCaseInfo.reset(); + } + void testGroupEnded(TestGroupStats const& /* _testGroupStats */) override { + currentGroupInfo.reset(); + } + void testRunEnded(TestRunStats const& /* _testRunStats */) override { + currentTestCaseInfo.reset(); + currentGroupInfo.reset(); + currentTestRunInfo.reset(); + } + + void skipTest(TestCaseInfo const&) override { + // Don't do anything with this by default. + // It can optionally be overridden in the derived class. + } + + IConfigPtr m_config; + std::ostream& stream; + + LazyStat currentTestRunInfo; + LazyStat currentGroupInfo; + LazyStat currentTestCaseInfo; + + std::vector m_sectionStack; + ReporterPreferences m_reporterPrefs; + }; + + template + struct CumulativeReporterBase : IStreamingReporter { + template + struct Node { + explicit Node( T const& _value ) : value( _value ) {} + virtual ~Node() {} + + using ChildNodes = std::vector>; + T value; + ChildNodes children; + }; + struct SectionNode { + explicit SectionNode(SectionStats const& _stats) : stats(_stats) {} + virtual ~SectionNode() = default; + + bool operator == (SectionNode const& other) const { + return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; + } + bool operator == (std::shared_ptr const& other) const { + return operator==(*other); + } + + SectionStats stats; + using ChildSections = std::vector>; + using Assertions = std::vector; + ChildSections childSections; + Assertions assertions; + std::string stdOut; + std::string stdErr; + }; + + struct BySectionInfo { + BySectionInfo( SectionInfo const& other ) : m_other( other ) {} + BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} + bool operator() (std::shared_ptr const& node) const { + return ((node->stats.sectionInfo.name == m_other.name) && + (node->stats.sectionInfo.lineInfo == m_other.lineInfo)); + } + void operator=(BySectionInfo const&) = delete; + + private: + SectionInfo const& m_other; + }; + + using TestCaseNode = Node; + using TestGroupNode = Node; + using TestRunNode = Node; + + CumulativeReporterBase( ReporterConfig const& _config ) + : m_config( _config.fullConfig() ), + stream( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = false; + if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) ) + throw std::domain_error( "Verbosity level not supported by this reporter" ); + } + ~CumulativeReporterBase() override = default; + + ReporterPreferences getPreferences() const override { + return m_reporterPrefs; + } + + static std::set getSupportedVerbosities() { + return { Verbosity::Normal }; + } + + void testRunStarting( TestRunInfo const& ) override {} + void testGroupStarting( GroupInfo const& ) override {} + + void testCaseStarting( TestCaseInfo const& ) override {} + + void sectionStarting( SectionInfo const& sectionInfo ) override { + SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); + std::shared_ptr node; + if( m_sectionStack.empty() ) { + if( !m_rootSection ) + m_rootSection = std::make_shared( incompleteStats ); + node = m_rootSection; + } + else { + SectionNode& parentNode = *m_sectionStack.back(); + auto it = + std::find_if( parentNode.childSections.begin(), + parentNode.childSections.end(), + BySectionInfo( sectionInfo ) ); + if( it == parentNode.childSections.end() ) { + node = std::make_shared( incompleteStats ); + parentNode.childSections.push_back( node ); + } + else + node = *it; + } + m_sectionStack.push_back( node ); + m_deepestSection = std::move(node); + } + + void assertionStarting(AssertionInfo const&) override {} + + bool assertionEnded(AssertionStats const& assertionStats) override { + assert(!m_sectionStack.empty()); + // AssertionResult holds a pointer to a temporary DecomposedExpression, + // which getExpandedExpression() calls to build the expression string. + // Our section stack copy of the assertionResult will likely outlive the + // temporary, so it must be expanded or discarded now to avoid calling + // a destroyed object later. + prepareExpandedExpression(const_cast( assertionStats.assertionResult ) ); + SectionNode& sectionNode = *m_sectionStack.back(); + sectionNode.assertions.push_back(assertionStats); + return true; + } + void sectionEnded(SectionStats const& sectionStats) override { + assert(!m_sectionStack.empty()); + SectionNode& node = *m_sectionStack.back(); + node.stats = sectionStats; + m_sectionStack.pop_back(); + } + void testCaseEnded(TestCaseStats const& testCaseStats) override { + auto node = std::make_shared(testCaseStats); + assert(m_sectionStack.size() == 0); + node->children.push_back(m_rootSection); + m_testCases.push_back(node); + m_rootSection.reset(); + + assert(m_deepestSection); + m_deepestSection->stdOut = testCaseStats.stdOut; + m_deepestSection->stdErr = testCaseStats.stdErr; + } + void testGroupEnded(TestGroupStats const& testGroupStats) override { + auto node = std::make_shared(testGroupStats); + node->children.swap(m_testCases); + m_testGroups.push_back(node); + } + void testRunEnded(TestRunStats const& testRunStats) override { + auto node = std::make_shared(testRunStats); + node->children.swap(m_testGroups); + m_testRuns.push_back(node); + testRunEndedCumulative(); + } + virtual void testRunEndedCumulative() = 0; + + void skipTest(TestCaseInfo const&) override {} + + IConfigPtr m_config; + std::ostream& stream; + std::vector m_assertions; + std::vector>> m_sections; + std::vector> m_testCases; + std::vector> m_testGroups; + + std::vector> m_testRuns; + + std::shared_ptr m_rootSection; + std::shared_ptr m_deepestSection; + std::vector> m_sectionStack; + ReporterPreferences m_reporterPrefs; + }; + + template + char const* getLineOfChars() { + static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; + if( !*line ) { + std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); + line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; + } + return line; + } + + struct TestEventListenerBase : StreamingReporterBase { + TestEventListenerBase( ReporterConfig const& _config ); + + void assertionStarting(AssertionInfo const&) override; + bool assertionEnded(AssertionStats const&) override; + }; + +} // end namespace Catch + +// end catch_reporter_bases.hpp +// start catch_console_colour.h + +namespace Catch { + + struct Colour { + enum Code { + None = 0, + + White, + Red, + Green, + Blue, + Cyan, + Yellow, + Grey, + + Bright = 0x10, + + BrightRed = Bright | Red, + BrightGreen = Bright | Green, + LightGrey = Bright | Grey, + BrightWhite = Bright | White, + BrightYellow = Bright | Yellow, + + // By intention + FileName = LightGrey, + Warning = BrightYellow, + ResultError = BrightRed, + ResultSuccess = BrightGreen, + ResultExpectedFailure = Warning, + + Error = BrightRed, + Success = Green, + + OriginalExpression = Cyan, + ReconstructedExpression = BrightYellow, + + SecondaryText = LightGrey, + Headers = White + }; + + // Use constructed object for RAII guard + Colour( Code _colourCode ); + Colour( Colour&& other ) noexcept; + Colour& operator=( Colour&& other ) noexcept; + ~Colour(); + + // Use static method for one-shot changes + static void use( Code _colourCode ); + + private: + bool m_moved = false; + }; + + std::ostream& operator << ( std::ostream& os, Colour const& ); + +} // end namespace Catch + +// end catch_console_colour.h +// start catch_reporter_registrars.hpp + + +namespace Catch { + + template + class ReporterRegistrar { + + class ReporterFactory : public IReporterFactory { + + virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override { + return std::unique_ptr( new T( config ) ); + } + + virtual std::string getDescription() const override { + return T::getDescription(); + } + }; + + public: + + explicit ReporterRegistrar( std::string const& name ) { + getMutableRegistryHub().registerReporter( name, std::make_shared() ); + } + }; + + template + class ListenerRegistrar { + + class ListenerFactory : public IReporterFactory { + + virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override { + return std::unique_ptr( new T( config ) ); + } + virtual std::string getDescription() const override { + return std::string(); + } + }; + + public: + + ListenerRegistrar() { + getMutableRegistryHub().registerListener( std::make_shared() ); + } + }; +} + +#if !defined(CATCH_CONFIG_DISABLE) + +#define CATCH_REGISTER_REPORTER( name, reporterType ) \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace{ Catch::ReporterRegistrar catch_internal_RegistrarFor##reporterType( name ); } \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS + +#define CATCH_REGISTER_LISTENER( listenerType ) \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace{ Catch::ListenerRegistrar catch_internal_RegistrarFor##listenerType; } \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS +#else // CATCH_CONFIG_DISABLE + +#define CATCH_REGISTER_REPORTER(name, reporterType) +#define CATCH_REGISTER_LISTENER(listenerType) + +#endif // CATCH_CONFIG_DISABLE + +// end catch_reporter_registrars.hpp +// Allow users to base their work off existing reporters +// start catch_reporter_compact.h + +namespace Catch { + + struct CompactReporter : StreamingReporterBase { + + using StreamingReporterBase::StreamingReporterBase; + + ~CompactReporter() override; + + static std::string getDescription(); + + ReporterPreferences getPreferences() const override; + + void noMatchingTestCases(std::string const& spec) override; + + void assertionStarting(AssertionInfo const&) override; + + bool assertionEnded(AssertionStats const& _assertionStats) override; + + void sectionEnded(SectionStats const& _sectionStats) override; + + void testRunEnded(TestRunStats const& _testRunStats) override; + + }; + +} // end namespace Catch + +// end catch_reporter_compact.h +// start catch_reporter_console.h + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch + // Note that 4062 (not all labels are handled + // and default is missing) is enabled +#endif + +namespace Catch { + // Fwd decls + struct SummaryColumn; + class TablePrinter; + + struct ConsoleReporter : StreamingReporterBase { + std::unique_ptr m_tablePrinter; + + ConsoleReporter(ReporterConfig const& config); + ~ConsoleReporter() override; + static std::string getDescription(); + + void noMatchingTestCases(std::string const& spec) override; + + void assertionStarting(AssertionInfo const&) override; + + bool assertionEnded(AssertionStats const& _assertionStats) override; + + void sectionStarting(SectionInfo const& _sectionInfo) override; + void sectionEnded(SectionStats const& _sectionStats) override; + + void benchmarkStarting(BenchmarkInfo const& info) override; + void benchmarkEnded(BenchmarkStats const& stats) override; + + void testCaseEnded(TestCaseStats const& _testCaseStats) override; + void testGroupEnded(TestGroupStats const& _testGroupStats) override; + void testRunEnded(TestRunStats const& _testRunStats) override; + + private: + + void lazyPrint(); + + void lazyPrintWithoutClosingBenchmarkTable(); + void lazyPrintRunInfo(); + void lazyPrintGroupInfo(); + void printTestCaseAndSectionHeader(); + + void printClosedHeader(std::string const& _name); + void printOpenHeader(std::string const& _name); + + // if string has a : in first line will set indent to follow it on + // subsequent lines + void printHeaderString(std::string const& _string, std::size_t indent = 0); + + void printTotals(Totals const& totals); + void printSummaryRow(std::string const& label, std::vector const& cols, std::size_t row); + + void printTotalsDivider(Totals const& totals); + void printSummaryDivider(); + + private: + bool m_headerPrinted = false; + }; + +} // end namespace Catch + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +// end catch_reporter_console.h +// start catch_reporter_junit.h + +// start catch_xmlwriter.h + +#include + +namespace Catch { + + class XmlEncode { + public: + enum ForWhat { ForTextNodes, ForAttributes }; + + XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ); + + void encodeTo( std::ostream& os ) const; + + friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ); + + private: + std::string m_str; + ForWhat m_forWhat; + }; + + class XmlWriter { + public: + + class ScopedElement { + public: + ScopedElement( XmlWriter* writer ); + + ScopedElement( ScopedElement&& other ) noexcept; + ScopedElement& operator=( ScopedElement&& other ) noexcept; + + ~ScopedElement(); + + ScopedElement& writeText( std::string const& text, bool indent = true ); + + template + ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { + m_writer->writeAttribute( name, attribute ); + return *this; + } + + private: + mutable XmlWriter* m_writer = nullptr; + }; + + XmlWriter( std::ostream& os = Catch::cout() ); + ~XmlWriter(); + + XmlWriter( XmlWriter const& ) = delete; + XmlWriter& operator=( XmlWriter const& ) = delete; + + XmlWriter& startElement( std::string const& name ); + + ScopedElement scopedElement( std::string const& name ); + + XmlWriter& endElement(); + + XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ); + + XmlWriter& writeAttribute( std::string const& name, bool attribute ); + + template + XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { + ReusableStringStream rss; + rss << attribute; + return writeAttribute( name, rss.str() ); + } + + XmlWriter& writeText( std::string const& text, bool indent = true ); + + XmlWriter& writeComment( std::string const& text ); + + void writeStylesheetRef( std::string const& url ); + + XmlWriter& writeBlankLine(); + + void ensureTagClosed(); + + private: + + void writeDeclaration(); + + void newlineIfNecessary(); + + bool m_tagIsOpen = false; + bool m_needsNewline = false; + std::vector m_tags; + std::string m_indent; + std::ostream& m_os; + }; + +} + +// end catch_xmlwriter.h +namespace Catch { + + class JunitReporter : public CumulativeReporterBase { + public: + JunitReporter(ReporterConfig const& _config); + + ~JunitReporter() override; + + static std::string getDescription(); + + void noMatchingTestCases(std::string const& /*spec*/) override; + + void testRunStarting(TestRunInfo const& runInfo) override; + + void testGroupStarting(GroupInfo const& groupInfo) override; + + void testCaseStarting(TestCaseInfo const& testCaseInfo) override; + bool assertionEnded(AssertionStats const& assertionStats) override; + + void testCaseEnded(TestCaseStats const& testCaseStats) override; + + void testGroupEnded(TestGroupStats const& testGroupStats) override; + + void testRunEndedCumulative() override; + + void writeGroup(TestGroupNode const& groupNode, double suiteTime); + + void writeTestCase(TestCaseNode const& testCaseNode); + + void writeSection(std::string const& className, + std::string const& rootName, + SectionNode const& sectionNode); + + void writeAssertions(SectionNode const& sectionNode); + void writeAssertion(AssertionStats const& stats); + + XmlWriter xml; + Timer suiteTimer; + std::string stdOutForSuite; + std::string stdErrForSuite; + unsigned int unexpectedExceptions = 0; + bool m_okToFail = false; + }; + +} // end namespace Catch + +// end catch_reporter_junit.h +// start catch_reporter_xml.h + +namespace Catch { + class XmlReporter : public StreamingReporterBase { + public: + XmlReporter(ReporterConfig const& _config); + + ~XmlReporter() override; + + static std::string getDescription(); + + virtual std::string getStylesheetRef() const; + + void writeSourceInfo(SourceLineInfo const& sourceInfo); + + public: // StreamingReporterBase + + void noMatchingTestCases(std::string const& s) override; + + void testRunStarting(TestRunInfo const& testInfo) override; + + void testGroupStarting(GroupInfo const& groupInfo) override; + + void testCaseStarting(TestCaseInfo const& testInfo) override; + + void sectionStarting(SectionInfo const& sectionInfo) override; + + void assertionStarting(AssertionInfo const&) override; + + bool assertionEnded(AssertionStats const& assertionStats) override; + + void sectionEnded(SectionStats const& sectionStats) override; + + void testCaseEnded(TestCaseStats const& testCaseStats) override; + + void testGroupEnded(TestGroupStats const& testGroupStats) override; + + void testRunEnded(TestRunStats const& testRunStats) override; + + private: + Timer m_testCaseTimer; + XmlWriter m_xml; + int m_sectionDepth = 0; + }; + +} // end namespace Catch + +// end catch_reporter_xml.h + +// end catch_external_interfaces.h +#endif + +#endif // ! CATCH_CONFIG_IMPL_ONLY + +#ifdef CATCH_IMPL +// start catch_impl.hpp + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" +#endif + +// Keep these here for external reporters +// start catch_test_case_tracker.h + +#include +#include +#include + +namespace Catch { +namespace TestCaseTracking { + + struct NameAndLocation { + std::string name; + SourceLineInfo location; + + NameAndLocation( std::string const& _name, SourceLineInfo const& _location ); + }; + + struct ITracker; + + using ITrackerPtr = std::shared_ptr; + + struct ITracker { + virtual ~ITracker(); + + // static queries + virtual NameAndLocation const& nameAndLocation() const = 0; + + // dynamic queries + virtual bool isComplete() const = 0; // Successfully completed or failed + virtual bool isSuccessfullyCompleted() const = 0; + virtual bool isOpen() const = 0; // Started but not complete + virtual bool hasChildren() const = 0; + + virtual ITracker& parent() = 0; + + // actions + virtual void close() = 0; // Successfully complete + virtual void fail() = 0; + virtual void markAsNeedingAnotherRun() = 0; + + virtual void addChild( ITrackerPtr const& child ) = 0; + virtual ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) = 0; + virtual void openChild() = 0; + + // Debug/ checking + virtual bool isSectionTracker() const = 0; + virtual bool isIndexTracker() const = 0; + }; + + class TrackerContext { + + enum RunState { + NotStarted, + Executing, + CompletedCycle + }; + + ITrackerPtr m_rootTracker; + ITracker* m_currentTracker = nullptr; + RunState m_runState = NotStarted; + + public: + + static TrackerContext& instance(); + + ITracker& startRun(); + void endRun(); + + void startCycle(); + void completeCycle(); + + bool completedCycle() const; + ITracker& currentTracker(); + void setCurrentTracker( ITracker* tracker ); + }; + + class TrackerBase : public ITracker { + protected: + enum CycleState { + NotStarted, + Executing, + ExecutingChildren, + NeedsAnotherRun, + CompletedSuccessfully, + Failed + }; + + class TrackerHasName { + NameAndLocation m_nameAndLocation; + public: + TrackerHasName( NameAndLocation const& nameAndLocation ); + bool operator ()( ITrackerPtr const& tracker ) const; + }; + + using Children = std::vector; + NameAndLocation m_nameAndLocation; + TrackerContext& m_ctx; + ITracker* m_parent; + Children m_children; + CycleState m_runState = NotStarted; + + public: + TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); + + NameAndLocation const& nameAndLocation() const override; + bool isComplete() const override; + bool isSuccessfullyCompleted() const override; + bool isOpen() const override; + bool hasChildren() const override; + + void addChild( ITrackerPtr const& child ) override; + + ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) override; + ITracker& parent() override; + + void openChild() override; + + bool isSectionTracker() const override; + bool isIndexTracker() const override; + + void open(); + + void close() override; + void fail() override; + void markAsNeedingAnotherRun() override; + + private: + void moveToParent(); + void moveToThis(); + }; + + class SectionTracker : public TrackerBase { + std::vector m_filters; + public: + SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ); + + bool isSectionTracker() const override; + + static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ); + + void tryOpen(); + + void addInitialFilters( std::vector const& filters ); + void addNextFilters( std::vector const& filters ); + }; + + class IndexTracker : public TrackerBase { + int m_size; + int m_index = -1; + public: + IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size ); + + bool isIndexTracker() const override; + void close() override; + + static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ); + + int index() const; + + void moveNext(); + }; + +} // namespace TestCaseTracking + +using TestCaseTracking::ITracker; +using TestCaseTracking::TrackerContext; +using TestCaseTracking::SectionTracker; +using TestCaseTracking::IndexTracker; + +} // namespace Catch + +// end catch_test_case_tracker.h + +// start catch_leak_detector.h + +namespace Catch { + + struct LeakDetector { + LeakDetector(); + }; + +} +// end catch_leak_detector.h +// Cpp files will be included in the single-header file here +// start catch_approx.cpp + +#include +#include + +namespace { + +// Performs equivalent check of std::fabs(lhs - rhs) <= margin +// But without the subtraction to allow for INFINITY in comparison +bool marginComparison(double lhs, double rhs, double margin) { + return (lhs + margin >= rhs) && (rhs + margin >= lhs); +} + +} + +namespace Catch { +namespace Detail { + + Approx::Approx ( double value ) + : m_epsilon( std::numeric_limits::epsilon()*100 ), + m_margin( 0.0 ), + m_scale( 0.0 ), + m_value( value ) + {} + + Approx Approx::custom() { + return Approx( 0 ); + } + + std::string Approx::toString() const { + ReusableStringStream rss; + rss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )"; + return rss.str(); + } + + bool Approx::equalityComparisonImpl(const double other) const { + // First try with fixed margin, then compute margin based on epsilon, scale and Approx's value + // Thanks to Richard Harris for his help refining the scaled margin value + return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value))); + } + +} // end namespace Detail + +std::string StringMaker::convert(Catch::Detail::Approx const& value) { + return value.toString(); +} + +} // end namespace Catch +// end catch_approx.cpp +// start catch_assertionhandler.cpp + +// start catch_context.h + +#include + +namespace Catch { + + struct IResultCapture; + struct IRunner; + struct IConfig; + struct IMutableContext; + + using IConfigPtr = std::shared_ptr; + + struct IContext + { + virtual ~IContext(); + + virtual IResultCapture* getResultCapture() = 0; + virtual IRunner* getRunner() = 0; + virtual IConfigPtr const& getConfig() const = 0; + }; + + struct IMutableContext : IContext + { + virtual ~IMutableContext(); + virtual void setResultCapture( IResultCapture* resultCapture ) = 0; + virtual void setRunner( IRunner* runner ) = 0; + virtual void setConfig( IConfigPtr const& config ) = 0; + + private: + static IMutableContext *currentContext; + friend IMutableContext& getCurrentMutableContext(); + friend void cleanUpContext(); + static void createContext(); + }; + + inline IMutableContext& getCurrentMutableContext() + { + if( !IMutableContext::currentContext ) + IMutableContext::createContext(); + return *IMutableContext::currentContext; + } + + inline IContext& getCurrentContext() + { + return getCurrentMutableContext(); + } + + void cleanUpContext(); +} + +// end catch_context.h +// start catch_debugger.h + +namespace Catch { + bool isDebuggerActive(); +} + +#ifdef CATCH_PLATFORM_MAC + + #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ + +#elif defined(CATCH_PLATFORM_LINUX) + // If we can use inline assembler, do it because this allows us to break + // directly at the location of the failing check instead of breaking inside + // raise() called from it, i.e. one stack frame below. + #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) + #define CATCH_TRAP() asm volatile ("int $3") /* NOLINT */ + #else // Fall back to the generic way. + #include + + #define CATCH_TRAP() raise(SIGTRAP) + #endif +#elif defined(_MSC_VER) + #define CATCH_TRAP() __debugbreak() +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) void __stdcall DebugBreak(); + #define CATCH_TRAP() DebugBreak() +#endif + +#ifdef CATCH_TRAP + #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } +#else + namespace Catch { + inline void doNothing() {} + } + #define CATCH_BREAK_INTO_DEBUGGER() Catch::doNothing() +#endif + +// end catch_debugger.h +// start catch_run_context.h + +// start catch_fatal_condition.h + +// start catch_windows_h_proxy.h + + +#if defined(CATCH_PLATFORM_WINDOWS) + +#if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) +# define CATCH_DEFINED_NOMINMAX +# define NOMINMAX +#endif +#if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) +# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif + +#ifdef __AFXDLL +#include +#else +#include +#endif + +#ifdef CATCH_DEFINED_NOMINMAX +# undef NOMINMAX +#endif +#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN +# undef WIN32_LEAN_AND_MEAN +#endif + +#endif // defined(CATCH_PLATFORM_WINDOWS) + +// end catch_windows_h_proxy.h +#if defined( CATCH_CONFIG_WINDOWS_SEH ) + +namespace Catch { + + struct FatalConditionHandler { + + static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo); + FatalConditionHandler(); + static void reset(); + ~FatalConditionHandler(); + + private: + static bool isSet; + static ULONG guaranteeSize; + static PVOID exceptionHandlerHandle; + }; + +} // namespace Catch + +#elif defined ( CATCH_CONFIG_POSIX_SIGNALS ) + +#include + +namespace Catch { + + struct FatalConditionHandler { + + static bool isSet; + static struct sigaction oldSigActions[]; + static stack_t oldSigStack; + static char altStackMem[]; + + static void handleSignal( int sig ); + + FatalConditionHandler(); + ~FatalConditionHandler(); + static void reset(); + }; + +} // namespace Catch + +#else + +namespace Catch { + struct FatalConditionHandler { + void reset(); + }; +} + +#endif + +// end catch_fatal_condition.h +#include + +namespace Catch { + + struct IMutableContext; + + /////////////////////////////////////////////////////////////////////////// + + class RunContext : public IResultCapture, public IRunner { + + public: + RunContext( RunContext const& ) = delete; + RunContext& operator =( RunContext const& ) = delete; + + explicit RunContext( IConfigPtr const& _config, IStreamingReporterPtr&& reporter ); + + ~RunContext() override; + + void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ); + void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ); + + Totals runTest(TestCase const& testCase); + + IConfigPtr config() const; + IStreamingReporter& reporter() const; + + public: // IResultCapture + + // Assertion handlers + void handleExpr + ( AssertionInfo const& info, + ITransientExpression const& expr, + AssertionReaction& reaction ) override; + void handleMessage + ( AssertionInfo const& info, + ResultWas::OfType resultType, + StringRef const& message, + AssertionReaction& reaction ) override; + void handleUnexpectedExceptionNotThrown + ( AssertionInfo const& info, + AssertionReaction& reaction ) override; + void handleUnexpectedInflightException + ( AssertionInfo const& info, + std::string const& message, + AssertionReaction& reaction ) override; + void handleIncomplete + ( AssertionInfo const& info ) override; + void handleNonExpr + ( AssertionInfo const &info, + ResultWas::OfType resultType, + AssertionReaction &reaction ) override; + + bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override; + + void sectionEnded( SectionEndInfo const& endInfo ) override; + void sectionEndedEarly( SectionEndInfo const& endInfo ) override; + + void benchmarkStarting( BenchmarkInfo const& info ) override; + void benchmarkEnded( BenchmarkStats const& stats ) override; + + void pushScopedMessage( MessageInfo const& message ) override; + void popScopedMessage( MessageInfo const& message ) override; + + std::string getCurrentTestName() const override; + + const AssertionResult* getLastResult() const override; + + void exceptionEarlyReported() override; + + void handleFatalErrorCondition( StringRef message ) override; + + bool lastAssertionPassed() override; + + void assertionPassed() override; + + public: + // !TBD We need to do this another way! + bool aborting() const final; + + private: + + void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ); + void invokeActiveTestCase(); + + void resetAssertionInfo(); + bool testForMissingAssertions( Counts& assertions ); + + void assertionEnded( AssertionResult const& result ); + void reportExpr + ( AssertionInfo const &info, + ResultWas::OfType resultType, + ITransientExpression const *expr, + bool negated ); + + void populateReaction( AssertionReaction& reaction ); + + private: + + void handleUnfinishedSections(); + + TestRunInfo m_runInfo; + IMutableContext& m_context; + TestCase const* m_activeTestCase = nullptr; + ITracker* m_testCaseTracker; + Option m_lastResult; + + IConfigPtr m_config; + Totals m_totals; + IStreamingReporterPtr m_reporter; + std::vector m_messages; + AssertionInfo m_lastAssertionInfo; + std::vector m_unfinishedSections; + std::vector m_activeSections; + TrackerContext m_trackerContext; + bool m_lastAssertionPassed = false; + bool m_shouldReportUnexpected = true; + bool m_includeSuccessfulResults; + }; + +} // end namespace Catch + +// end catch_run_context.h +namespace Catch { + + auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& { + expr.streamReconstructedExpression( os ); + return os; + } + + LazyExpression::LazyExpression( bool isNegated ) + : m_isNegated( isNegated ) + {} + + LazyExpression::LazyExpression( LazyExpression const& other ) : m_isNegated( other.m_isNegated ) {} + + LazyExpression::operator bool() const { + return m_transientExpression != nullptr; + } + + auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream& { + if( lazyExpr.m_isNegated ) + os << "!"; + + if( lazyExpr ) { + if( lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression() ) + os << "(" << *lazyExpr.m_transientExpression << ")"; + else + os << *lazyExpr.m_transientExpression; + } + else { + os << "{** error - unchecked empty expression requested **}"; + } + return os; + } + + AssertionHandler::AssertionHandler + ( StringRef macroName, + SourceLineInfo const& lineInfo, + StringRef capturedExpression, + ResultDisposition::Flags resultDisposition ) + : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition }, + m_resultCapture( getResultCapture() ) + {} + + void AssertionHandler::handleExpr( ITransientExpression const& expr ) { + m_resultCapture.handleExpr( m_assertionInfo, expr, m_reaction ); + } + void AssertionHandler::handleMessage(ResultWas::OfType resultType, StringRef const& message) { + m_resultCapture.handleMessage( m_assertionInfo, resultType, message, m_reaction ); + } + + auto AssertionHandler::allowThrows() const -> bool { + return getCurrentContext().getConfig()->allowThrows(); + } + + void AssertionHandler::complete() { + setCompleted(); + if( m_reaction.shouldDebugBreak ) { + + // If you find your debugger stopping you here then go one level up on the + // call-stack for the code that caused it (typically a failed assertion) + + // (To go back to the test and change execution, jump over the throw, next) + CATCH_BREAK_INTO_DEBUGGER(); + } + if( m_reaction.shouldThrow ) + throw Catch::TestFailureException(); + } + void AssertionHandler::setCompleted() { + m_completed = true; + } + + void AssertionHandler::handleUnexpectedInflightException() { + m_resultCapture.handleUnexpectedInflightException( m_assertionInfo, Catch::translateActiveException(), m_reaction ); + } + + void AssertionHandler::handleExceptionThrownAsExpected() { + m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction); + } + void AssertionHandler::handleExceptionNotThrownAsExpected() { + m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction); + } + + void AssertionHandler::handleUnexpectedExceptionNotThrown() { + m_resultCapture.handleUnexpectedExceptionNotThrown( m_assertionInfo, m_reaction ); + } + + void AssertionHandler::handleThrowingCallSkipped() { + m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction); + } + + // This is the overload that takes a string and infers the Equals matcher from it + // The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp + void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef matcherString ) { + handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString ); + } + +} // namespace Catch +// end catch_assertionhandler.cpp +// start catch_assertionresult.cpp + +namespace Catch { + AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const & _lazyExpression): + lazyExpression(_lazyExpression), + resultType(_resultType) {} + + std::string AssertionResultData::reconstructExpression() const { + + if( reconstructedExpression.empty() ) { + if( lazyExpression ) { + ReusableStringStream rss; + rss << lazyExpression; + reconstructedExpression = rss.str(); + } + } + return reconstructedExpression; + } + + AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) + : m_info( info ), + m_resultData( data ) + {} + + // Result was a success + bool AssertionResult::succeeded() const { + return Catch::isOk( m_resultData.resultType ); + } + + // Result was a success, or failure is suppressed + bool AssertionResult::isOk() const { + return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); + } + + ResultWas::OfType AssertionResult::getResultType() const { + return m_resultData.resultType; + } + + bool AssertionResult::hasExpression() const { + return m_info.capturedExpression[0] != 0; + } + + bool AssertionResult::hasMessage() const { + return !m_resultData.message.empty(); + } + + std::string AssertionResult::getExpression() const { + if( isFalseTest( m_info.resultDisposition ) ) + return "!(" + m_info.capturedExpression + ")"; + else + return m_info.capturedExpression; + } + + std::string AssertionResult::getExpressionInMacro() const { + std::string expr; + if( m_info.macroName[0] == 0 ) + expr = m_info.capturedExpression; + else { + expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 ); + expr += m_info.macroName; + expr += "( "; + expr += m_info.capturedExpression; + expr += " )"; + } + return expr; + } + + bool AssertionResult::hasExpandedExpression() const { + return hasExpression() && getExpandedExpression() != getExpression(); + } + + std::string AssertionResult::getExpandedExpression() const { + std::string expr = m_resultData.reconstructExpression(); + return expr.empty() + ? getExpression() + : expr; + } + + std::string AssertionResult::getMessage() const { + return m_resultData.message; + } + SourceLineInfo AssertionResult::getSourceInfo() const { + return m_info.lineInfo; + } + + StringRef AssertionResult::getTestMacroName() const { + return m_info.macroName; + } + +} // end namespace Catch +// end catch_assertionresult.cpp +// start catch_benchmark.cpp + +namespace Catch { + + auto BenchmarkLooper::getResolution() -> uint64_t { + return getEstimatedClockResolution() * getCurrentContext().getConfig()->benchmarkResolutionMultiple(); + } + + void BenchmarkLooper::reportStart() { + getResultCapture().benchmarkStarting( { m_name } ); + } + auto BenchmarkLooper::needsMoreIterations() -> bool { + auto elapsed = m_timer.getElapsedNanoseconds(); + + // Exponentially increasing iterations until we're confident in our timer resolution + if( elapsed < m_resolution ) { + m_iterationsToRun *= 10; + return true; + } + + getResultCapture().benchmarkEnded( { { m_name }, m_count, elapsed } ); + return false; + } + +} // end namespace Catch +// end catch_benchmark.cpp +// start catch_capture_matchers.cpp + +namespace Catch { + + using StringMatcher = Matchers::Impl::MatcherBase; + + // This is the general overload that takes a any string matcher + // There is another overload, in catch_assertionhandler.h/.cpp, that only takes a string and infers + // the Equals matcher (so the header does not mention matchers) + void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef matcherString ) { + std::string exceptionMessage = Catch::translateActiveException(); + MatchExpr expr( exceptionMessage, matcher, matcherString ); + handler.handleExpr( expr ); + } + +} // namespace Catch +// end catch_capture_matchers.cpp +// start catch_commandline.cpp + +// start catch_commandline.h + +// start catch_clara.h + +// Use Catch's value for console width (store Clara's off to the side, if present) +#ifdef CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH +#undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH +#endif +#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1 + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wweak-vtables" +#pragma clang diagnostic ignored "-Wexit-time-destructors" +#pragma clang diagnostic ignored "-Wshadow" +#endif + +// start clara.hpp +// Copyright 2017 Two Blue Cubes Ltd. All rights reserved. +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// See https://github.com/philsquared/Clara for more details + +// Clara v1.1.4 + + +#ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80 +#endif + +#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH +#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH +#endif + +#ifndef CLARA_CONFIG_OPTIONAL_TYPE +#ifdef __has_include +#if __has_include() && __cplusplus >= 201703L +#include +#define CLARA_CONFIG_OPTIONAL_TYPE std::optional +#endif +#endif +#endif + +// ----------- #included from clara_textflow.hpp ----------- + +// TextFlowCpp +// +// A single-header library for wrapping and laying out basic text, by Phil Nash +// +// This work is licensed under the BSD 2-Clause license. +// See the accompanying LICENSE file, or the one at https://opensource.org/licenses/BSD-2-Clause +// +// This project is hosted at https://github.com/philsquared/textflowcpp + + +#include +#include +#include +#include + +#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH +#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80 +#endif + +namespace Catch { namespace clara { namespace TextFlow { + + inline auto isWhitespace( char c ) -> bool { + static std::string chars = " \t\n\r"; + return chars.find( c ) != std::string::npos; + } + inline auto isBreakableBefore( char c ) -> bool { + static std::string chars = "[({<|"; + return chars.find( c ) != std::string::npos; + } + inline auto isBreakableAfter( char c ) -> bool { + static std::string chars = "])}>.,:;*+-=&/\\"; + return chars.find( c ) != std::string::npos; + } + + class Columns; + + class Column { + std::vector m_strings; + size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH; + size_t m_indent = 0; + size_t m_initialIndent = std::string::npos; + + public: + class iterator { + friend Column; + + Column const& m_column; + size_t m_stringIndex = 0; + size_t m_pos = 0; + + size_t m_len = 0; + size_t m_end = 0; + bool m_suffix = false; + + iterator( Column const& column, size_t stringIndex ) + : m_column( column ), + m_stringIndex( stringIndex ) + {} + + auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; } + + auto isBoundary( size_t at ) const -> bool { + assert( at > 0 ); + assert( at <= line().size() ); + + return at == line().size() || + ( isWhitespace( line()[at] ) && !isWhitespace( line()[at-1] ) ) || + isBreakableBefore( line()[at] ) || + isBreakableAfter( line()[at-1] ); + } + + void calcLength() { + assert( m_stringIndex < m_column.m_strings.size() ); + + m_suffix = false; + auto width = m_column.m_width-indent(); + m_end = m_pos; + while( m_end < line().size() && line()[m_end] != '\n' ) + ++m_end; + + if( m_end < m_pos + width ) { + m_len = m_end - m_pos; + } + else { + size_t len = width; + while (len > 0 && !isBoundary(m_pos + len)) + --len; + while (len > 0 && isWhitespace( line()[m_pos + len - 1] )) + --len; + + if (len > 0) { + m_len = len; + } else { + m_suffix = true; + m_len = width - 1; + } + } + } + + auto indent() const -> size_t { + auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos; + return initial == std::string::npos ? m_column.m_indent : initial; + } + + auto addIndentAndSuffix(std::string const &plain) const -> std::string { + return std::string( indent(), ' ' ) + (m_suffix ? plain + "-" : plain); + } + + public: + explicit iterator( Column const& column ) : m_column( column ) { + assert( m_column.m_width > m_column.m_indent ); + assert( m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent ); + calcLength(); + if( m_len == 0 ) + m_stringIndex++; // Empty string + } + + auto operator *() const -> std::string { + assert( m_stringIndex < m_column.m_strings.size() ); + assert( m_pos <= m_end ); + if( m_pos + m_column.m_width < m_end ) + return addIndentAndSuffix(line().substr(m_pos, m_len)); + else + return addIndentAndSuffix(line().substr(m_pos, m_end - m_pos)); + } + + auto operator ++() -> iterator& { + m_pos += m_len; + if( m_pos < line().size() && line()[m_pos] == '\n' ) + m_pos += 1; + else + while( m_pos < line().size() && isWhitespace( line()[m_pos] ) ) + ++m_pos; + + if( m_pos == line().size() ) { + m_pos = 0; + ++m_stringIndex; + } + if( m_stringIndex < m_column.m_strings.size() ) + calcLength(); + return *this; + } + auto operator ++(int) -> iterator { + iterator prev( *this ); + operator++(); + return prev; + } + + auto operator ==( iterator const& other ) const -> bool { + return + m_pos == other.m_pos && + m_stringIndex == other.m_stringIndex && + &m_column == &other.m_column; + } + auto operator !=( iterator const& other ) const -> bool { + return !operator==( other ); + } + }; + using const_iterator = iterator; + + explicit Column( std::string const& text ) { m_strings.push_back( text ); } + + auto width( size_t newWidth ) -> Column& { + assert( newWidth > 0 ); + m_width = newWidth; + return *this; + } + auto indent( size_t newIndent ) -> Column& { + m_indent = newIndent; + return *this; + } + auto initialIndent( size_t newIndent ) -> Column& { + m_initialIndent = newIndent; + return *this; + } + + auto width() const -> size_t { return m_width; } + auto begin() const -> iterator { return iterator( *this ); } + auto end() const -> iterator { return { *this, m_strings.size() }; } + + inline friend std::ostream& operator << ( std::ostream& os, Column const& col ) { + bool first = true; + for( auto line : col ) { + if( first ) + first = false; + else + os << "\n"; + os << line; + } + return os; + } + + auto operator + ( Column const& other ) -> Columns; + + auto toString() const -> std::string { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + }; + + class Spacer : public Column { + + public: + explicit Spacer( size_t spaceWidth ) : Column( "" ) { + width( spaceWidth ); + } + }; + + class Columns { + std::vector m_columns; + + public: + + class iterator { + friend Columns; + struct EndTag {}; + + std::vector const& m_columns; + std::vector m_iterators; + size_t m_activeIterators; + + iterator( Columns const& columns, EndTag ) + : m_columns( columns.m_columns ), + m_activeIterators( 0 ) + { + m_iterators.reserve( m_columns.size() ); + + for( auto const& col : m_columns ) + m_iterators.push_back( col.end() ); + } + + public: + explicit iterator( Columns const& columns ) + : m_columns( columns.m_columns ), + m_activeIterators( m_columns.size() ) + { + m_iterators.reserve( m_columns.size() ); + + for( auto const& col : m_columns ) + m_iterators.push_back( col.begin() ); + } + + auto operator ==( iterator const& other ) const -> bool { + return m_iterators == other.m_iterators; + } + auto operator !=( iterator const& other ) const -> bool { + return m_iterators != other.m_iterators; + } + auto operator *() const -> std::string { + std::string row, padding; + + for( size_t i = 0; i < m_columns.size(); ++i ) { + auto width = m_columns[i].width(); + if( m_iterators[i] != m_columns[i].end() ) { + std::string col = *m_iterators[i]; + row += padding + col; + if( col.size() < width ) + padding = std::string( width - col.size(), ' ' ); + else + padding = ""; + } + else { + padding += std::string( width, ' ' ); + } + } + return row; + } + auto operator ++() -> iterator& { + for( size_t i = 0; i < m_columns.size(); ++i ) { + if (m_iterators[i] != m_columns[i].end()) + ++m_iterators[i]; + } + return *this; + } + auto operator ++(int) -> iterator { + iterator prev( *this ); + operator++(); + return prev; + } + }; + using const_iterator = iterator; + + auto begin() const -> iterator { return iterator( *this ); } + auto end() const -> iterator { return { *this, iterator::EndTag() }; } + + auto operator += ( Column const& col ) -> Columns& { + m_columns.push_back( col ); + return *this; + } + auto operator + ( Column const& col ) -> Columns { + Columns combined = *this; + combined += col; + return combined; + } + + inline friend std::ostream& operator << ( std::ostream& os, Columns const& cols ) { + + bool first = true; + for( auto line : cols ) { + if( first ) + first = false; + else + os << "\n"; + os << line; + } + return os; + } + + auto toString() const -> std::string { + std::ostringstream oss; + oss << *this; + return oss.str(); + } + }; + + inline auto Column::operator + ( Column const& other ) -> Columns { + Columns cols; + cols += *this; + cols += other; + return cols; + } +}}} // namespace Catch::clara::TextFlow + +// ----------- end of #include from clara_textflow.hpp ----------- +// ........... back in clara.hpp + +#include +#include +#include + +#if !defined(CATCH_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) ) +#define CATCH_PLATFORM_WINDOWS +#endif + +namespace Catch { namespace clara { +namespace detail { + + // Traits for extracting arg and return type of lambdas (for single argument lambdas) + template + struct UnaryLambdaTraits : UnaryLambdaTraits {}; + + template + struct UnaryLambdaTraits { + static const bool isValid = false; + }; + + template + struct UnaryLambdaTraits { + static const bool isValid = true; + using ArgType = typename std::remove_const::type>::type; + using ReturnType = ReturnT; + }; + + class TokenStream; + + // Transport for raw args (copied from main args, or supplied via init list for testing) + class Args { + friend TokenStream; + std::string m_exeName; + std::vector m_args; + + public: + Args( int argc, char const* const* argv ) + : m_exeName(argv[0]), + m_args(argv + 1, argv + argc) {} + + Args( std::initializer_list args ) + : m_exeName( *args.begin() ), + m_args( args.begin()+1, args.end() ) + {} + + auto exeName() const -> std::string { + return m_exeName; + } + }; + + // Wraps a token coming from a token stream. These may not directly correspond to strings as a single string + // may encode an option + its argument if the : or = form is used + enum class TokenType { + Option, Argument + }; + struct Token { + TokenType type; + std::string token; + }; + + inline auto isOptPrefix( char c ) -> bool { + return c == '-' +#ifdef CATCH_PLATFORM_WINDOWS + || c == '/' +#endif + ; + } + + // Abstracts iterators into args as a stream of tokens, with option arguments uniformly handled + class TokenStream { + using Iterator = std::vector::const_iterator; + Iterator it; + Iterator itEnd; + std::vector m_tokenBuffer; + + void loadBuffer() { + m_tokenBuffer.resize( 0 ); + + // Skip any empty strings + while( it != itEnd && it->empty() ) + ++it; + + if( it != itEnd ) { + auto const &next = *it; + if( isOptPrefix( next[0] ) ) { + auto delimiterPos = next.find_first_of( " :=" ); + if( delimiterPos != std::string::npos ) { + m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } ); + m_tokenBuffer.push_back( { TokenType::Argument, next.substr( delimiterPos + 1 ) } ); + } else { + if( next[1] != '-' && next.size() > 2 ) { + std::string opt = "- "; + for( size_t i = 1; i < next.size(); ++i ) { + opt[1] = next[i]; + m_tokenBuffer.push_back( { TokenType::Option, opt } ); + } + } else { + m_tokenBuffer.push_back( { TokenType::Option, next } ); + } + } + } else { + m_tokenBuffer.push_back( { TokenType::Argument, next } ); + } + } + } + + public: + explicit TokenStream( Args const &args ) : TokenStream( args.m_args.begin(), args.m_args.end() ) {} + + TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) { + loadBuffer(); + } + + explicit operator bool() const { + return !m_tokenBuffer.empty() || it != itEnd; + } + + auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); } + + auto operator*() const -> Token { + assert( !m_tokenBuffer.empty() ); + return m_tokenBuffer.front(); + } + + auto operator->() const -> Token const * { + assert( !m_tokenBuffer.empty() ); + return &m_tokenBuffer.front(); + } + + auto operator++() -> TokenStream & { + if( m_tokenBuffer.size() >= 2 ) { + m_tokenBuffer.erase( m_tokenBuffer.begin() ); + } else { + if( it != itEnd ) + ++it; + loadBuffer(); + } + return *this; + } + }; + + class ResultBase { + public: + enum Type { + Ok, LogicError, RuntimeError + }; + + protected: + ResultBase( Type type ) : m_type( type ) {} + virtual ~ResultBase() = default; + + virtual void enforceOk() const = 0; + + Type m_type; + }; + + template + class ResultValueBase : public ResultBase { + public: + auto value() const -> T const & { + enforceOk(); + return m_value; + } + + protected: + ResultValueBase( Type type ) : ResultBase( type ) {} + + ResultValueBase( ResultValueBase const &other ) : ResultBase( other ) { + if( m_type == ResultBase::Ok ) + new( &m_value ) T( other.m_value ); + } + + ResultValueBase( Type, T const &value ) : ResultBase( Ok ) { + new( &m_value ) T( value ); + } + + auto operator=( ResultValueBase const &other ) -> ResultValueBase & { + if( m_type == ResultBase::Ok ) + m_value.~T(); + ResultBase::operator=(other); + if( m_type == ResultBase::Ok ) + new( &m_value ) T( other.m_value ); + return *this; + } + + ~ResultValueBase() override { + if( m_type == Ok ) + m_value.~T(); + } + + union { + T m_value; + }; + }; + + template<> + class ResultValueBase : public ResultBase { + protected: + using ResultBase::ResultBase; + }; + + template + class BasicResult : public ResultValueBase { + public: + template + explicit BasicResult( BasicResult const &other ) + : ResultValueBase( other.type() ), + m_errorMessage( other.errorMessage() ) + { + assert( type() != ResultBase::Ok ); + } + + template + static auto ok( U const &value ) -> BasicResult { return { ResultBase::Ok, value }; } + static auto ok() -> BasicResult { return { ResultBase::Ok }; } + static auto logicError( std::string const &message ) -> BasicResult { return { ResultBase::LogicError, message }; } + static auto runtimeError( std::string const &message ) -> BasicResult { return { ResultBase::RuntimeError, message }; } + + explicit operator bool() const { return m_type == ResultBase::Ok; } + auto type() const -> ResultBase::Type { return m_type; } + auto errorMessage() const -> std::string { return m_errorMessage; } + + protected: + void enforceOk() const override { + + // Errors shouldn't reach this point, but if they do + // the actual error message will be in m_errorMessage + assert( m_type != ResultBase::LogicError ); + assert( m_type != ResultBase::RuntimeError ); + if( m_type != ResultBase::Ok ) + std::abort(); + } + + std::string m_errorMessage; // Only populated if resultType is an error + + BasicResult( ResultBase::Type type, std::string const &message ) + : ResultValueBase(type), + m_errorMessage(message) + { + assert( m_type != ResultBase::Ok ); + } + + using ResultValueBase::ResultValueBase; + using ResultBase::m_type; + }; + + enum class ParseResultType { + Matched, NoMatch, ShortCircuitAll, ShortCircuitSame + }; + + class ParseState { + public: + + ParseState( ParseResultType type, TokenStream const &remainingTokens ) + : m_type(type), + m_remainingTokens( remainingTokens ) + {} + + auto type() const -> ParseResultType { return m_type; } + auto remainingTokens() const -> TokenStream { return m_remainingTokens; } + + private: + ParseResultType m_type; + TokenStream m_remainingTokens; + }; + + using Result = BasicResult; + using ParserResult = BasicResult; + using InternalParseResult = BasicResult; + + struct HelpColumns { + std::string left; + std::string right; + }; + + template + inline auto convertInto( std::string const &source, T& target ) -> ParserResult { + std::stringstream ss; + ss << source; + ss >> target; + if( ss.fail() ) + return ParserResult::runtimeError( "Unable to convert '" + source + "' to destination type" ); + else + return ParserResult::ok( ParseResultType::Matched ); + } + inline auto convertInto( std::string const &source, std::string& target ) -> ParserResult { + target = source; + return ParserResult::ok( ParseResultType::Matched ); + } + inline auto convertInto( std::string const &source, bool &target ) -> ParserResult { + std::string srcLC = source; + std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( char c ) { return static_cast( ::tolower(c) ); } ); + if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on") + target = true; + else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off") + target = false; + else + return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" ); + return ParserResult::ok( ParseResultType::Matched ); + } +#ifdef CLARA_CONFIG_OPTIONAL_TYPE + template + inline auto convertInto( std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE& target ) -> ParserResult { + T temp; + auto result = convertInto( source, temp ); + if( result ) + target = std::move(temp); + return result; + } +#endif // CLARA_CONFIG_OPTIONAL_TYPE + + struct NonCopyable { + NonCopyable() = default; + NonCopyable( NonCopyable const & ) = delete; + NonCopyable( NonCopyable && ) = delete; + NonCopyable &operator=( NonCopyable const & ) = delete; + NonCopyable &operator=( NonCopyable && ) = delete; + }; + + struct BoundRef : NonCopyable { + virtual ~BoundRef() = default; + virtual auto isContainer() const -> bool { return false; } + virtual auto isFlag() const -> bool { return false; } + }; + struct BoundValueRefBase : BoundRef { + virtual auto setValue( std::string const &arg ) -> ParserResult = 0; + }; + struct BoundFlagRefBase : BoundRef { + virtual auto setFlag( bool flag ) -> ParserResult = 0; + virtual auto isFlag() const -> bool { return true; } + }; + + template + struct BoundValueRef : BoundValueRefBase { + T &m_ref; + + explicit BoundValueRef( T &ref ) : m_ref( ref ) {} + + auto setValue( std::string const &arg ) -> ParserResult override { + return convertInto( arg, m_ref ); + } + }; + + template + struct BoundValueRef> : BoundValueRefBase { + std::vector &m_ref; + + explicit BoundValueRef( std::vector &ref ) : m_ref( ref ) {} + + auto isContainer() const -> bool override { return true; } + + auto setValue( std::string const &arg ) -> ParserResult override { + T temp; + auto result = convertInto( arg, temp ); + if( result ) + m_ref.push_back( temp ); + return result; + } + }; + + struct BoundFlagRef : BoundFlagRefBase { + bool &m_ref; + + explicit BoundFlagRef( bool &ref ) : m_ref( ref ) {} + + auto setFlag( bool flag ) -> ParserResult override { + m_ref = flag; + return ParserResult::ok( ParseResultType::Matched ); + } + }; + + template + struct LambdaInvoker { + static_assert( std::is_same::value, "Lambda must return void or clara::ParserResult" ); + + template + static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult { + return lambda( arg ); + } + }; + + template<> + struct LambdaInvoker { + template + static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult { + lambda( arg ); + return ParserResult::ok( ParseResultType::Matched ); + } + }; + + template + inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult { + ArgType temp{}; + auto result = convertInto( arg, temp ); + return !result + ? result + : LambdaInvoker::ReturnType>::invoke( lambda, temp ); + } + + template + struct BoundLambda : BoundValueRefBase { + L m_lambda; + + static_assert( UnaryLambdaTraits::isValid, "Supplied lambda must take exactly one argument" ); + explicit BoundLambda( L const &lambda ) : m_lambda( lambda ) {} + + auto setValue( std::string const &arg ) -> ParserResult override { + return invokeLambda::ArgType>( m_lambda, arg ); + } + }; + + template + struct BoundFlagLambda : BoundFlagRefBase { + L m_lambda; + + static_assert( UnaryLambdaTraits::isValid, "Supplied lambda must take exactly one argument" ); + static_assert( std::is_same::ArgType, bool>::value, "flags must be boolean" ); + + explicit BoundFlagLambda( L const &lambda ) : m_lambda( lambda ) {} + + auto setFlag( bool flag ) -> ParserResult override { + return LambdaInvoker::ReturnType>::invoke( m_lambda, flag ); + } + }; + + enum class Optionality { Optional, Required }; + + struct Parser; + + class ParserBase { + public: + virtual ~ParserBase() = default; + virtual auto validate() const -> Result { return Result::ok(); } + virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult = 0; + virtual auto cardinality() const -> size_t { return 1; } + + auto parse( Args const &args ) const -> InternalParseResult { + return parse( args.exeName(), TokenStream( args ) ); + } + }; + + template + class ComposableParserImpl : public ParserBase { + public: + template + auto operator|( T const &other ) const -> Parser; + + template + auto operator+( T const &other ) const -> Parser; + }; + + // Common code and state for Args and Opts + template + class ParserRefImpl : public ComposableParserImpl { + protected: + Optionality m_optionality = Optionality::Optional; + std::shared_ptr m_ref; + std::string m_hint; + std::string m_description; + + explicit ParserRefImpl( std::shared_ptr const &ref ) : m_ref( ref ) {} + + public: + template + ParserRefImpl( T &ref, std::string const &hint ) + : m_ref( std::make_shared>( ref ) ), + m_hint( hint ) + {} + + template + ParserRefImpl( LambdaT const &ref, std::string const &hint ) + : m_ref( std::make_shared>( ref ) ), + m_hint(hint) + {} + + auto operator()( std::string const &description ) -> DerivedT & { + m_description = description; + return static_cast( *this ); + } + + auto optional() -> DerivedT & { + m_optionality = Optionality::Optional; + return static_cast( *this ); + }; + + auto required() -> DerivedT & { + m_optionality = Optionality::Required; + return static_cast( *this ); + }; + + auto isOptional() const -> bool { + return m_optionality == Optionality::Optional; + } + + auto cardinality() const -> size_t override { + if( m_ref->isContainer() ) + return 0; + else + return 1; + } + + auto hint() const -> std::string { return m_hint; } + }; + + class ExeName : public ComposableParserImpl { + std::shared_ptr m_name; + std::shared_ptr m_ref; + + template + static auto makeRef(LambdaT const &lambda) -> std::shared_ptr { + return std::make_shared>( lambda) ; + } + + public: + ExeName() : m_name( std::make_shared( "" ) ) {} + + explicit ExeName( std::string &ref ) : ExeName() { + m_ref = std::make_shared>( ref ); + } + + template + explicit ExeName( LambdaT const& lambda ) : ExeName() { + m_ref = std::make_shared>( lambda ); + } + + // The exe name is not parsed out of the normal tokens, but is handled specially + auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { + return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) ); + } + + auto name() const -> std::string { return *m_name; } + auto set( std::string const& newName ) -> ParserResult { + + auto lastSlash = newName.find_last_of( "\\/" ); + auto filename = ( lastSlash == std::string::npos ) + ? newName + : newName.substr( lastSlash+1 ); + + *m_name = filename; + if( m_ref ) + return m_ref->setValue( filename ); + else + return ParserResult::ok( ParseResultType::Matched ); + } + }; + + class Arg : public ParserRefImpl { + public: + using ParserRefImpl::ParserRefImpl; + + auto parse( std::string const &, TokenStream const &tokens ) const -> InternalParseResult override { + auto validationResult = validate(); + if( !validationResult ) + return InternalParseResult( validationResult ); + + auto remainingTokens = tokens; + auto const &token = *remainingTokens; + if( token.type != TokenType::Argument ) + return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) ); + + assert( !m_ref->isFlag() ); + auto valueRef = static_cast( m_ref.get() ); + + auto result = valueRef->setValue( remainingTokens->token ); + if( !result ) + return InternalParseResult( result ); + else + return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) ); + } + }; + + inline auto normaliseOpt( std::string const &optName ) -> std::string { +#ifdef CATCH_PLATFORM_WINDOWS + if( optName[0] == '/' ) + return "-" + optName.substr( 1 ); + else +#endif + return optName; + } + + class Opt : public ParserRefImpl { + protected: + std::vector m_optNames; + + public: + template + explicit Opt( LambdaT const &ref ) : ParserRefImpl( std::make_shared>( ref ) ) {} + + explicit Opt( bool &ref ) : ParserRefImpl( std::make_shared( ref ) ) {} + + template + Opt( LambdaT const &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} + + template + Opt( T &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {} + + auto operator[]( std::string const &optName ) -> Opt & { + m_optNames.push_back( optName ); + return *this; + } + + auto getHelpColumns() const -> std::vector { + std::ostringstream oss; + bool first = true; + for( auto const &opt : m_optNames ) { + if (first) + first = false; + else + oss << ", "; + oss << opt; + } + if( !m_hint.empty() ) + oss << " <" << m_hint << ">"; + return { { oss.str(), m_description } }; + } + + auto isMatch( std::string const &optToken ) const -> bool { + auto normalisedToken = normaliseOpt( optToken ); + for( auto const &name : m_optNames ) { + if( normaliseOpt( name ) == normalisedToken ) + return true; + } + return false; + } + + using ParserBase::parse; + + auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override { + auto validationResult = validate(); + if( !validationResult ) + return InternalParseResult( validationResult ); + + auto remainingTokens = tokens; + if( remainingTokens && remainingTokens->type == TokenType::Option ) { + auto const &token = *remainingTokens; + if( isMatch(token.token ) ) { + if( m_ref->isFlag() ) { + auto flagRef = static_cast( m_ref.get() ); + auto result = flagRef->setFlag( true ); + if( !result ) + return InternalParseResult( result ); + if( result.value() == ParseResultType::ShortCircuitAll ) + return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); + } else { + auto valueRef = static_cast( m_ref.get() ); + ++remainingTokens; + if( !remainingTokens ) + return InternalParseResult::runtimeError( "Expected argument following " + token.token ); + auto const &argToken = *remainingTokens; + if( argToken.type != TokenType::Argument ) + return InternalParseResult::runtimeError( "Expected argument following " + token.token ); + auto result = valueRef->setValue( argToken.token ); + if( !result ) + return InternalParseResult( result ); + if( result.value() == ParseResultType::ShortCircuitAll ) + return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) ); + } + return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) ); + } + } + return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) ); + } + + auto validate() const -> Result override { + if( m_optNames.empty() ) + return Result::logicError( "No options supplied to Opt" ); + for( auto const &name : m_optNames ) { + if( name.empty() ) + return Result::logicError( "Option name cannot be empty" ); +#ifdef CATCH_PLATFORM_WINDOWS + if( name[0] != '-' && name[0] != '/' ) + return Result::logicError( "Option name must begin with '-' or '/'" ); +#else + if( name[0] != '-' ) + return Result::logicError( "Option name must begin with '-'" ); +#endif + } + return ParserRefImpl::validate(); + } + }; + + struct Help : Opt { + Help( bool &showHelpFlag ) + : Opt([&]( bool flag ) { + showHelpFlag = flag; + return ParserResult::ok( ParseResultType::ShortCircuitAll ); + }) + { + static_cast( *this ) + ("display usage information") + ["-?"]["-h"]["--help"] + .optional(); + } + }; + + struct Parser : ParserBase { + + mutable ExeName m_exeName; + std::vector m_options; + std::vector m_args; + + auto operator|=( ExeName const &exeName ) -> Parser & { + m_exeName = exeName; + return *this; + } + + auto operator|=( Arg const &arg ) -> Parser & { + m_args.push_back(arg); + return *this; + } + + auto operator|=( Opt const &opt ) -> Parser & { + m_options.push_back(opt); + return *this; + } + + auto operator|=( Parser const &other ) -> Parser & { + m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end()); + m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end()); + return *this; + } + + template + auto operator|( T const &other ) const -> Parser { + return Parser( *this ) |= other; + } + + // Forward deprecated interface with '+' instead of '|' + template + auto operator+=( T const &other ) -> Parser & { return operator|=( other ); } + template + auto operator+( T const &other ) const -> Parser { return operator|( other ); } + + auto getHelpColumns() const -> std::vector { + std::vector cols; + for (auto const &o : m_options) { + auto childCols = o.getHelpColumns(); + cols.insert( cols.end(), childCols.begin(), childCols.end() ); + } + return cols; + } + + void writeToStream( std::ostream &os ) const { + if (!m_exeName.name().empty()) { + os << "usage:\n" << " " << m_exeName.name() << " "; + bool required = true, first = true; + for( auto const &arg : m_args ) { + if (first) + first = false; + else + os << " "; + if( arg.isOptional() && required ) { + os << "["; + required = false; + } + os << "<" << arg.hint() << ">"; + if( arg.cardinality() == 0 ) + os << " ... "; + } + if( !required ) + os << "]"; + if( !m_options.empty() ) + os << " options"; + os << "\n\nwhere options are:" << std::endl; + } + + auto rows = getHelpColumns(); + size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH; + size_t optWidth = 0; + for( auto const &cols : rows ) + optWidth = (std::max)(optWidth, cols.left.size() + 2); + + optWidth = (std::min)(optWidth, consoleWidth/2); + + for( auto const &cols : rows ) { + auto row = + TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) + + TextFlow::Spacer(4) + + TextFlow::Column( cols.right ).width( consoleWidth - 7 - optWidth ); + os << row << std::endl; + } + } + + friend auto operator<<( std::ostream &os, Parser const &parser ) -> std::ostream& { + parser.writeToStream( os ); + return os; + } + + auto validate() const -> Result override { + for( auto const &opt : m_options ) { + auto result = opt.validate(); + if( !result ) + return result; + } + for( auto const &arg : m_args ) { + auto result = arg.validate(); + if( !result ) + return result; + } + return Result::ok(); + } + + using ParserBase::parse; + + auto parse( std::string const& exeName, TokenStream const &tokens ) const -> InternalParseResult override { + + struct ParserInfo { + ParserBase const* parser = nullptr; + size_t count = 0; + }; + const size_t totalParsers = m_options.size() + m_args.size(); + assert( totalParsers < 512 ); + // ParserInfo parseInfos[totalParsers]; // <-- this is what we really want to do + ParserInfo parseInfos[512]; + + { + size_t i = 0; + for (auto const &opt : m_options) parseInfos[i++].parser = &opt; + for (auto const &arg : m_args) parseInfos[i++].parser = &arg; + } + + m_exeName.set( exeName ); + + auto result = InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) ); + while( result.value().remainingTokens() ) { + bool tokenParsed = false; + + for( size_t i = 0; i < totalParsers; ++i ) { + auto& parseInfo = parseInfos[i]; + if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) { + result = parseInfo.parser->parse(exeName, result.value().remainingTokens()); + if (!result) + return result; + if (result.value().type() != ParseResultType::NoMatch) { + tokenParsed = true; + ++parseInfo.count; + break; + } + } + } + + if( result.value().type() == ParseResultType::ShortCircuitAll ) + return result; + if( !tokenParsed ) + return InternalParseResult::runtimeError( "Unrecognised token: " + result.value().remainingTokens()->token ); + } + // !TBD Check missing required options + return result; + } + }; + + template + template + auto ComposableParserImpl::operator|( T const &other ) const -> Parser { + return Parser() | static_cast( *this ) | other; + } +} // namespace detail + +// A Combined parser +using detail::Parser; + +// A parser for options +using detail::Opt; + +// A parser for arguments +using detail::Arg; + +// Wrapper for argc, argv from main() +using detail::Args; + +// Specifies the name of the executable +using detail::ExeName; + +// Convenience wrapper for option parser that specifies the help option +using detail::Help; + +// enum of result types from a parse +using detail::ParseResultType; + +// Result type for parser operation +using detail::ParserResult; + +}} // namespace Catch::clara + +// end clara.hpp +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// Restore Clara's value for console width, if present +#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH +#endif + +// end catch_clara.h +namespace Catch { + + clara::Parser makeCommandLineParser( ConfigData& config ); + +} // end namespace Catch + +// end catch_commandline.h +#include +#include + +namespace Catch { + + clara::Parser makeCommandLineParser( ConfigData& config ) { + + using namespace clara; + + auto const setWarning = [&]( std::string const& warning ) { + auto warningSet = [&]() { + if( warning == "NoAssertions" ) + return WarnAbout::NoAssertions; + + if ( warning == "NoTests" ) + return WarnAbout::NoTests; + + return WarnAbout::Nothing; + }(); + + if (warningSet == WarnAbout::Nothing) + return ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" ); + config.warnings = static_cast( config.warnings | warningSet ); + return ParserResult::ok( ParseResultType::Matched ); + }; + auto const loadTestNamesFromFile = [&]( std::string const& filename ) { + std::ifstream f( filename.c_str() ); + if( !f.is_open() ) + return ParserResult::runtimeError( "Unable to load input file: '" + filename + "'" ); + + std::string line; + while( std::getline( f, line ) ) { + line = trim(line); + if( !line.empty() && !startsWith( line, '#' ) ) { + if( !startsWith( line, '"' ) ) + line = '"' + line + '"'; + config.testsOrTags.push_back( line + ',' ); + } + } + return ParserResult::ok( ParseResultType::Matched ); + }; + auto const setTestOrder = [&]( std::string const& order ) { + if( startsWith( "declared", order ) ) + config.runOrder = RunTests::InDeclarationOrder; + else if( startsWith( "lexical", order ) ) + config.runOrder = RunTests::InLexicographicalOrder; + else if( startsWith( "random", order ) ) + config.runOrder = RunTests::InRandomOrder; + else + return clara::ParserResult::runtimeError( "Unrecognised ordering: '" + order + "'" ); + return ParserResult::ok( ParseResultType::Matched ); + }; + auto const setRngSeed = [&]( std::string const& seed ) { + if( seed != "time" ) + return clara::detail::convertInto( seed, config.rngSeed ); + config.rngSeed = static_cast( std::time(nullptr) ); + return ParserResult::ok( ParseResultType::Matched ); + }; + auto const setColourUsage = [&]( std::string const& useColour ) { + auto mode = toLower( useColour ); + + if( mode == "yes" ) + config.useColour = UseColour::Yes; + else if( mode == "no" ) + config.useColour = UseColour::No; + else if( mode == "auto" ) + config.useColour = UseColour::Auto; + else + return ParserResult::runtimeError( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" ); + return ParserResult::ok( ParseResultType::Matched ); + }; + auto const setWaitForKeypress = [&]( std::string const& keypress ) { + auto keypressLc = toLower( keypress ); + if( keypressLc == "start" ) + config.waitForKeypress = WaitForKeypress::BeforeStart; + else if( keypressLc == "exit" ) + config.waitForKeypress = WaitForKeypress::BeforeExit; + else if( keypressLc == "both" ) + config.waitForKeypress = WaitForKeypress::BeforeStartAndExit; + else + return ParserResult::runtimeError( "keypress argument must be one of: start, exit or both. '" + keypress + "' not recognised" ); + return ParserResult::ok( ParseResultType::Matched ); + }; + auto const setVerbosity = [&]( std::string const& verbosity ) { + auto lcVerbosity = toLower( verbosity ); + if( lcVerbosity == "quiet" ) + config.verbosity = Verbosity::Quiet; + else if( lcVerbosity == "normal" ) + config.verbosity = Verbosity::Normal; + else if( lcVerbosity == "high" ) + config.verbosity = Verbosity::High; + else + return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + "'" ); + return ParserResult::ok( ParseResultType::Matched ); + }; + + auto cli + = ExeName( config.processName ) + | Help( config.showHelp ) + | Opt( config.listTests ) + ["-l"]["--list-tests"] + ( "list all/matching test cases" ) + | Opt( config.listTags ) + ["-t"]["--list-tags"] + ( "list all/matching tags" ) + | Opt( config.showSuccessfulTests ) + ["-s"]["--success"] + ( "include successful tests in output" ) + | Opt( config.shouldDebugBreak ) + ["-b"]["--break"] + ( "break into debugger on failure" ) + | Opt( config.noThrow ) + ["-e"]["--nothrow"] + ( "skip exception tests" ) + | Opt( config.showInvisibles ) + ["-i"]["--invisibles"] + ( "show invisibles (tabs, newlines)" ) + | Opt( config.outputFilename, "filename" ) + ["-o"]["--out"] + ( "output filename" ) + | Opt( config.reporterName, "name" ) + ["-r"]["--reporter"] + ( "reporter to use (defaults to console)" ) + | Opt( config.name, "name" ) + ["-n"]["--name"] + ( "suite name" ) + | Opt( [&]( bool ){ config.abortAfter = 1; } ) + ["-a"]["--abort"] + ( "abort at first failure" ) + | Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" ) + ["-x"]["--abortx"] + ( "abort after x failures" ) + | Opt( setWarning, "warning name" ) + ["-w"]["--warn"] + ( "enable warnings" ) + | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" ) + ["-d"]["--durations"] + ( "show test durations" ) + | Opt( loadTestNamesFromFile, "filename" ) + ["-f"]["--input-file"] + ( "load test names to run from a file" ) + | Opt( config.filenamesAsTags ) + ["-#"]["--filenames-as-tags"] + ( "adds a tag for the filename" ) + | Opt( config.sectionsToRun, "section name" ) + ["-c"]["--section"] + ( "specify section to run" ) + | Opt( setVerbosity, "quiet|normal|high" ) + ["-v"]["--verbosity"] + ( "set output verbosity" ) + | Opt( config.listTestNamesOnly ) + ["--list-test-names-only"] + ( "list all/matching test cases names only" ) + | Opt( config.listReporters ) + ["--list-reporters"] + ( "list all reporters" ) + | Opt( setTestOrder, "decl|lex|rand" ) + ["--order"] + ( "test case order (defaults to decl)" ) + | Opt( setRngSeed, "'time'|number" ) + ["--rng-seed"] + ( "set a specific seed for random numbers" ) + | Opt( setColourUsage, "yes|no" ) + ["--use-colour"] + ( "should output be colourised" ) + | Opt( config.libIdentify ) + ["--libidentify"] + ( "report name and version according to libidentify standard" ) + | Opt( setWaitForKeypress, "start|exit|both" ) + ["--wait-for-keypress"] + ( "waits for a keypress before exiting" ) + | Opt( config.benchmarkResolutionMultiple, "multiplier" ) + ["--benchmark-resolution-multiple"] + ( "multiple of clock resolution to run benchmarks" ) + + | Arg( config.testsOrTags, "test name|pattern|tags" ) + ( "which test or tests to use" ); + + return cli; + } + +} // end namespace Catch +// end catch_commandline.cpp +// start catch_common.cpp + +#include +#include + +namespace Catch { + + bool SourceLineInfo::empty() const noexcept { + return file[0] == '\0'; + } + bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const noexcept { + return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0); + } + bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const noexcept { + return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0)); + } + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { +#ifndef __GNUG__ + os << info.file << '(' << info.line << ')'; +#else + os << info.file << ':' << info.line; +#endif + return os; + } + + std::string StreamEndStop::operator+() const { + return std::string(); + } + + NonCopyable::NonCopyable() = default; + NonCopyable::~NonCopyable() = default; + +} +// end catch_common.cpp +// start catch_config.cpp + +// start catch_enforce.h + +#include + +#define CATCH_PREPARE_EXCEPTION( type, msg ) \ + type( ( Catch::ReusableStringStream() << msg ).str() ) +#define CATCH_INTERNAL_ERROR( msg ) \ + throw CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg); +#define CATCH_ERROR( msg ) \ + throw CATCH_PREPARE_EXCEPTION( std::domain_error, msg ) +#define CATCH_ENFORCE( condition, msg ) \ + do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false) + +// end catch_enforce.h +namespace Catch { + + Config::Config( ConfigData const& data ) + : m_data( data ), + m_stream( openStream() ) + { + TestSpecParser parser(ITagAliasRegistry::get()); + if (data.testsOrTags.empty()) { + parser.parse("~[.]"); // All not hidden tests + } + else { + m_hasTestFilters = true; + for( auto const& testOrTags : data.testsOrTags ) + parser.parse( testOrTags ); + } + m_testSpec = parser.testSpec(); + } + + std::string const& Config::getFilename() const { + return m_data.outputFilename ; + } + + bool Config::listTests() const { return m_data.listTests; } + bool Config::listTestNamesOnly() const { return m_data.listTestNamesOnly; } + bool Config::listTags() const { return m_data.listTags; } + bool Config::listReporters() const { return m_data.listReporters; } + + std::string Config::getProcessName() const { return m_data.processName; } + std::string const& Config::getReporterName() const { return m_data.reporterName; } + + std::vector const& Config::getTestsOrTags() const { return m_data.testsOrTags; } + std::vector const& Config::getSectionsToRun() const { return m_data.sectionsToRun; } + + TestSpec const& Config::testSpec() const { return m_testSpec; } + bool Config::hasTestFilters() const { return m_hasTestFilters; } + + bool Config::showHelp() const { return m_data.showHelp; } + + // IConfig interface + bool Config::allowThrows() const { return !m_data.noThrow; } + std::ostream& Config::stream() const { return m_stream->stream(); } + std::string Config::name() const { return m_data.name.empty() ? m_data.processName : m_data.name; } + bool Config::includeSuccessfulResults() const { return m_data.showSuccessfulTests; } + bool Config::warnAboutMissingAssertions() const { return !!(m_data.warnings & WarnAbout::NoAssertions); } + bool Config::warnAboutNoTests() const { return !!(m_data.warnings & WarnAbout::NoTests); } + ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; } + RunTests::InWhatOrder Config::runOrder() const { return m_data.runOrder; } + unsigned int Config::rngSeed() const { return m_data.rngSeed; } + int Config::benchmarkResolutionMultiple() const { return m_data.benchmarkResolutionMultiple; } + UseColour::YesOrNo Config::useColour() const { return m_data.useColour; } + bool Config::shouldDebugBreak() const { return m_data.shouldDebugBreak; } + int Config::abortAfter() const { return m_data.abortAfter; } + bool Config::showInvisibles() const { return m_data.showInvisibles; } + Verbosity Config::verbosity() const { return m_data.verbosity; } + + IStream const* Config::openStream() { + return Catch::makeStream(m_data.outputFilename); + } + +} // end namespace Catch +// end catch_config.cpp +// start catch_console_colour.cpp + +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wexit-time-destructors" +#endif + +// start catch_errno_guard.h + +namespace Catch { + + class ErrnoGuard { + public: + ErrnoGuard(); + ~ErrnoGuard(); + private: + int m_oldErrno; + }; + +} + +// end catch_errno_guard.h +#include + +namespace Catch { + namespace { + + struct IColourImpl { + virtual ~IColourImpl() = default; + virtual void use( Colour::Code _colourCode ) = 0; + }; + + struct NoColourImpl : IColourImpl { + void use( Colour::Code ) {} + + static IColourImpl* instance() { + static NoColourImpl s_instance; + return &s_instance; + } + }; + + } // anon namespace +} // namespace Catch + +#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) +# ifdef CATCH_PLATFORM_WINDOWS +# define CATCH_CONFIG_COLOUR_WINDOWS +# else +# define CATCH_CONFIG_COLOUR_ANSI +# endif +#endif + +#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// + +namespace Catch { +namespace { + + class Win32ColourImpl : public IColourImpl { + public: + Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) + { + CONSOLE_SCREEN_BUFFER_INFO csbiInfo; + GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); + originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); + originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); + } + + virtual void use( Colour::Code _colourCode ) override { + switch( _colourCode ) { + case Colour::None: return setTextAttribute( originalForegroundAttributes ); + case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + case Colour::Red: return setTextAttribute( FOREGROUND_RED ); + case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); + case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); + case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); + case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); + case Colour::Grey: return setTextAttribute( 0 ); + + case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); + case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); + case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); + case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); + case Colour::BrightYellow: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN ); + + case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" ); + + default: + CATCH_ERROR( "Unknown colour requested" ); + } + } + + private: + void setTextAttribute( WORD _textAttribute ) { + SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); + } + HANDLE stdoutHandle; + WORD originalForegroundAttributes; + WORD originalBackgroundAttributes; + }; + + IColourImpl* platformColourInstance() { + static Win32ColourImpl s_instance; + + IConfigPtr config = getCurrentContext().getConfig(); + UseColour::YesOrNo colourMode = config + ? config->useColour() + : UseColour::Auto; + if( colourMode == UseColour::Auto ) + colourMode = UseColour::Yes; + return colourMode == UseColour::Yes + ? &s_instance + : NoColourImpl::instance(); + } + +} // end anon namespace +} // end namespace Catch + +#elif defined( CATCH_CONFIG_COLOUR_ANSI ) ////////////////////////////////////// + +#include + +namespace Catch { +namespace { + + // use POSIX/ ANSI console terminal codes + // Thanks to Adam Strzelecki for original contribution + // (http://github.com/nanoant) + // https://github.com/philsquared/Catch/pull/131 + class PosixColourImpl : public IColourImpl { + public: + virtual void use( Colour::Code _colourCode ) override { + switch( _colourCode ) { + case Colour::None: + case Colour::White: return setColour( "[0m" ); + case Colour::Red: return setColour( "[0;31m" ); + case Colour::Green: return setColour( "[0;32m" ); + case Colour::Blue: return setColour( "[0;34m" ); + case Colour::Cyan: return setColour( "[0;36m" ); + case Colour::Yellow: return setColour( "[0;33m" ); + case Colour::Grey: return setColour( "[1;30m" ); + + case Colour::LightGrey: return setColour( "[0;37m" ); + case Colour::BrightRed: return setColour( "[1;31m" ); + case Colour::BrightGreen: return setColour( "[1;32m" ); + case Colour::BrightWhite: return setColour( "[1;37m" ); + case Colour::BrightYellow: return setColour( "[1;33m" ); + + case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" ); + default: CATCH_INTERNAL_ERROR( "Unknown colour requested" ); + } + } + static IColourImpl* instance() { + static PosixColourImpl s_instance; + return &s_instance; + } + + private: + void setColour( const char* _escapeCode ) { + Catch::cout() << '\033' << _escapeCode; + } + }; + + bool useColourOnPlatform() { + return +#ifdef CATCH_PLATFORM_MAC + !isDebuggerActive() && +#endif +#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__)) + isatty(STDOUT_FILENO) +#else + false +#endif + ; + } + IColourImpl* platformColourInstance() { + ErrnoGuard guard; + IConfigPtr config = getCurrentContext().getConfig(); + UseColour::YesOrNo colourMode = config + ? config->useColour() + : UseColour::Auto; + if( colourMode == UseColour::Auto ) + colourMode = useColourOnPlatform() + ? UseColour::Yes + : UseColour::No; + return colourMode == UseColour::Yes + ? PosixColourImpl::instance() + : NoColourImpl::instance(); + } + +} // end anon namespace +} // end namespace Catch + +#else // not Windows or ANSI /////////////////////////////////////////////// + +namespace Catch { + + static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); } + +} // end namespace Catch + +#endif // Windows/ ANSI/ None + +namespace Catch { + + Colour::Colour( Code _colourCode ) { use( _colourCode ); } + Colour::Colour( Colour&& rhs ) noexcept { + m_moved = rhs.m_moved; + rhs.m_moved = true; + } + Colour& Colour::operator=( Colour&& rhs ) noexcept { + m_moved = rhs.m_moved; + rhs.m_moved = true; + return *this; + } + + Colour::~Colour(){ if( !m_moved ) use( None ); } + + void Colour::use( Code _colourCode ) { + static IColourImpl* impl = platformColourInstance(); + impl->use( _colourCode ); + } + + std::ostream& operator << ( std::ostream& os, Colour const& ) { + return os; + } + +} // end namespace Catch + +#if defined(__clang__) +# pragma clang diagnostic pop +#endif + +// end catch_console_colour.cpp +// start catch_context.cpp + +namespace Catch { + + class Context : public IMutableContext, NonCopyable { + + public: // IContext + virtual IResultCapture* getResultCapture() override { + return m_resultCapture; + } + virtual IRunner* getRunner() override { + return m_runner; + } + + virtual IConfigPtr const& getConfig() const override { + return m_config; + } + + virtual ~Context() override; + + public: // IMutableContext + virtual void setResultCapture( IResultCapture* resultCapture ) override { + m_resultCapture = resultCapture; + } + virtual void setRunner( IRunner* runner ) override { + m_runner = runner; + } + virtual void setConfig( IConfigPtr const& config ) override { + m_config = config; + } + + friend IMutableContext& getCurrentMutableContext(); + + private: + IConfigPtr m_config; + IRunner* m_runner = nullptr; + IResultCapture* m_resultCapture = nullptr; + }; + + IMutableContext *IMutableContext::currentContext = nullptr; + + void IMutableContext::createContext() + { + currentContext = new Context(); + } + + void cleanUpContext() { + delete IMutableContext::currentContext; + IMutableContext::currentContext = nullptr; + } + IContext::~IContext() = default; + IMutableContext::~IMutableContext() = default; + Context::~Context() = default; +} +// end catch_context.cpp +// start catch_debug_console.cpp + +// start catch_debug_console.h + +#include + +namespace Catch { + void writeToDebugConsole( std::string const& text ); +} + +// end catch_debug_console.h +#ifdef CATCH_PLATFORM_WINDOWS + + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + ::OutputDebugStringA( text.c_str() ); + } + } + +#else + + namespace Catch { + void writeToDebugConsole( std::string const& text ) { + // !TBD: Need a version for Mac/ XCode and other IDEs + Catch::cout() << text; + } + } + +#endif // Platform +// end catch_debug_console.cpp +// start catch_debugger.cpp + +#ifdef CATCH_PLATFORM_MAC + +# include +# include +# include +# include +# include +# include +# include + +namespace Catch { + + // The following function is taken directly from the following technical note: + // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html + + // Returns true if the current process is being debugged (either + // running under the debugger or has a debugger attached post facto). + bool isDebuggerActive(){ + + int mib[4]; + struct kinfo_proc info; + std::size_t size; + + // Initialize the flags so that, if sysctl fails for some bizarre + // reason, we get a predictable result. + + info.kp_proc.p_flag = 0; + + // Initialize mib, which tells sysctl the info we want, in this case + // we're looking for information about a specific process ID. + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = getpid(); + + // Call sysctl. + + size = sizeof(info); + if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0) != 0 ) { + Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; + return false; + } + + // We're being debugged if the P_TRACED flag is set. + + return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); + } + } // namespace Catch + +#elif defined(CATCH_PLATFORM_LINUX) + #include + #include + + namespace Catch{ + // The standard POSIX way of detecting a debugger is to attempt to + // ptrace() the process, but this needs to be done from a child and not + // this process itself to still allow attaching to this process later + // if wanted, so is rather heavy. Under Linux we have the PID of the + // "debugger" (which doesn't need to be gdb, of course, it could also + // be strace, for example) in /proc/$PID/status, so just get it from + // there instead. + bool isDebuggerActive(){ + // Libstdc++ has a bug, where std::ifstream sets errno to 0 + // This way our users can properly assert over errno values + ErrnoGuard guard; + std::ifstream in("/proc/self/status"); + for( std::string line; std::getline(in, line); ) { + static const int PREFIX_LEN = 11; + if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) { + // We're traced if the PID is not 0 and no other PID starts + // with 0 digit, so it's enough to check for just a single + // character. + return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; + } + } + + return false; + } + } // namespace Catch +#elif defined(_MSC_VER) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#elif defined(__MINGW32__) + extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); + namespace Catch { + bool isDebuggerActive() { + return IsDebuggerPresent() != 0; + } + } +#else + namespace Catch { + bool isDebuggerActive() { return false; } + } +#endif // Platform +// end catch_debugger.cpp +// start catch_decomposer.cpp + +namespace Catch { + + ITransientExpression::~ITransientExpression() = default; + + void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) { + if( lhs.size() + rhs.size() < 40 && + lhs.find('\n') == std::string::npos && + rhs.find('\n') == std::string::npos ) + os << lhs << " " << op << " " << rhs; + else + os << lhs << "\n" << op << "\n" << rhs; + } +} +// end catch_decomposer.cpp +// start catch_errno_guard.cpp + +#include + +namespace Catch { + ErrnoGuard::ErrnoGuard():m_oldErrno(errno){} + ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; } +} +// end catch_errno_guard.cpp +// start catch_exception_translator_registry.cpp + +// start catch_exception_translator_registry.h + +#include +#include +#include + +namespace Catch { + + class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { + public: + ~ExceptionTranslatorRegistry(); + virtual void registerTranslator( const IExceptionTranslator* translator ); + virtual std::string translateActiveException() const override; + std::string tryTranslators() const; + + private: + std::vector> m_translators; + }; +} + +// end catch_exception_translator_registry.h +#ifdef __OBJC__ +#import "Foundation/Foundation.h" +#endif + +namespace Catch { + + ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() { + } + + void ExceptionTranslatorRegistry::registerTranslator( const IExceptionTranslator* translator ) { + m_translators.push_back( std::unique_ptr( translator ) ); + } + + std::string ExceptionTranslatorRegistry::translateActiveException() const { + try { +#ifdef __OBJC__ + // In Objective-C try objective-c exceptions first + @try { + return tryTranslators(); + } + @catch (NSException *exception) { + return Catch::Detail::stringify( [exception description] ); + } +#else + // Compiling a mixed mode project with MSVC means that CLR + // exceptions will be caught in (...) as well. However, these + // do not fill-in std::current_exception and thus lead to crash + // when attempting rethrow. + // /EHa switch also causes structured exceptions to be caught + // here, but they fill-in current_exception properly, so + // at worst the output should be a little weird, instead of + // causing a crash. + if (std::current_exception() == nullptr) { + return "Non C++ exception. Possibly a CLR exception."; + } + return tryTranslators(); +#endif + } + catch( TestFailureException& ) { + std::rethrow_exception(std::current_exception()); + } + catch( std::exception& ex ) { + return ex.what(); + } + catch( std::string& msg ) { + return msg; + } + catch( const char* msg ) { + return msg; + } + catch(...) { + return "Unknown exception"; + } + } + + std::string ExceptionTranslatorRegistry::tryTranslators() const { + if( m_translators.empty() ) + std::rethrow_exception(std::current_exception()); + else + return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); + } +} +// end catch_exception_translator_registry.cpp +// start catch_fatal_condition.cpp + +#if defined(__GNUC__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#endif + +#if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS ) + +namespace { + // Report the error condition + void reportFatal( char const * const message ) { + Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message ); + } +} + +#endif // signals/SEH handling + +#if defined( CATCH_CONFIG_WINDOWS_SEH ) + +namespace Catch { + struct SignalDefs { DWORD id; const char* name; }; + + // There is no 1-1 mapping between signals and windows exceptions. + // Windows can easily distinguish between SO and SigSegV, + // but SigInt, SigTerm, etc are handled differently. + static SignalDefs signalDefs[] = { + { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" }, + { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" }, + { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" }, + { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" }, + }; + + LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { + for (auto const& def : signalDefs) { + if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) { + reportFatal(def.name); + } + } + // If its not an exception we care about, pass it along. + // This stops us from eating debugger breaks etc. + return EXCEPTION_CONTINUE_SEARCH; + } + + FatalConditionHandler::FatalConditionHandler() { + isSet = true; + // 32k seems enough for Catch to handle stack overflow, + // but the value was found experimentally, so there is no strong guarantee + guaranteeSize = 32 * 1024; + exceptionHandlerHandle = nullptr; + // Register as first handler in current chain + exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); + // Pass in guarantee size to be filled + SetThreadStackGuarantee(&guaranteeSize); + } + + void FatalConditionHandler::reset() { + if (isSet) { + RemoveVectoredExceptionHandler(exceptionHandlerHandle); + SetThreadStackGuarantee(&guaranteeSize); + exceptionHandlerHandle = nullptr; + isSet = false; + } + } + + FatalConditionHandler::~FatalConditionHandler() { + reset(); + } + +bool FatalConditionHandler::isSet = false; +ULONG FatalConditionHandler::guaranteeSize = 0; +PVOID FatalConditionHandler::exceptionHandlerHandle = nullptr; + +} // namespace Catch + +#elif defined( CATCH_CONFIG_POSIX_SIGNALS ) + +namespace Catch { + + struct SignalDefs { + int id; + const char* name; + }; + + // 32kb for the alternate stack seems to be sufficient. However, this value + // is experimentally determined, so that's not guaranteed. + constexpr static std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ; + + static SignalDefs signalDefs[] = { + { SIGINT, "SIGINT - Terminal interrupt signal" }, + { SIGILL, "SIGILL - Illegal instruction signal" }, + { SIGFPE, "SIGFPE - Floating point error signal" }, + { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, + { SIGTERM, "SIGTERM - Termination request signal" }, + { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } + }; + + void FatalConditionHandler::handleSignal( int sig ) { + char const * name = ""; + for (auto const& def : signalDefs) { + if (sig == def.id) { + name = def.name; + break; + } + } + reset(); + reportFatal(name); + raise( sig ); + } + + FatalConditionHandler::FatalConditionHandler() { + isSet = true; + stack_t sigStack; + sigStack.ss_sp = altStackMem; + sigStack.ss_size = sigStackSize; + sigStack.ss_flags = 0; + sigaltstack(&sigStack, &oldSigStack); + struct sigaction sa = { }; + + sa.sa_handler = handleSignal; + sa.sa_flags = SA_ONSTACK; + for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) { + sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); + } + } + + FatalConditionHandler::~FatalConditionHandler() { + reset(); + } + + void FatalConditionHandler::reset() { + if( isSet ) { + // Set signals back to previous values -- hopefully nobody overwrote them in the meantime + for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) { + sigaction(signalDefs[i].id, &oldSigActions[i], nullptr); + } + // Return the old stack + sigaltstack(&oldSigStack, nullptr); + isSet = false; + } + } + + bool FatalConditionHandler::isSet = false; + struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {}; + stack_t FatalConditionHandler::oldSigStack = {}; + char FatalConditionHandler::altStackMem[sigStackSize] = {}; + +} // namespace Catch + +#else + +namespace Catch { + void FatalConditionHandler::reset() {} +} + +#endif // signals/SEH handling + +#if defined(__GNUC__) +# pragma GCC diagnostic pop +#endif +// end catch_fatal_condition.cpp +// start catch_interfaces_capture.cpp + +namespace Catch { + IResultCapture::~IResultCapture() = default; +} +// end catch_interfaces_capture.cpp +// start catch_interfaces_config.cpp + +namespace Catch { + IConfig::~IConfig() = default; +} +// end catch_interfaces_config.cpp +// start catch_interfaces_exception.cpp + +namespace Catch { + IExceptionTranslator::~IExceptionTranslator() = default; + IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() = default; +} +// end catch_interfaces_exception.cpp +// start catch_interfaces_registry_hub.cpp + +namespace Catch { + IRegistryHub::~IRegistryHub() = default; + IMutableRegistryHub::~IMutableRegistryHub() = default; +} +// end catch_interfaces_registry_hub.cpp +// start catch_interfaces_reporter.cpp + +// start catch_reporter_listening.h + +namespace Catch { + + class ListeningReporter : public IStreamingReporter { + using Reporters = std::vector; + Reporters m_listeners; + IStreamingReporterPtr m_reporter = nullptr; + + public: + void addListener( IStreamingReporterPtr&& listener ); + void addReporter( IStreamingReporterPtr&& reporter ); + + public: // IStreamingReporter + + ReporterPreferences getPreferences() const override; + + void noMatchingTestCases( std::string const& spec ) override; + + static std::set getSupportedVerbosities(); + + void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override; + void benchmarkEnded( BenchmarkStats const& benchmarkStats ) override; + + void testRunStarting( TestRunInfo const& testRunInfo ) override; + void testGroupStarting( GroupInfo const& groupInfo ) override; + void testCaseStarting( TestCaseInfo const& testInfo ) override; + void sectionStarting( SectionInfo const& sectionInfo ) override; + void assertionStarting( AssertionInfo const& assertionInfo ) override; + + // The return value indicates if the messages buffer should be cleared: + bool assertionEnded( AssertionStats const& assertionStats ) override; + void sectionEnded( SectionStats const& sectionStats ) override; + void testCaseEnded( TestCaseStats const& testCaseStats ) override; + void testGroupEnded( TestGroupStats const& testGroupStats ) override; + void testRunEnded( TestRunStats const& testRunStats ) override; + + void skipTest( TestCaseInfo const& testInfo ) override; + bool isMulti() const override; + + }; + +} // end namespace Catch + +// end catch_reporter_listening.h +namespace Catch { + + ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig ) + : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} + + ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream ) + : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} + + std::ostream& ReporterConfig::stream() const { return *m_stream; } + IConfigPtr ReporterConfig::fullConfig() const { return m_fullConfig; } + + TestRunInfo::TestRunInfo( std::string const& _name ) : name( _name ) {} + + GroupInfo::GroupInfo( std::string const& _name, + std::size_t _groupIndex, + std::size_t _groupsCount ) + : name( _name ), + groupIndex( _groupIndex ), + groupsCounts( _groupsCount ) + {} + + AssertionStats::AssertionStats( AssertionResult const& _assertionResult, + std::vector const& _infoMessages, + Totals const& _totals ) + : assertionResult( _assertionResult ), + infoMessages( _infoMessages ), + totals( _totals ) + { + assertionResult.m_resultData.lazyExpression.m_transientExpression = _assertionResult.m_resultData.lazyExpression.m_transientExpression; + + if( assertionResult.hasMessage() ) { + // Copy message into messages list. + // !TBD This should have been done earlier, somewhere + MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); + builder << assertionResult.getMessage(); + builder.m_info.message = builder.m_stream.str(); + + infoMessages.push_back( builder.m_info ); + } + } + + AssertionStats::~AssertionStats() = default; + + SectionStats::SectionStats( SectionInfo const& _sectionInfo, + Counts const& _assertions, + double _durationInSeconds, + bool _missingAssertions ) + : sectionInfo( _sectionInfo ), + assertions( _assertions ), + durationInSeconds( _durationInSeconds ), + missingAssertions( _missingAssertions ) + {} + + SectionStats::~SectionStats() = default; + + TestCaseStats::TestCaseStats( TestCaseInfo const& _testInfo, + Totals const& _totals, + std::string const& _stdOut, + std::string const& _stdErr, + bool _aborting ) + : testInfo( _testInfo ), + totals( _totals ), + stdOut( _stdOut ), + stdErr( _stdErr ), + aborting( _aborting ) + {} + + TestCaseStats::~TestCaseStats() = default; + + TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo, + Totals const& _totals, + bool _aborting ) + : groupInfo( _groupInfo ), + totals( _totals ), + aborting( _aborting ) + {} + + TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo ) + : groupInfo( _groupInfo ), + aborting( false ) + {} + + TestGroupStats::~TestGroupStats() = default; + + TestRunStats::TestRunStats( TestRunInfo const& _runInfo, + Totals const& _totals, + bool _aborting ) + : runInfo( _runInfo ), + totals( _totals ), + aborting( _aborting ) + {} + + TestRunStats::~TestRunStats() = default; + + void IStreamingReporter::fatalErrorEncountered( StringRef ) {} + bool IStreamingReporter::isMulti() const { return false; } + + IReporterFactory::~IReporterFactory() = default; + IReporterRegistry::~IReporterRegistry() = default; + +} // end namespace Catch +// end catch_interfaces_reporter.cpp +// start catch_interfaces_runner.cpp + +namespace Catch { + IRunner::~IRunner() = default; +} +// end catch_interfaces_runner.cpp +// start catch_interfaces_testcase.cpp + +namespace Catch { + ITestInvoker::~ITestInvoker() = default; + ITestCaseRegistry::~ITestCaseRegistry() = default; +} +// end catch_interfaces_testcase.cpp +// start catch_leak_detector.cpp + +#ifdef CATCH_CONFIG_WINDOWS_CRTDBG +#include + +namespace Catch { + + LeakDetector::LeakDetector() { + int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); + flag |= _CRTDBG_LEAK_CHECK_DF; + flag |= _CRTDBG_ALLOC_MEM_DF; + _CrtSetDbgFlag(flag); + _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); + _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); + // Change this to leaking allocation's number to break there + _CrtSetBreakAlloc(-1); + } +} + +#else + + Catch::LeakDetector::LeakDetector() {} + +#endif +// end catch_leak_detector.cpp +// start catch_list.cpp + +// start catch_list.h + +#include + +namespace Catch { + + std::size_t listTests( Config const& config ); + + std::size_t listTestsNamesOnly( Config const& config ); + + struct TagInfo { + void add( std::string const& spelling ); + std::string all() const; + + std::set spellings; + std::size_t count = 0; + }; + + std::size_t listTags( Config const& config ); + + std::size_t listReporters( Config const& /*config*/ ); + + Option list( Config const& config ); + +} // end namespace Catch + +// end catch_list.h +// start catch_text.h + +namespace Catch { + using namespace clara::TextFlow; +} + +// end catch_text.h +#include +#include +#include + +namespace Catch { + + std::size_t listTests( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( config.hasTestFilters() ) + Catch::cout() << "Matching test cases:\n"; + else { + Catch::cout() << "All available test cases:\n"; + } + + auto matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( auto const& testCaseInfo : matchedTestCases ) { + Colour::Code colour = testCaseInfo.isHidden() + ? Colour::SecondaryText + : Colour::None; + Colour colourGuard( colour ); + + Catch::cout() << Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) << "\n"; + if( config.verbosity() >= Verbosity::High ) { + Catch::cout() << Column( Catch::Detail::stringify( testCaseInfo.lineInfo ) ).indent(4) << std::endl; + std::string description = testCaseInfo.description; + if( description.empty() ) + description = "(NO DESCRIPTION)"; + Catch::cout() << Column( description ).indent(4) << std::endl; + } + if( !testCaseInfo.tags.empty() ) + Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) << "\n"; + } + + if( !config.hasTestFilters() ) + Catch::cout() << pluralise( matchedTestCases.size(), "test case" ) << '\n' << std::endl; + else + Catch::cout() << pluralise( matchedTestCases.size(), "matching test case" ) << '\n' << std::endl; + return matchedTestCases.size(); + } + + std::size_t listTestsNamesOnly( Config const& config ) { + TestSpec testSpec = config.testSpec(); + std::size_t matchedTests = 0; + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( auto const& testCaseInfo : matchedTestCases ) { + matchedTests++; + if( startsWith( testCaseInfo.name, '#' ) ) + Catch::cout() << '"' << testCaseInfo.name << '"'; + else + Catch::cout() << testCaseInfo.name; + if ( config.verbosity() >= Verbosity::High ) + Catch::cout() << "\t@" << testCaseInfo.lineInfo; + Catch::cout() << std::endl; + } + return matchedTests; + } + + void TagInfo::add( std::string const& spelling ) { + ++count; + spellings.insert( spelling ); + } + + std::string TagInfo::all() const { + std::string out; + for( auto const& spelling : spellings ) + out += "[" + spelling + "]"; + return out; + } + + std::size_t listTags( Config const& config ) { + TestSpec testSpec = config.testSpec(); + if( config.hasTestFilters() ) + Catch::cout() << "Tags for matching test cases:\n"; + else { + Catch::cout() << "All available tags:\n"; + } + + std::map tagCounts; + + std::vector matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); + for( auto const& testCase : matchedTestCases ) { + for( auto const& tagName : testCase.getTestCaseInfo().tags ) { + std::string lcaseTagName = toLower( tagName ); + auto countIt = tagCounts.find( lcaseTagName ); + if( countIt == tagCounts.end() ) + countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; + countIt->second.add( tagName ); + } + } + + for( auto const& tagCount : tagCounts ) { + ReusableStringStream rss; + rss << " " << std::setw(2) << tagCount.second.count << " "; + auto str = rss.str(); + auto wrapper = Column( tagCount.second.all() ) + .initialIndent( 0 ) + .indent( str.size() ) + .width( CATCH_CONFIG_CONSOLE_WIDTH-10 ); + Catch::cout() << str << wrapper << '\n'; + } + Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl; + return tagCounts.size(); + } + + std::size_t listReporters( Config const& /*config*/ ) { + Catch::cout() << "Available reporters:\n"; + IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); + std::size_t maxNameLen = 0; + for( auto const& factoryKvp : factories ) + maxNameLen = (std::max)( maxNameLen, factoryKvp.first.size() ); + + for( auto const& factoryKvp : factories ) { + Catch::cout() + << Column( factoryKvp.first + ":" ) + .indent(2) + .width( 5+maxNameLen ) + + Column( factoryKvp.second->getDescription() ) + .initialIndent(0) + .indent(2) + .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) + << "\n"; + } + Catch::cout() << std::endl; + return factories.size(); + } + + Option list( Config const& config ) { + Option listedCount; + if( config.listTests() ) + listedCount = listedCount.valueOr(0) + listTests( config ); + if( config.listTestNamesOnly() ) + listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config ); + if( config.listTags() ) + listedCount = listedCount.valueOr(0) + listTags( config ); + if( config.listReporters() ) + listedCount = listedCount.valueOr(0) + listReporters( config ); + return listedCount; + } + +} // end namespace Catch +// end catch_list.cpp +// start catch_matchers.cpp + +namespace Catch { +namespace Matchers { + namespace Impl { + + std::string MatcherUntypedBase::toString() const { + if( m_cachedToString.empty() ) + m_cachedToString = describe(); + return m_cachedToString; + } + + MatcherUntypedBase::~MatcherUntypedBase() = default; + + } // namespace Impl +} // namespace Matchers + +using namespace Matchers; +using Matchers::Impl::MatcherBase; + +} // namespace Catch +// end catch_matchers.cpp +// start catch_matchers_floating.cpp + +// start catch_to_string.hpp + +#include + +namespace Catch { + template + std::string to_string(T const& t) { +#if defined(CATCH_CONFIG_CPP11_TO_STRING) + return std::to_string(t); +#else + ReusableStringStream rss; + rss << t; + return rss.str(); +#endif + } +} // end namespace Catch + +// end catch_to_string.hpp +#include +#include +#include +#include + +namespace Catch { +namespace Matchers { +namespace Floating { +enum class FloatingPointKind : uint8_t { + Float, + Double +}; +} +} +} + +namespace { + +template +struct Converter; + +template <> +struct Converter { + static_assert(sizeof(float) == sizeof(int32_t), "Important ULP matcher assumption violated"); + Converter(float f) { + std::memcpy(&i, &f, sizeof(f)); + } + int32_t i; +}; + +template <> +struct Converter { + static_assert(sizeof(double) == sizeof(int64_t), "Important ULP matcher assumption violated"); + Converter(double d) { + std::memcpy(&i, &d, sizeof(d)); + } + int64_t i; +}; + +template +auto convert(T t) -> Converter { + return Converter(t); +} + +template +bool almostEqualUlps(FP lhs, FP rhs, int maxUlpDiff) { + // Comparison with NaN should always be false. + // This way we can rule it out before getting into the ugly details + if (std::isnan(lhs) || std::isnan(rhs)) { + return false; + } + + auto lc = convert(lhs); + auto rc = convert(rhs); + + if ((lc.i < 0) != (rc.i < 0)) { + // Potentially we can have +0 and -0 + return lhs == rhs; + } + + auto ulpDiff = std::abs(lc.i - rc.i); + return ulpDiff <= maxUlpDiff; +} + +} + +namespace Catch { +namespace Matchers { +namespace Floating { + WithinAbsMatcher::WithinAbsMatcher(double target, double margin) + :m_target{ target }, m_margin{ margin } { + if (m_margin < 0) { + throw std::domain_error("Allowed margin difference has to be >= 0"); + } + } + + // Performs equivalent check of std::fabs(lhs - rhs) <= margin + // But without the subtraction to allow for INFINITY in comparison + bool WithinAbsMatcher::match(double const& matchee) const { + return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee); + } + + std::string WithinAbsMatcher::describe() const { + return "is within " + ::Catch::Detail::stringify(m_margin) + " of " + ::Catch::Detail::stringify(m_target); + } + + WithinUlpsMatcher::WithinUlpsMatcher(double target, int ulps, FloatingPointKind baseType) + :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } { + if (m_ulps < 0) { + throw std::domain_error("Allowed ulp difference has to be >= 0"); + } + } + + bool WithinUlpsMatcher::match(double const& matchee) const { + switch (m_type) { + case FloatingPointKind::Float: + return almostEqualUlps(static_cast(matchee), static_cast(m_target), m_ulps); + case FloatingPointKind::Double: + return almostEqualUlps(matchee, m_target, m_ulps); + default: + throw std::domain_error("Unknown FloatingPointKind value"); + } + } + + std::string WithinUlpsMatcher::describe() const { + return "is within " + Catch::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)? "f" : ""); + } + +}// namespace Floating + +Floating::WithinUlpsMatcher WithinULP(double target, int maxUlpDiff) { + return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Double); +} + +Floating::WithinUlpsMatcher WithinULP(float target, int maxUlpDiff) { + return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Float); +} + +Floating::WithinAbsMatcher WithinAbs(double target, double margin) { + return Floating::WithinAbsMatcher(target, margin); +} + +} // namespace Matchers +} // namespace Catch + +// end catch_matchers_floating.cpp +// start catch_matchers_generic.cpp + +std::string Catch::Matchers::Generic::Detail::finalizeDescription(const std::string& desc) { + if (desc.empty()) { + return "matches undescribed predicate"; + } else { + return "matches predicate: \"" + desc + '"'; + } +} +// end catch_matchers_generic.cpp +// start catch_matchers_string.cpp + +#include + +namespace Catch { +namespace Matchers { + + namespace StdString { + + CasedString::CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_str( adjustString( str ) ) + {} + std::string CasedString::adjustString( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No + ? toLower( str ) + : str; + } + std::string CasedString::caseSensitivitySuffix() const { + return m_caseSensitivity == CaseSensitive::No + ? " (case insensitive)" + : std::string(); + } + + StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator ) + : m_comparator( comparator ), + m_operation( operation ) { + } + + std::string StringMatcherBase::describe() const { + std::string description; + description.reserve(5 + m_operation.size() + m_comparator.m_str.size() + + m_comparator.caseSensitivitySuffix().size()); + description += m_operation; + description += ": \""; + description += m_comparator.m_str; + description += "\""; + description += m_comparator.caseSensitivitySuffix(); + return description; + } + + EqualsMatcher::EqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals", comparator ) {} + + bool EqualsMatcher::match( std::string const& source ) const { + return m_comparator.adjustString( source ) == m_comparator.m_str; + } + + ContainsMatcher::ContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains", comparator ) {} + + bool ContainsMatcher::match( std::string const& source ) const { + return contains( m_comparator.adjustString( source ), m_comparator.m_str ); + } + + StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with", comparator ) {} + + bool StartsWithMatcher::match( std::string const& source ) const { + return startsWith( m_comparator.adjustString( source ), m_comparator.m_str ); + } + + EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with", comparator ) {} + + bool EndsWithMatcher::match( std::string const& source ) const { + return endsWith( m_comparator.adjustString( source ), m_comparator.m_str ); + } + + RegexMatcher::RegexMatcher(std::string regex, CaseSensitive::Choice caseSensitivity): m_regex(std::move(regex)), m_caseSensitivity(caseSensitivity) {} + + bool RegexMatcher::match(std::string const& matchee) const { + auto flags = std::regex::ECMAScript; // ECMAScript is the default syntax option anyway + if (m_caseSensitivity == CaseSensitive::Choice::No) { + flags |= std::regex::icase; + } + auto reg = std::regex(m_regex, flags); + return std::regex_match(matchee, reg); + } + + std::string RegexMatcher::describe() const { + return "matches " + ::Catch::Detail::stringify(m_regex) + ((m_caseSensitivity == CaseSensitive::Choice::Yes)? " case sensitively" : " case insensitively"); + } + + } // namespace StdString + + StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity ) { + return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) ); + } + StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity ) { + return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) ); + } + StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) { + return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) ); + } + StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) { + return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) ); + } + + StdString::RegexMatcher Matches(std::string const& regex, CaseSensitive::Choice caseSensitivity) { + return StdString::RegexMatcher(regex, caseSensitivity); + } + +} // namespace Matchers +} // namespace Catch +// end catch_matchers_string.cpp +// start catch_message.cpp + +// start catch_uncaught_exceptions.h + +namespace Catch { + bool uncaught_exceptions(); +} // end namespace Catch + +// end catch_uncaught_exceptions.h +namespace Catch { + + MessageInfo::MessageInfo( std::string const& _macroName, + SourceLineInfo const& _lineInfo, + ResultWas::OfType _type ) + : macroName( _macroName ), + lineInfo( _lineInfo ), + type( _type ), + sequence( ++globalCount ) + {} + + bool MessageInfo::operator==( MessageInfo const& other ) const { + return sequence == other.sequence; + } + + bool MessageInfo::operator<( MessageInfo const& other ) const { + return sequence < other.sequence; + } + + // This may need protecting if threading support is added + unsigned int MessageInfo::globalCount = 0; + + //////////////////////////////////////////////////////////////////////////// + + Catch::MessageBuilder::MessageBuilder( std::string const& macroName, + SourceLineInfo const& lineInfo, + ResultWas::OfType type ) + :m_info(macroName, lineInfo, type) {} + + //////////////////////////////////////////////////////////////////////////// + + ScopedMessage::ScopedMessage( MessageBuilder const& builder ) + : m_info( builder.m_info ) + { + m_info.message = builder.m_stream.str(); + getResultCapture().pushScopedMessage( m_info ); + } + + ScopedMessage::~ScopedMessage() { + if ( !uncaught_exceptions() ){ + getResultCapture().popScopedMessage(m_info); + } + } +} // end namespace Catch +// end catch_message.cpp +// start catch_output_redirect.cpp + +// start catch_output_redirect.h +#ifndef TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H +#define TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H + +#include +#include +#include + +namespace Catch { + + class RedirectedStream { + std::ostream& m_originalStream; + std::ostream& m_redirectionStream; + std::streambuf* m_prevBuf; + + public: + RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream ); + ~RedirectedStream(); + }; + + class RedirectedStdOut { + ReusableStringStream m_rss; + RedirectedStream m_cout; + public: + RedirectedStdOut(); + auto str() const -> std::string; + }; + + // StdErr has two constituent streams in C++, std::cerr and std::clog + // This means that we need to redirect 2 streams into 1 to keep proper + // order of writes + class RedirectedStdErr { + ReusableStringStream m_rss; + RedirectedStream m_cerr; + RedirectedStream m_clog; + public: + RedirectedStdErr(); + auto str() const -> std::string; + }; + + // Windows's implementation of std::tmpfile is terrible (it tries + // to create a file inside system folder, thus requiring elevated + // privileges for the binary), so we have to use tmpnam(_s) and + // create the file ourselves there. + class TempFile { + public: + TempFile(TempFile const&) = delete; + TempFile& operator=(TempFile const&) = delete; + TempFile(TempFile&&) = delete; + TempFile& operator=(TempFile&&) = delete; + + TempFile(); + ~TempFile(); + + std::FILE* getFile(); + std::string getContents(); + + private: + std::FILE* m_file = nullptr; + #if defined(_MSC_VER) + char m_buffer[L_tmpnam] = { 0 }; + #endif + }; + + class OutputRedirect { + public: + OutputRedirect(OutputRedirect const&) = delete; + OutputRedirect& operator=(OutputRedirect const&) = delete; + OutputRedirect(OutputRedirect&&) = delete; + OutputRedirect& operator=(OutputRedirect&&) = delete; + + OutputRedirect(std::string& stdout_dest, std::string& stderr_dest); + ~OutputRedirect(); + + private: + int m_originalStdout = -1; + int m_originalStderr = -1; + TempFile m_stdoutFile; + TempFile m_stderrFile; + std::string& m_stdoutDest; + std::string& m_stderrDest; + }; + +} // end namespace Catch + +#endif // TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H +// end catch_output_redirect.h +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) +#include //_dup and _dup2 +#define dup _dup +#define dup2 _dup2 +#define fileno _fileno +#else +#include // dup and dup2 +#endif + +namespace Catch { + + RedirectedStream::RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream ) + : m_originalStream( originalStream ), + m_redirectionStream( redirectionStream ), + m_prevBuf( m_originalStream.rdbuf() ) + { + m_originalStream.rdbuf( m_redirectionStream.rdbuf() ); + } + + RedirectedStream::~RedirectedStream() { + m_originalStream.rdbuf( m_prevBuf ); + } + + RedirectedStdOut::RedirectedStdOut() : m_cout( Catch::cout(), m_rss.get() ) {} + auto RedirectedStdOut::str() const -> std::string { return m_rss.str(); } + + RedirectedStdErr::RedirectedStdErr() + : m_cerr( Catch::cerr(), m_rss.get() ), + m_clog( Catch::clog(), m_rss.get() ) + {} + auto RedirectedStdErr::str() const -> std::string { return m_rss.str(); } + +#if defined(_MSC_VER) + TempFile::TempFile() { + if (tmpnam_s(m_buffer)) { + throw std::runtime_error("Could not get a temp filename"); + } + if (fopen_s(&m_file, m_buffer, "w")) { + char buffer[100]; + if (strerror_s(buffer, errno)) { + throw std::runtime_error("Could not translate errno to string"); + } + throw std::runtime_error("Could not open the temp file: " + std::string(m_buffer) + buffer); + } + } +#else + TempFile::TempFile() { + m_file = std::tmpfile(); + if (!m_file) { + throw std::runtime_error("Could not create a temp file."); + } + } + +#endif + + TempFile::~TempFile() { + // TBD: What to do about errors here? + std::fclose(m_file); + // We manually create the file on Windows only, on Linux + // it will be autodeleted +#if defined(_MSC_VER) + std::remove(m_buffer); +#endif + } + + FILE* TempFile::getFile() { + return m_file; + } + + std::string TempFile::getContents() { + std::stringstream sstr; + char buffer[100] = {}; + std::rewind(m_file); + while (std::fgets(buffer, sizeof(buffer), m_file)) { + sstr << buffer; + } + return sstr.str(); + } + + OutputRedirect::OutputRedirect(std::string& stdout_dest, std::string& stderr_dest) : + m_originalStdout(dup(1)), + m_originalStderr(dup(2)), + m_stdoutDest(stdout_dest), + m_stderrDest(stderr_dest) { + dup2(fileno(m_stdoutFile.getFile()), 1); + dup2(fileno(m_stderrFile.getFile()), 2); + } + + OutputRedirect::~OutputRedirect() { + Catch::cout() << std::flush; + fflush(stdout); + // Since we support overriding these streams, we flush cerr + // even though std::cerr is unbuffered + Catch::cerr() << std::flush; + Catch::clog() << std::flush; + fflush(stderr); + + dup2(m_originalStdout, 1); + dup2(m_originalStderr, 2); + + m_stdoutDest += m_stdoutFile.getContents(); + m_stderrDest += m_stderrFile.getContents(); + } + +} // namespace Catch + +#if defined(_MSC_VER) +#undef dup +#undef dup2 +#undef fileno +#endif +// end catch_output_redirect.cpp +// start catch_random_number_generator.cpp + +// start catch_random_number_generator.h + +#include + +namespace Catch { + + struct IConfig; + + void seedRng( IConfig const& config ); + + unsigned int rngSeed(); + + struct RandomNumberGenerator { + using result_type = unsigned int; + + static constexpr result_type (min)() { return 0; } + static constexpr result_type (max)() { return 1000000; } + + result_type operator()( result_type n ) const; + result_type operator()() const; + + template + static void shuffle( V& vector ) { + RandomNumberGenerator rng; + std::shuffle( vector.begin(), vector.end(), rng ); + } + }; + +} + +// end catch_random_number_generator.h +#include + +namespace Catch { + + void seedRng( IConfig const& config ) { + if( config.rngSeed() != 0 ) + std::srand( config.rngSeed() ); + } + unsigned int rngSeed() { + return getCurrentContext().getConfig()->rngSeed(); + } + + RandomNumberGenerator::result_type RandomNumberGenerator::operator()( result_type n ) const { + return std::rand() % n; + } + RandomNumberGenerator::result_type RandomNumberGenerator::operator()() const { + return std::rand() % (max)(); + } + +} +// end catch_random_number_generator.cpp +// start catch_registry_hub.cpp + +// start catch_test_case_registry_impl.h + +#include +#include +#include +#include + +namespace Catch { + + class TestCase; + struct IConfig; + + std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ); + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); + + void enforceNoDuplicateTestCases( std::vector const& functions ); + + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); + std::vector const& getAllTestCasesSorted( IConfig const& config ); + + class TestRegistry : public ITestCaseRegistry { + public: + virtual ~TestRegistry() = default; + + virtual void registerTest( TestCase const& testCase ); + + std::vector const& getAllTests() const override; + std::vector const& getAllTestsSorted( IConfig const& config ) const override; + + private: + std::vector m_functions; + mutable RunTests::InWhatOrder m_currentSortOrder = RunTests::InDeclarationOrder; + mutable std::vector m_sortedFunctions; + std::size_t m_unnamedCount = 0; + std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised + }; + + /////////////////////////////////////////////////////////////////////////// + + class TestInvokerAsFunction : public ITestInvoker { + void(*m_testAsFunction)(); + public: + TestInvokerAsFunction( void(*testAsFunction)() ) noexcept; + + void invoke() const override; + }; + + std::string extractClassName( StringRef const& classOrQualifiedMethodName ); + + /////////////////////////////////////////////////////////////////////////// + +} // end namespace Catch + +// end catch_test_case_registry_impl.h +// start catch_reporter_registry.h + +#include + +namespace Catch { + + class ReporterRegistry : public IReporterRegistry { + + public: + + ~ReporterRegistry() override; + + IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const override; + + void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ); + void registerListener( IReporterFactoryPtr const& factory ); + + FactoryMap const& getFactories() const override; + Listeners const& getListeners() const override; + + private: + FactoryMap m_factories; + Listeners m_listeners; + }; +} + +// end catch_reporter_registry.h +// start catch_tag_alias_registry.h + +// start catch_tag_alias.h + +#include + +namespace Catch { + + struct TagAlias { + TagAlias(std::string const& _tag, SourceLineInfo _lineInfo); + + std::string tag; + SourceLineInfo lineInfo; + }; + +} // end namespace Catch + +// end catch_tag_alias.h +#include + +namespace Catch { + + class TagAliasRegistry : public ITagAliasRegistry { + public: + ~TagAliasRegistry() override; + TagAlias const* find( std::string const& alias ) const override; + std::string expandAliases( std::string const& unexpandedTestSpec ) const override; + void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ); + + private: + std::map m_registry; + }; + +} // end namespace Catch + +// end catch_tag_alias_registry.h +// start catch_startup_exception_registry.h + +#include +#include + +namespace Catch { + + class StartupExceptionRegistry { + public: + void add(std::exception_ptr const& exception) noexcept; + std::vector const& getExceptions() const noexcept; + private: + std::vector m_exceptions; + }; + +} // end namespace Catch + +// end catch_startup_exception_registry.h +namespace Catch { + + namespace { + + class RegistryHub : public IRegistryHub, public IMutableRegistryHub, + private NonCopyable { + + public: // IRegistryHub + RegistryHub() = default; + IReporterRegistry const& getReporterRegistry() const override { + return m_reporterRegistry; + } + ITestCaseRegistry const& getTestCaseRegistry() const override { + return m_testCaseRegistry; + } + IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() override { + return m_exceptionTranslatorRegistry; + } + ITagAliasRegistry const& getTagAliasRegistry() const override { + return m_tagAliasRegistry; + } + StartupExceptionRegistry const& getStartupExceptionRegistry() const override { + return m_exceptionRegistry; + } + + public: // IMutableRegistryHub + void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) override { + m_reporterRegistry.registerReporter( name, factory ); + } + void registerListener( IReporterFactoryPtr const& factory ) override { + m_reporterRegistry.registerListener( factory ); + } + void registerTest( TestCase const& testInfo ) override { + m_testCaseRegistry.registerTest( testInfo ); + } + void registerTranslator( const IExceptionTranslator* translator ) override { + m_exceptionTranslatorRegistry.registerTranslator( translator ); + } + void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) override { + m_tagAliasRegistry.add( alias, tag, lineInfo ); + } + void registerStartupException() noexcept override { + m_exceptionRegistry.add(std::current_exception()); + } + + private: + TestRegistry m_testCaseRegistry; + ReporterRegistry m_reporterRegistry; + ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; + TagAliasRegistry m_tagAliasRegistry; + StartupExceptionRegistry m_exceptionRegistry; + }; + + // Single, global, instance + RegistryHub*& getTheRegistryHub() { + static RegistryHub* theRegistryHub = nullptr; + if( !theRegistryHub ) + theRegistryHub = new RegistryHub(); + return theRegistryHub; + } + } + + IRegistryHub& getRegistryHub() { + return *getTheRegistryHub(); + } + IMutableRegistryHub& getMutableRegistryHub() { + return *getTheRegistryHub(); + } + void cleanUp() { + delete getTheRegistryHub(); + getTheRegistryHub() = nullptr; + cleanUpContext(); + ReusableStringStream::cleanup(); + } + std::string translateActiveException() { + return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); + } + +} // end namespace Catch +// end catch_registry_hub.cpp +// start catch_reporter_registry.cpp + +namespace Catch { + + ReporterRegistry::~ReporterRegistry() = default; + + IStreamingReporterPtr ReporterRegistry::create( std::string const& name, IConfigPtr const& config ) const { + auto it = m_factories.find( name ); + if( it == m_factories.end() ) + return nullptr; + return it->second->create( ReporterConfig( config ) ); + } + + void ReporterRegistry::registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) { + m_factories.emplace(name, factory); + } + void ReporterRegistry::registerListener( IReporterFactoryPtr const& factory ) { + m_listeners.push_back( factory ); + } + + IReporterRegistry::FactoryMap const& ReporterRegistry::getFactories() const { + return m_factories; + } + IReporterRegistry::Listeners const& ReporterRegistry::getListeners() const { + return m_listeners; + } + +} +// end catch_reporter_registry.cpp +// start catch_result_type.cpp + +namespace Catch { + + bool isOk( ResultWas::OfType resultType ) { + return ( resultType & ResultWas::FailureBit ) == 0; + } + bool isJustInfo( int flags ) { + return flags == ResultWas::Info; + } + + ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { + return static_cast( static_cast( lhs ) | static_cast( rhs ) ); + } + + bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } + bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } + +} // end namespace Catch +// end catch_result_type.cpp +// start catch_run_context.cpp + +#include +#include +#include + +namespace Catch { + + RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter) + : m_runInfo(_config->name()), + m_context(getCurrentMutableContext()), + m_config(_config), + m_reporter(std::move(reporter)), + m_lastAssertionInfo{ StringRef(), SourceLineInfo("",0), StringRef(), ResultDisposition::Normal }, + m_includeSuccessfulResults( m_config->includeSuccessfulResults() ) + { + m_context.setRunner(this); + m_context.setConfig(m_config); + m_context.setResultCapture(this); + m_reporter->testRunStarting(m_runInfo); + } + + RunContext::~RunContext() { + m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting())); + } + + void RunContext::testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount) { + m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount)); + } + + void RunContext::testGroupEnded(std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount) { + m_reporter->testGroupEnded(TestGroupStats(GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting())); + } + + Totals RunContext::runTest(TestCase const& testCase) { + Totals prevTotals = m_totals; + + std::string redirectedCout; + std::string redirectedCerr; + + auto const& testInfo = testCase.getTestCaseInfo(); + + m_reporter->testCaseStarting(testInfo); + + m_activeTestCase = &testCase; + + ITracker& rootTracker = m_trackerContext.startRun(); + assert(rootTracker.isSectionTracker()); + static_cast(rootTracker).addInitialFilters(m_config->getSectionsToRun()); + do { + m_trackerContext.startCycle(); + m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo)); + runCurrentTest(redirectedCout, redirectedCerr); + } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting()); + + Totals deltaTotals = m_totals.delta(prevTotals); + if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) { + deltaTotals.assertions.failed++; + deltaTotals.testCases.passed--; + deltaTotals.testCases.failed++; + } + m_totals.testCases += deltaTotals.testCases; + m_reporter->testCaseEnded(TestCaseStats(testInfo, + deltaTotals, + redirectedCout, + redirectedCerr, + aborting())); + + m_activeTestCase = nullptr; + m_testCaseTracker = nullptr; + + return deltaTotals; + } + + IConfigPtr RunContext::config() const { + return m_config; + } + + IStreamingReporter& RunContext::reporter() const { + return *m_reporter; + } + + void RunContext::assertionEnded(AssertionResult const & result) { + if (result.getResultType() == ResultWas::Ok) { + m_totals.assertions.passed++; + m_lastAssertionPassed = true; + } else if (!result.isOk()) { + m_lastAssertionPassed = false; + if( m_activeTestCase->getTestCaseInfo().okToFail() ) + m_totals.assertions.failedButOk++; + else + m_totals.assertions.failed++; + } + else { + m_lastAssertionPassed = true; + } + + // We have no use for the return value (whether messages should be cleared), because messages were made scoped + // and should be let to clear themselves out. + static_cast(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals))); + + // Reset working state + resetAssertionInfo(); + m_lastResult = result; + } + void RunContext::resetAssertionInfo() { + m_lastAssertionInfo.macroName = StringRef(); + m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"_sr; + } + + bool RunContext::sectionStarted(SectionInfo const & sectionInfo, Counts & assertions) { + ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.name, sectionInfo.lineInfo)); + if (!sectionTracker.isOpen()) + return false; + m_activeSections.push_back(§ionTracker); + + m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; + + m_reporter->sectionStarting(sectionInfo); + + assertions = m_totals.assertions; + + return true; + } + + bool RunContext::testForMissingAssertions(Counts& assertions) { + if (assertions.total() != 0) + return false; + if (!m_config->warnAboutMissingAssertions()) + return false; + if (m_trackerContext.currentTracker().hasChildren()) + return false; + m_totals.assertions.failed++; + assertions.failed++; + return true; + } + + void RunContext::sectionEnded(SectionEndInfo const & endInfo) { + Counts assertions = m_totals.assertions - endInfo.prevAssertions; + bool missingAssertions = testForMissingAssertions(assertions); + + if (!m_activeSections.empty()) { + m_activeSections.back()->close(); + m_activeSections.pop_back(); + } + + m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions)); + m_messages.clear(); + } + + void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) { + if (m_unfinishedSections.empty()) + m_activeSections.back()->fail(); + else + m_activeSections.back()->close(); + m_activeSections.pop_back(); + + m_unfinishedSections.push_back(endInfo); + } + void RunContext::benchmarkStarting( BenchmarkInfo const& info ) { + m_reporter->benchmarkStarting( info ); + } + void RunContext::benchmarkEnded( BenchmarkStats const& stats ) { + m_reporter->benchmarkEnded( stats ); + } + + void RunContext::pushScopedMessage(MessageInfo const & message) { + m_messages.push_back(message); + } + + void RunContext::popScopedMessage(MessageInfo const & message) { + m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end()); + } + + std::string RunContext::getCurrentTestName() const { + return m_activeTestCase + ? m_activeTestCase->getTestCaseInfo().name + : std::string(); + } + + const AssertionResult * RunContext::getLastResult() const { + return &(*m_lastResult); + } + + void RunContext::exceptionEarlyReported() { + m_shouldReportUnexpected = false; + } + + void RunContext::handleFatalErrorCondition( StringRef message ) { + // First notify reporter that bad things happened + m_reporter->fatalErrorEncountered(message); + + // Don't rebuild the result -- the stringification itself can cause more fatal errors + // Instead, fake a result data. + AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } ); + tempResult.message = message; + AssertionResult result(m_lastAssertionInfo, tempResult); + + assertionEnded(result); + + handleUnfinishedSections(); + + // Recreate section for test case (as we will lose the one that was in scope) + auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description); + + Counts assertions; + assertions.failed = 1; + SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false); + m_reporter->sectionEnded(testCaseSectionStats); + + auto const& testInfo = m_activeTestCase->getTestCaseInfo(); + + Totals deltaTotals; + deltaTotals.testCases.failed = 1; + deltaTotals.assertions.failed = 1; + m_reporter->testCaseEnded(TestCaseStats(testInfo, + deltaTotals, + std::string(), + std::string(), + false)); + m_totals.testCases.failed++; + testGroupEnded(std::string(), m_totals, 1, 1); + m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false)); + } + + bool RunContext::lastAssertionPassed() { + return m_lastAssertionPassed; + } + + void RunContext::assertionPassed() { + m_lastAssertionPassed = true; + ++m_totals.assertions.passed; + resetAssertionInfo(); + } + + bool RunContext::aborting() const { + return m_totals.assertions.failed == static_cast(m_config->abortAfter()); + } + + void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) { + auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); + SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description); + m_reporter->sectionStarting(testCaseSection); + Counts prevAssertions = m_totals.assertions; + double duration = 0; + m_shouldReportUnexpected = true; + m_lastAssertionInfo = { "TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), ResultDisposition::Normal }; + + seedRng(*m_config); + + Timer timer; + try { + if (m_reporter->getPreferences().shouldRedirectStdOut) { +#if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) + RedirectedStdOut redirectedStdOut; + RedirectedStdErr redirectedStdErr; + + timer.start(); + invokeActiveTestCase(); + redirectedCout += redirectedStdOut.str(); + redirectedCerr += redirectedStdErr.str(); +#else + OutputRedirect r(redirectedCout, redirectedCerr); + timer.start(); + invokeActiveTestCase(); +#endif + } else { + timer.start(); + invokeActiveTestCase(); + } + duration = timer.getElapsedSeconds(); + } catch (TestFailureException&) { + // This just means the test was aborted due to failure + } catch (...) { + // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions + // are reported without translation at the point of origin. + if( m_shouldReportUnexpected ) { + AssertionReaction dummyReaction; + handleUnexpectedInflightException( m_lastAssertionInfo, translateActiveException(), dummyReaction ); + } + } + Counts assertions = m_totals.assertions - prevAssertions; + bool missingAssertions = testForMissingAssertions(assertions); + + m_testCaseTracker->close(); + handleUnfinishedSections(); + m_messages.clear(); + + SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions); + m_reporter->sectionEnded(testCaseSectionStats); + } + + void RunContext::invokeActiveTestCase() { + FatalConditionHandler fatalConditionHandler; // Handle signals + m_activeTestCase->invoke(); + fatalConditionHandler.reset(); + } + + void RunContext::handleUnfinishedSections() { + // If sections ended prematurely due to an exception we stored their + // infos here so we can tear them down outside the unwind process. + for (auto it = m_unfinishedSections.rbegin(), + itEnd = m_unfinishedSections.rend(); + it != itEnd; + ++it) + sectionEnded(*it); + m_unfinishedSections.clear(); + } + + void RunContext::handleExpr( + AssertionInfo const& info, + ITransientExpression const& expr, + AssertionReaction& reaction + ) { + m_reporter->assertionStarting( info ); + + bool negated = isFalseTest( info.resultDisposition ); + bool result = expr.getResult() != negated; + + if( result ) { + if (!m_includeSuccessfulResults) { + assertionPassed(); + } + else { + reportExpr(info, ResultWas::Ok, &expr, negated); + } + } + else { + reportExpr(info, ResultWas::ExpressionFailed, &expr, negated ); + populateReaction( reaction ); + } + } + void RunContext::reportExpr( + AssertionInfo const &info, + ResultWas::OfType resultType, + ITransientExpression const *expr, + bool negated ) { + + m_lastAssertionInfo = info; + AssertionResultData data( resultType, LazyExpression( negated ) ); + + AssertionResult assertionResult{ info, data }; + assertionResult.m_resultData.lazyExpression.m_transientExpression = expr; + + assertionEnded( assertionResult ); + } + + void RunContext::handleMessage( + AssertionInfo const& info, + ResultWas::OfType resultType, + StringRef const& message, + AssertionReaction& reaction + ) { + m_reporter->assertionStarting( info ); + + m_lastAssertionInfo = info; + + AssertionResultData data( resultType, LazyExpression( false ) ); + data.message = message; + AssertionResult assertionResult{ m_lastAssertionInfo, data }; + assertionEnded( assertionResult ); + if( !assertionResult.isOk() ) + populateReaction( reaction ); + } + void RunContext::handleUnexpectedExceptionNotThrown( + AssertionInfo const& info, + AssertionReaction& reaction + ) { + handleNonExpr(info, Catch::ResultWas::DidntThrowException, reaction); + } + + void RunContext::handleUnexpectedInflightException( + AssertionInfo const& info, + std::string const& message, + AssertionReaction& reaction + ) { + m_lastAssertionInfo = info; + + AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) ); + data.message = message; + AssertionResult assertionResult{ info, data }; + assertionEnded( assertionResult ); + populateReaction( reaction ); + } + + void RunContext::populateReaction( AssertionReaction& reaction ) { + reaction.shouldDebugBreak = m_config->shouldDebugBreak(); + reaction.shouldThrow = aborting() || (m_lastAssertionInfo.resultDisposition & ResultDisposition::Normal); + } + + void RunContext::handleIncomplete( + AssertionInfo const& info + ) { + m_lastAssertionInfo = info; + + AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) ); + data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"; + AssertionResult assertionResult{ info, data }; + assertionEnded( assertionResult ); + } + void RunContext::handleNonExpr( + AssertionInfo const &info, + ResultWas::OfType resultType, + AssertionReaction &reaction + ) { + m_lastAssertionInfo = info; + + AssertionResultData data( resultType, LazyExpression( false ) ); + AssertionResult assertionResult{ info, data }; + assertionEnded( assertionResult ); + + if( !assertionResult.isOk() ) + populateReaction( reaction ); + } + + IResultCapture& getResultCapture() { + if (auto* capture = getCurrentContext().getResultCapture()) + return *capture; + else + CATCH_INTERNAL_ERROR("No result capture instance"); + } +} +// end catch_run_context.cpp +// start catch_section.cpp + +namespace Catch { + + Section::Section( SectionInfo const& info ) + : m_info( info ), + m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) + { + m_timer.start(); + } + + Section::~Section() { + if( m_sectionIncluded ) { + SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); + if( uncaught_exceptions() ) + getResultCapture().sectionEndedEarly( endInfo ); + else + getResultCapture().sectionEnded( endInfo ); + } + } + + // This indicates whether the section should be executed or not + Section::operator bool() const { + return m_sectionIncluded; + } + +} // end namespace Catch +// end catch_section.cpp +// start catch_section_info.cpp + +namespace Catch { + + SectionInfo::SectionInfo + ( SourceLineInfo const& _lineInfo, + std::string const& _name, + std::string const& _description ) + : name( _name ), + description( _description ), + lineInfo( _lineInfo ) + {} + + SectionEndInfo::SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) + : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) + {} + +} // end namespace Catch +// end catch_section_info.cpp +// start catch_session.cpp + +// start catch_session.h + +#include + +namespace Catch { + + class Session : NonCopyable { + public: + + Session(); + ~Session() override; + + void showHelp() const; + void libIdentify(); + + int applyCommandLine( int argc, char const * const * argv ); + + void useConfigData( ConfigData const& configData ); + + int run( int argc, char* argv[] ); + #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE) + int run( int argc, wchar_t* const argv[] ); + #endif + int run(); + + clara::Parser const& cli() const; + void cli( clara::Parser const& newParser ); + ConfigData& configData(); + Config& config(); + private: + int runInternal(); + + clara::Parser m_cli; + ConfigData m_configData; + std::shared_ptr m_config; + bool m_startupExceptions = false; + }; + +} // end namespace Catch + +// end catch_session.h +// start catch_version.h + +#include + +namespace Catch { + + // Versioning information + struct Version { + Version( Version const& ) = delete; + Version& operator=( Version const& ) = delete; + Version( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _patchNumber, + char const * const _branchName, + unsigned int _buildNumber ); + + unsigned int const majorVersion; + unsigned int const minorVersion; + unsigned int const patchNumber; + + // buildNumber is only used if branchName is not null + char const * const branchName; + unsigned int const buildNumber; + + friend std::ostream& operator << ( std::ostream& os, Version const& version ); + }; + + Version const& libraryVersion(); +} + +// end catch_version.h +#include +#include + +namespace Catch { + + namespace { + const int MaxExitCode = 255; + + IStreamingReporterPtr createReporter(std::string const& reporterName, IConfigPtr const& config) { + auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, config); + CATCH_ENFORCE(reporter, "No reporter registered with name: '" << reporterName << "'"); + + return reporter; + } + + IStreamingReporterPtr makeReporter(std::shared_ptr const& config) { + if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()) { + return createReporter(config->getReporterName(), config); + } + + auto multi = std::unique_ptr(new ListeningReporter); + + auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners(); + for (auto const& listener : listeners) { + multi->addListener(listener->create(Catch::ReporterConfig(config))); + } + multi->addReporter(createReporter(config->getReporterName(), config)); + return std::move(multi); + } + + Catch::Totals runTests(std::shared_ptr const& config) { + // FixMe: Add listeners in order first, then add reporters. + + auto reporter = makeReporter(config); + + RunContext context(config, std::move(reporter)); + + Totals totals; + + context.testGroupStarting(config->name(), 1, 1); + + TestSpec testSpec = config->testSpec(); + + auto const& allTestCases = getAllTestCasesSorted(*config); + for (auto const& testCase : allTestCases) { + if (!context.aborting() && matchTest(testCase, testSpec, *config)) + totals += context.runTest(testCase); + else + context.reporter().skipTest(testCase); + } + + if (config->warnAboutNoTests() && totals.testCases.total() == 0) { + ReusableStringStream testConfig; + + bool first = true; + for (const auto& input : config->getTestsOrTags()) { + if (!first) { testConfig << ' '; } + first = false; + testConfig << input; + } + + context.reporter().noMatchingTestCases(testConfig.str()); + totals.error = -1; + } + + context.testGroupEnded(config->name(), totals, 1, 1); + return totals; + } + + void applyFilenamesAsTags(Catch::IConfig const& config) { + auto& tests = const_cast&>(getAllTestCasesSorted(config)); + for (auto& testCase : tests) { + auto tags = testCase.tags; + + std::string filename = testCase.lineInfo.file; + auto lastSlash = filename.find_last_of("\\/"); + if (lastSlash != std::string::npos) { + filename.erase(0, lastSlash); + filename[0] = '#'; + } + + auto lastDot = filename.find_last_of('.'); + if (lastDot != std::string::npos) { + filename.erase(lastDot); + } + + tags.push_back(std::move(filename)); + setTags(testCase, tags); + } + } + + } // anon namespace + + Session::Session() { + static bool alreadyInstantiated = false; + if( alreadyInstantiated ) { + try { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); } + catch(...) { getMutableRegistryHub().registerStartupException(); } + } + + const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions(); + if ( !exceptions.empty() ) { + m_startupExceptions = true; + Colour colourGuard( Colour::Red ); + Catch::cerr() << "Errors occurred during startup!" << '\n'; + // iterate over all exceptions and notify user + for ( const auto& ex_ptr : exceptions ) { + try { + std::rethrow_exception(ex_ptr); + } catch ( std::exception const& ex ) { + Catch::cerr() << Column( ex.what() ).indent(2) << '\n'; + } + } + } + + alreadyInstantiated = true; + m_cli = makeCommandLineParser( m_configData ); + } + Session::~Session() { + Catch::cleanUp(); + } + + void Session::showHelp() const { + Catch::cout() + << "\nCatch v" << libraryVersion() << "\n" + << m_cli << std::endl + << "For more detailed usage please see the project docs\n" << std::endl; + } + void Session::libIdentify() { + Catch::cout() + << std::left << std::setw(16) << "description: " << "A Catch test executable\n" + << std::left << std::setw(16) << "category: " << "testframework\n" + << std::left << std::setw(16) << "framework: " << "Catch Test\n" + << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl; + } + + int Session::applyCommandLine( int argc, char const * const * argv ) { + if( m_startupExceptions ) + return 1; + + auto result = m_cli.parse( clara::Args( argc, argv ) ); + if( !result ) { + Catch::cerr() + << Colour( Colour::Red ) + << "\nError(s) in input:\n" + << Column( result.errorMessage() ).indent( 2 ) + << "\n\n"; + Catch::cerr() << "Run with -? for usage\n" << std::endl; + return MaxExitCode; + } + + if( m_configData.showHelp ) + showHelp(); + if( m_configData.libIdentify ) + libIdentify(); + m_config.reset(); + return 0; + } + + void Session::useConfigData( ConfigData const& configData ) { + m_configData = configData; + m_config.reset(); + } + + int Session::run( int argc, char* argv[] ) { + if( m_startupExceptions ) + return 1; + int returnCode = applyCommandLine( argc, argv ); + if( returnCode == 0 ) + returnCode = run(); + return returnCode; + } + +#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE) + int Session::run( int argc, wchar_t* const argv[] ) { + + char **utf8Argv = new char *[ argc ]; + + for ( int i = 0; i < argc; ++i ) { + int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL ); + + utf8Argv[ i ] = new char[ bufSize ]; + + WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL ); + } + + int returnCode = run( argc, utf8Argv ); + + for ( int i = 0; i < argc; ++i ) + delete [] utf8Argv[ i ]; + + delete [] utf8Argv; + + return returnCode; + } +#endif + int Session::run() { + if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) { + Catch::cout() << "...waiting for enter/ return before starting" << std::endl; + static_cast(std::getchar()); + } + int exitCode = runInternal(); + if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) { + Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl; + static_cast(std::getchar()); + } + return exitCode; + } + + clara::Parser const& Session::cli() const { + return m_cli; + } + void Session::cli( clara::Parser const& newParser ) { + m_cli = newParser; + } + ConfigData& Session::configData() { + return m_configData; + } + Config& Session::config() { + if( !m_config ) + m_config = std::make_shared( m_configData ); + return *m_config; + } + + int Session::runInternal() { + if( m_startupExceptions ) + return 1; + + if( m_configData.showHelp || m_configData.libIdentify ) + return 0; + + try + { + config(); // Force config to be constructed + + seedRng( *m_config ); + + if( m_configData.filenamesAsTags ) + applyFilenamesAsTags( *m_config ); + + // Handle list request + if( Option listed = list( config() ) ) + return static_cast( *listed ); + + auto totals = runTests( m_config ); + // Note that on unices only the lower 8 bits are usually used, clamping + // the return value to 255 prevents false negative when some multiple + // of 256 tests has failed + return (std::min) (MaxExitCode, (std::max) (totals.error, static_cast(totals.assertions.failed))); + } + catch( std::exception& ex ) { + Catch::cerr() << ex.what() << std::endl; + return MaxExitCode; + } + } + +} // end namespace Catch +// end catch_session.cpp +// start catch_startup_exception_registry.cpp + +namespace Catch { + void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept { + try { + m_exceptions.push_back(exception); + } + catch(...) { + // If we run out of memory during start-up there's really not a lot more we can do about it + std::terminate(); + } + } + + std::vector const& StartupExceptionRegistry::getExceptions() const noexcept { + return m_exceptions; + } + +} // end namespace Catch +// end catch_startup_exception_registry.cpp +// start catch_stream.cpp + +#include +#include +#include +#include +#include +#include + +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wexit-time-destructors" +#endif + +namespace Catch { + + Catch::IStream::~IStream() = default; + + namespace detail { namespace { + template + class StreamBufImpl : public std::streambuf { + char data[bufferSize]; + WriterF m_writer; + + public: + StreamBufImpl() { + setp( data, data + sizeof(data) ); + } + + ~StreamBufImpl() noexcept { + StreamBufImpl::sync(); + } + + private: + int overflow( int c ) override { + sync(); + + if( c != EOF ) { + if( pbase() == epptr() ) + m_writer( std::string( 1, static_cast( c ) ) ); + else + sputc( static_cast( c ) ); + } + return 0; + } + + int sync() override { + if( pbase() != pptr() ) { + m_writer( std::string( pbase(), static_cast( pptr() - pbase() ) ) ); + setp( pbase(), epptr() ); + } + return 0; + } + }; + + /////////////////////////////////////////////////////////////////////////// + + struct OutputDebugWriter { + + void operator()( std::string const&str ) { + writeToDebugConsole( str ); + } + }; + + /////////////////////////////////////////////////////////////////////////// + + class FileStream : public IStream { + mutable std::ofstream m_ofs; + public: + FileStream( StringRef filename ) { + m_ofs.open( filename.c_str() ); + CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << "'" ); + } + ~FileStream() override = default; + public: // IStream + std::ostream& stream() const override { + return m_ofs; + } + }; + + /////////////////////////////////////////////////////////////////////////// + + class CoutStream : public IStream { + mutable std::ostream m_os; + public: + // Store the streambuf from cout up-front because + // cout may get redirected when running tests + CoutStream() : m_os( Catch::cout().rdbuf() ) {} + ~CoutStream() override = default; + + public: // IStream + std::ostream& stream() const override { return m_os; } + }; + + /////////////////////////////////////////////////////////////////////////// + + class DebugOutStream : public IStream { + std::unique_ptr> m_streamBuf; + mutable std::ostream m_os; + public: + DebugOutStream() + : m_streamBuf( new StreamBufImpl() ), + m_os( m_streamBuf.get() ) + {} + + ~DebugOutStream() override = default; + + public: // IStream + std::ostream& stream() const override { return m_os; } + }; + + }} // namespace anon::detail + + /////////////////////////////////////////////////////////////////////////// + + auto makeStream( StringRef const &filename ) -> IStream const* { + if( filename.empty() ) + return new detail::CoutStream(); + else if( filename[0] == '%' ) { + if( filename == "%debug" ) + return new detail::DebugOutStream(); + else + CATCH_ERROR( "Unrecognised stream: '" << filename << "'" ); + } + else + return new detail::FileStream( filename ); + } + + // This class encapsulates the idea of a pool of ostringstreams that can be reused. + struct StringStreams { + std::vector> m_streams; + std::vector m_unused; + std::ostringstream m_referenceStream; // Used for copy state/ flags from + static StringStreams* s_instance; + + auto add() -> std::size_t { + if( m_unused.empty() ) { + m_streams.push_back( std::unique_ptr( new std::ostringstream ) ); + return m_streams.size()-1; + } + else { + auto index = m_unused.back(); + m_unused.pop_back(); + return index; + } + } + + void release( std::size_t index ) { + m_streams[index]->copyfmt( m_referenceStream ); // Restore initial flags and other state + m_unused.push_back(index); + } + + // !TBD: put in TLS + static auto instance() -> StringStreams& { + if( !s_instance ) + s_instance = new StringStreams(); + return *s_instance; + } + static void cleanup() { + delete s_instance; + s_instance = nullptr; + } + }; + + StringStreams* StringStreams::s_instance = nullptr; + + void ReusableStringStream::cleanup() { + StringStreams::cleanup(); + } + + ReusableStringStream::ReusableStringStream() + : m_index( StringStreams::instance().add() ), + m_oss( StringStreams::instance().m_streams[m_index].get() ) + {} + + ReusableStringStream::~ReusableStringStream() { + static_cast( m_oss )->str(""); + m_oss->clear(); + StringStreams::instance().release( m_index ); + } + + auto ReusableStringStream::str() const -> std::string { + return static_cast( m_oss )->str(); + } + + /////////////////////////////////////////////////////////////////////////// + +#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions + std::ostream& cout() { return std::cout; } + std::ostream& cerr() { return std::cerr; } + std::ostream& clog() { return std::clog; } +#endif +} + +#if defined(__clang__) +# pragma clang diagnostic pop +#endif +// end catch_stream.cpp +// start catch_string_manip.cpp + +#include +#include +#include +#include + +namespace Catch { + + bool startsWith( std::string const& s, std::string const& prefix ) { + return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin()); + } + bool startsWith( std::string const& s, char prefix ) { + return !s.empty() && s[0] == prefix; + } + bool endsWith( std::string const& s, std::string const& suffix ) { + return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin()); + } + bool endsWith( std::string const& s, char suffix ) { + return !s.empty() && s[s.size()-1] == suffix; + } + bool contains( std::string const& s, std::string const& infix ) { + return s.find( infix ) != std::string::npos; + } + char toLowerCh(char c) { + return static_cast( std::tolower( c ) ); + } + void toLowerInPlace( std::string& s ) { + std::transform( s.begin(), s.end(), s.begin(), toLowerCh ); + } + std::string toLower( std::string const& s ) { + std::string lc = s; + toLowerInPlace( lc ); + return lc; + } + std::string trim( std::string const& str ) { + static char const* whitespaceChars = "\n\r\t "; + std::string::size_type start = str.find_first_not_of( whitespaceChars ); + std::string::size_type end = str.find_last_not_of( whitespaceChars ); + + return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string(); + } + + bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { + bool replaced = false; + std::size_t i = str.find( replaceThis ); + while( i != std::string::npos ) { + replaced = true; + str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); + if( i < str.size()-withThis.size() ) + i = str.find( replaceThis, i+withThis.size() ); + else + i = std::string::npos; + } + return replaced; + } + + pluralise::pluralise( std::size_t count, std::string const& label ) + : m_count( count ), + m_label( label ) + {} + + std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { + os << pluraliser.m_count << ' ' << pluraliser.m_label; + if( pluraliser.m_count != 1 ) + os << 's'; + return os; + } + +} +// end catch_string_manip.cpp +// start catch_stringref.cpp + +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wexit-time-destructors" +#endif + +#include +#include +#include + +namespace { + const uint32_t byte_2_lead = 0xC0; + const uint32_t byte_3_lead = 0xE0; + const uint32_t byte_4_lead = 0xF0; +} + +namespace Catch { + StringRef::StringRef( char const* rawChars ) noexcept + : StringRef( rawChars, static_cast(std::strlen(rawChars) ) ) + {} + + StringRef::operator std::string() const { + return std::string( m_start, m_size ); + } + + void StringRef::swap( StringRef& other ) noexcept { + std::swap( m_start, other.m_start ); + std::swap( m_size, other.m_size ); + std::swap( m_data, other.m_data ); + } + + auto StringRef::c_str() const -> char const* { + if( isSubstring() ) + const_cast( this )->takeOwnership(); + return m_start; + } + auto StringRef::currentData() const noexcept -> char const* { + return m_start; + } + + auto StringRef::isOwned() const noexcept -> bool { + return m_data != nullptr; + } + auto StringRef::isSubstring() const noexcept -> bool { + return m_start[m_size] != '\0'; + } + + void StringRef::takeOwnership() { + if( !isOwned() ) { + m_data = new char[m_size+1]; + memcpy( m_data, m_start, m_size ); + m_data[m_size] = '\0'; + m_start = m_data; + } + } + auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef { + if( start < m_size ) + return StringRef( m_start+start, size ); + else + return StringRef(); + } + auto StringRef::operator == ( StringRef const& other ) const noexcept -> bool { + return + size() == other.size() && + (std::strncmp( m_start, other.m_start, size() ) == 0); + } + auto StringRef::operator != ( StringRef const& other ) const noexcept -> bool { + return !operator==( other ); + } + + auto StringRef::operator[](size_type index) const noexcept -> char { + return m_start[index]; + } + + auto StringRef::numberOfCharacters() const noexcept -> size_type { + size_type noChars = m_size; + // Make adjustments for uft encodings + for( size_type i=0; i < m_size; ++i ) { + char c = m_start[i]; + if( ( c & byte_2_lead ) == byte_2_lead ) { + noChars--; + if (( c & byte_3_lead ) == byte_3_lead ) + noChars--; + if( ( c & byte_4_lead ) == byte_4_lead ) + noChars--; + } + } + return noChars; + } + + auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string { + std::string str; + str.reserve( lhs.size() + rhs.size() ); + str += lhs; + str += rhs; + return str; + } + auto operator + ( StringRef const& lhs, const char* rhs ) -> std::string { + return std::string( lhs ) + std::string( rhs ); + } + auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string { + return std::string( lhs ) + std::string( rhs ); + } + + auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& { + return os.write(str.currentData(), str.size()); + } + + auto operator+=( std::string& lhs, StringRef const& rhs ) -> std::string& { + lhs.append(rhs.currentData(), rhs.size()); + return lhs; + } + +} // namespace Catch + +#if defined(__clang__) +# pragma clang diagnostic pop +#endif +// end catch_stringref.cpp +// start catch_tag_alias.cpp + +namespace Catch { + TagAlias::TagAlias(std::string const & _tag, SourceLineInfo _lineInfo): tag(_tag), lineInfo(_lineInfo) {} +} +// end catch_tag_alias.cpp +// start catch_tag_alias_autoregistrar.cpp + +namespace Catch { + + RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo) { + try { + getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo); + } catch (...) { + // Do not throw when constructing global objects, instead register the exception to be processed later + getMutableRegistryHub().registerStartupException(); + } + } + +} +// end catch_tag_alias_autoregistrar.cpp +// start catch_tag_alias_registry.cpp + +#include + +namespace Catch { + + TagAliasRegistry::~TagAliasRegistry() {} + + TagAlias const* TagAliasRegistry::find( std::string const& alias ) const { + auto it = m_registry.find( alias ); + if( it != m_registry.end() ) + return &(it->second); + else + return nullptr; + } + + std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { + std::string expandedTestSpec = unexpandedTestSpec; + for( auto const& registryKvp : m_registry ) { + std::size_t pos = expandedTestSpec.find( registryKvp.first ); + if( pos != std::string::npos ) { + expandedTestSpec = expandedTestSpec.substr( 0, pos ) + + registryKvp.second.tag + + expandedTestSpec.substr( pos + registryKvp.first.size() ); + } + } + return expandedTestSpec; + } + + void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) { + CATCH_ENFORCE( startsWith(alias, "[@") && endsWith(alias, ']'), + "error: tag alias, '" << alias << "' is not of the form [@alias name].\n" << lineInfo ); + + CATCH_ENFORCE( m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second, + "error: tag alias, '" << alias << "' already registered.\n" + << "\tFirst seen at: " << find(alias)->lineInfo << "\n" + << "\tRedefined at: " << lineInfo ); + } + + ITagAliasRegistry::~ITagAliasRegistry() {} + + ITagAliasRegistry const& ITagAliasRegistry::get() { + return getRegistryHub().getTagAliasRegistry(); + } + +} // end namespace Catch +// end catch_tag_alias_registry.cpp +// start catch_test_case_info.cpp + +#include +#include +#include +#include + +namespace Catch { + + TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { + if( startsWith( tag, '.' ) || + tag == "!hide" ) + return TestCaseInfo::IsHidden; + else if( tag == "!throws" ) + return TestCaseInfo::Throws; + else if( tag == "!shouldfail" ) + return TestCaseInfo::ShouldFail; + else if( tag == "!mayfail" ) + return TestCaseInfo::MayFail; + else if( tag == "!nonportable" ) + return TestCaseInfo::NonPortable; + else if( tag == "!benchmark" ) + return static_cast( TestCaseInfo::Benchmark | TestCaseInfo::IsHidden ); + else + return TestCaseInfo::None; + } + bool isReservedTag( std::string const& tag ) { + return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( static_cast(tag[0]) ); + } + void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { + CATCH_ENFORCE( !isReservedTag(tag), + "Tag name: [" << tag << "] is not allowed.\n" + << "Tag names starting with non alpha-numeric characters are reserved\n" + << _lineInfo ); + } + + TestCase makeTestCase( ITestInvoker* _testCase, + std::string const& _className, + NameAndTags const& nameAndTags, + SourceLineInfo const& _lineInfo ) + { + bool isHidden = false; + + // Parse out tags + std::vector tags; + std::string desc, tag; + bool inTag = false; + std::string _descOrTags = nameAndTags.tags; + for (char c : _descOrTags) { + if( !inTag ) { + if( c == '[' ) + inTag = true; + else + desc += c; + } + else { + if( c == ']' ) { + TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag ); + if( ( prop & TestCaseInfo::IsHidden ) != 0 ) + isHidden = true; + else if( prop == TestCaseInfo::None ) + enforceNotReservedTag( tag, _lineInfo ); + + tags.push_back( tag ); + tag.clear(); + inTag = false; + } + else + tag += c; + } + } + if( isHidden ) { + tags.push_back( "." ); + } + + TestCaseInfo info( nameAndTags.name, _className, desc, tags, _lineInfo ); + return TestCase( _testCase, std::move(info) ); + } + + void setTags( TestCaseInfo& testCaseInfo, std::vector tags ) { + std::sort(begin(tags), end(tags)); + tags.erase(std::unique(begin(tags), end(tags)), end(tags)); + testCaseInfo.lcaseTags.clear(); + + for( auto const& tag : tags ) { + std::string lcaseTag = toLower( tag ); + testCaseInfo.properties = static_cast( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); + testCaseInfo.lcaseTags.push_back( lcaseTag ); + } + testCaseInfo.tags = std::move(tags); + } + + TestCaseInfo::TestCaseInfo( std::string const& _name, + std::string const& _className, + std::string const& _description, + std::vector const& _tags, + SourceLineInfo const& _lineInfo ) + : name( _name ), + className( _className ), + description( _description ), + lineInfo( _lineInfo ), + properties( None ) + { + setTags( *this, _tags ); + } + + bool TestCaseInfo::isHidden() const { + return ( properties & IsHidden ) != 0; + } + bool TestCaseInfo::throws() const { + return ( properties & Throws ) != 0; + } + bool TestCaseInfo::okToFail() const { + return ( properties & (ShouldFail | MayFail ) ) != 0; + } + bool TestCaseInfo::expectedToFail() const { + return ( properties & (ShouldFail ) ) != 0; + } + + std::string TestCaseInfo::tagsAsString() const { + std::string ret; + // '[' and ']' per tag + std::size_t full_size = 2 * tags.size(); + for (const auto& tag : tags) { + full_size += tag.size(); + } + ret.reserve(full_size); + for (const auto& tag : tags) { + ret.push_back('['); + ret.append(tag); + ret.push_back(']'); + } + + return ret; + } + + TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo&& info ) : TestCaseInfo( std::move(info) ), test( testCase ) {} + + TestCase TestCase::withName( std::string const& _newName ) const { + TestCase other( *this ); + other.name = _newName; + return other; + } + + void TestCase::invoke() const { + test->invoke(); + } + + bool TestCase::operator == ( TestCase const& other ) const { + return test.get() == other.test.get() && + name == other.name && + className == other.className; + } + + bool TestCase::operator < ( TestCase const& other ) const { + return name < other.name; + } + + TestCaseInfo const& TestCase::getTestCaseInfo() const + { + return *this; + } + +} // end namespace Catch +// end catch_test_case_info.cpp +// start catch_test_case_registry_impl.cpp + +#include + +namespace Catch { + + std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { + + std::vector sorted = unsortedTestCases; + + switch( config.runOrder() ) { + case RunTests::InLexicographicalOrder: + std::sort( sorted.begin(), sorted.end() ); + break; + case RunTests::InRandomOrder: + seedRng( config ); + RandomNumberGenerator::shuffle( sorted ); + break; + case RunTests::InDeclarationOrder: + // already in declaration order + break; + } + return sorted; + } + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { + return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); + } + + void enforceNoDuplicateTestCases( std::vector const& functions ) { + std::set seenFunctions; + for( auto const& function : functions ) { + auto prev = seenFunctions.insert( function ); + CATCH_ENFORCE( prev.second, + "error: TEST_CASE( \"" << function.name << "\" ) already defined.\n" + << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n" + << "\tRedefined at " << function.getTestCaseInfo().lineInfo ); + } + } + + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { + std::vector filtered; + filtered.reserve( testCases.size() ); + for( auto const& testCase : testCases ) + if( matchTest( testCase, testSpec, config ) ) + filtered.push_back( testCase ); + return filtered; + } + std::vector const& getAllTestCasesSorted( IConfig const& config ) { + return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); + } + + void TestRegistry::registerTest( TestCase const& testCase ) { + std::string name = testCase.getTestCaseInfo().name; + if( name.empty() ) { + ReusableStringStream rss; + rss << "Anonymous test case " << ++m_unnamedCount; + return registerTest( testCase.withName( rss.str() ) ); + } + m_functions.push_back( testCase ); + } + + std::vector const& TestRegistry::getAllTests() const { + return m_functions; + } + std::vector const& TestRegistry::getAllTestsSorted( IConfig const& config ) const { + if( m_sortedFunctions.empty() ) + enforceNoDuplicateTestCases( m_functions ); + + if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { + m_sortedFunctions = sortTests( config, m_functions ); + m_currentSortOrder = config.runOrder(); + } + return m_sortedFunctions; + } + + /////////////////////////////////////////////////////////////////////////// + TestInvokerAsFunction::TestInvokerAsFunction( void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {} + + void TestInvokerAsFunction::invoke() const { + m_testAsFunction(); + } + + std::string extractClassName( StringRef const& classOrQualifiedMethodName ) { + std::string className = classOrQualifiedMethodName; + if( startsWith( className, '&' ) ) + { + std::size_t lastColons = className.rfind( "::" ); + std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); + if( penultimateColons == std::string::npos ) + penultimateColons = 1; + className = className.substr( penultimateColons, lastColons-penultimateColons ); + } + return className; + } + +} // end namespace Catch +// end catch_test_case_registry_impl.cpp +// start catch_test_case_tracker.cpp + +#include +#include +#include +#include +#include + +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wexit-time-destructors" +#endif + +namespace Catch { +namespace TestCaseTracking { + + NameAndLocation::NameAndLocation( std::string const& _name, SourceLineInfo const& _location ) + : name( _name ), + location( _location ) + {} + + ITracker::~ITracker() = default; + + TrackerContext& TrackerContext::instance() { + static TrackerContext s_instance; + return s_instance; + } + + ITracker& TrackerContext::startRun() { + m_rootTracker = std::make_shared( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr ); + m_currentTracker = nullptr; + m_runState = Executing; + return *m_rootTracker; + } + + void TrackerContext::endRun() { + m_rootTracker.reset(); + m_currentTracker = nullptr; + m_runState = NotStarted; + } + + void TrackerContext::startCycle() { + m_currentTracker = m_rootTracker.get(); + m_runState = Executing; + } + void TrackerContext::completeCycle() { + m_runState = CompletedCycle; + } + + bool TrackerContext::completedCycle() const { + return m_runState == CompletedCycle; + } + ITracker& TrackerContext::currentTracker() { + return *m_currentTracker; + } + void TrackerContext::setCurrentTracker( ITracker* tracker ) { + m_currentTracker = tracker; + } + + TrackerBase::TrackerHasName::TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {} + bool TrackerBase::TrackerHasName::operator ()( ITrackerPtr const& tracker ) const { + return + tracker->nameAndLocation().name == m_nameAndLocation.name && + tracker->nameAndLocation().location == m_nameAndLocation.location; + } + + TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) + : m_nameAndLocation( nameAndLocation ), + m_ctx( ctx ), + m_parent( parent ) + {} + + NameAndLocation const& TrackerBase::nameAndLocation() const { + return m_nameAndLocation; + } + bool TrackerBase::isComplete() const { + return m_runState == CompletedSuccessfully || m_runState == Failed; + } + bool TrackerBase::isSuccessfullyCompleted() const { + return m_runState == CompletedSuccessfully; + } + bool TrackerBase::isOpen() const { + return m_runState != NotStarted && !isComplete(); + } + bool TrackerBase::hasChildren() const { + return !m_children.empty(); + } + + void TrackerBase::addChild( ITrackerPtr const& child ) { + m_children.push_back( child ); + } + + ITrackerPtr TrackerBase::findChild( NameAndLocation const& nameAndLocation ) { + auto it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) ); + return( it != m_children.end() ) + ? *it + : nullptr; + } + ITracker& TrackerBase::parent() { + assert( m_parent ); // Should always be non-null except for root + return *m_parent; + } + + void TrackerBase::openChild() { + if( m_runState != ExecutingChildren ) { + m_runState = ExecutingChildren; + if( m_parent ) + m_parent->openChild(); + } + } + + bool TrackerBase::isSectionTracker() const { return false; } + bool TrackerBase::isIndexTracker() const { return false; } + + void TrackerBase::open() { + m_runState = Executing; + moveToThis(); + if( m_parent ) + m_parent->openChild(); + } + + void TrackerBase::close() { + + // Close any still open children (e.g. generators) + while( &m_ctx.currentTracker() != this ) + m_ctx.currentTracker().close(); + + switch( m_runState ) { + case NeedsAnotherRun: + break; + + case Executing: + m_runState = CompletedSuccessfully; + break; + case ExecutingChildren: + if( m_children.empty() || m_children.back()->isComplete() ) + m_runState = CompletedSuccessfully; + break; + + case NotStarted: + case CompletedSuccessfully: + case Failed: + CATCH_INTERNAL_ERROR( "Illogical state: " << m_runState ); + + default: + CATCH_INTERNAL_ERROR( "Unknown state: " << m_runState ); + } + moveToParent(); + m_ctx.completeCycle(); + } + void TrackerBase::fail() { + m_runState = Failed; + if( m_parent ) + m_parent->markAsNeedingAnotherRun(); + moveToParent(); + m_ctx.completeCycle(); + } + void TrackerBase::markAsNeedingAnotherRun() { + m_runState = NeedsAnotherRun; + } + + void TrackerBase::moveToParent() { + assert( m_parent ); + m_ctx.setCurrentTracker( m_parent ); + } + void TrackerBase::moveToThis() { + m_ctx.setCurrentTracker( this ); + } + + SectionTracker::SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) + : TrackerBase( nameAndLocation, ctx, parent ) + { + if( parent ) { + while( !parent->isSectionTracker() ) + parent = &parent->parent(); + + SectionTracker& parentSection = static_cast( *parent ); + addNextFilters( parentSection.m_filters ); + } + } + + bool SectionTracker::isSectionTracker() const { return true; } + + SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) { + std::shared_ptr section; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { + assert( childTracker ); + assert( childTracker->isSectionTracker() ); + section = std::static_pointer_cast( childTracker ); + } + else { + section = std::make_shared( nameAndLocation, ctx, ¤tTracker ); + currentTracker.addChild( section ); + } + if( !ctx.completedCycle() ) + section->tryOpen(); + return *section; + } + + void SectionTracker::tryOpen() { + if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) ) + open(); + } + + void SectionTracker::addInitialFilters( std::vector const& filters ) { + if( !filters.empty() ) { + m_filters.push_back(""); // Root - should never be consulted + m_filters.push_back(""); // Test Case - not a section filter + m_filters.insert( m_filters.end(), filters.begin(), filters.end() ); + } + } + void SectionTracker::addNextFilters( std::vector const& filters ) { + if( filters.size() > 1 ) + m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() ); + } + + IndexTracker::IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size ) + : TrackerBase( nameAndLocation, ctx, parent ), + m_size( size ) + {} + + bool IndexTracker::isIndexTracker() const { return true; } + + IndexTracker& IndexTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) { + std::shared_ptr tracker; + + ITracker& currentTracker = ctx.currentTracker(); + if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) { + assert( childTracker ); + assert( childTracker->isIndexTracker() ); + tracker = std::static_pointer_cast( childTracker ); + } + else { + tracker = std::make_shared( nameAndLocation, ctx, ¤tTracker, size ); + currentTracker.addChild( tracker ); + } + + if( !ctx.completedCycle() && !tracker->isComplete() ) { + if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) + tracker->moveNext(); + tracker->open(); + } + + return *tracker; + } + + int IndexTracker::index() const { return m_index; } + + void IndexTracker::moveNext() { + m_index++; + m_children.clear(); + } + + void IndexTracker::close() { + TrackerBase::close(); + if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) + m_runState = Executing; + } + +} // namespace TestCaseTracking + +using TestCaseTracking::ITracker; +using TestCaseTracking::TrackerContext; +using TestCaseTracking::SectionTracker; +using TestCaseTracking::IndexTracker; + +} // namespace Catch + +#if defined(__clang__) +# pragma clang diagnostic pop +#endif +// end catch_test_case_tracker.cpp +// start catch_test_registry.cpp + +namespace Catch { + + auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker* { + return new(std::nothrow) TestInvokerAsFunction( testAsFunction ); + } + + NameAndTags::NameAndTags( StringRef const& name_ , StringRef const& tags_ ) noexcept : name( name_ ), tags( tags_ ) {} + + AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept { + try { + getMutableRegistryHub() + .registerTest( + makeTestCase( + invoker, + extractClassName( classOrMethod ), + nameAndTags, + lineInfo)); + } catch (...) { + // Do not throw when constructing global objects, instead register the exception to be processed later + getMutableRegistryHub().registerStartupException(); + } + } + + AutoReg::~AutoReg() = default; +} +// end catch_test_registry.cpp +// start catch_test_spec.cpp + +#include +#include +#include +#include + +namespace Catch { + + TestSpec::Pattern::~Pattern() = default; + TestSpec::NamePattern::~NamePattern() = default; + TestSpec::TagPattern::~TagPattern() = default; + TestSpec::ExcludedPattern::~ExcludedPattern() = default; + + TestSpec::NamePattern::NamePattern( std::string const& name ) + : m_wildcardPattern( toLower( name ), CaseSensitive::No ) + {} + bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const { + return m_wildcardPattern.matches( toLower( testCase.name ) ); + } + + TestSpec::TagPattern::TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} + bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const { + return std::find(begin(testCase.lcaseTags), + end(testCase.lcaseTags), + m_tag) != end(testCase.lcaseTags); + } + + TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} + bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } + + bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const { + // All patterns in a filter must match for the filter to be a match + for( auto const& pattern : m_patterns ) { + if( !pattern->matches( testCase ) ) + return false; + } + return true; + } + + bool TestSpec::hasFilters() const { + return !m_filters.empty(); + } + bool TestSpec::matches( TestCaseInfo const& testCase ) const { + // A TestSpec matches if any filter matches + for( auto const& filter : m_filters ) + if( filter.matches( testCase ) ) + return true; + return false; + } +} +// end catch_test_spec.cpp +// start catch_test_spec_parser.cpp + +namespace Catch { + + TestSpecParser::TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} + + TestSpecParser& TestSpecParser::parse( std::string const& arg ) { + m_mode = None; + m_exclusion = false; + m_start = std::string::npos; + m_arg = m_tagAliases->expandAliases( arg ); + m_escapeChars.clear(); + for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) + visitChar( m_arg[m_pos] ); + if( m_mode == Name ) + addPattern(); + return *this; + } + TestSpec TestSpecParser::testSpec() { + addFilter(); + return m_testSpec; + } + + void TestSpecParser::visitChar( char c ) { + if( m_mode == None ) { + switch( c ) { + case ' ': return; + case '~': m_exclusion = true; return; + case '[': return startNewMode( Tag, ++m_pos ); + case '"': return startNewMode( QuotedName, ++m_pos ); + case '\\': return escape(); + default: startNewMode( Name, m_pos ); break; + } + } + if( m_mode == Name ) { + if( c == ',' ) { + addPattern(); + addFilter(); + } + else if( c == '[' ) { + if( subString() == "exclude:" ) + m_exclusion = true; + else + addPattern(); + startNewMode( Tag, ++m_pos ); + } + else if( c == '\\' ) + escape(); + } + else if( m_mode == EscapedName ) + m_mode = Name; + else if( m_mode == QuotedName && c == '"' ) + addPattern(); + else if( m_mode == Tag && c == ']' ) + addPattern(); + } + void TestSpecParser::startNewMode( Mode mode, std::size_t start ) { + m_mode = mode; + m_start = start; + } + void TestSpecParser::escape() { + if( m_mode == None ) + m_start = m_pos; + m_mode = EscapedName; + m_escapeChars.push_back( m_pos ); + } + std::string TestSpecParser::subString() const { return m_arg.substr( m_start, m_pos - m_start ); } + + void TestSpecParser::addFilter() { + if( !m_currentFilter.m_patterns.empty() ) { + m_testSpec.m_filters.push_back( m_currentFilter ); + m_currentFilter = TestSpec::Filter(); + } + } + + TestSpec parseTestSpec( std::string const& arg ) { + return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); + } + +} // namespace Catch +// end catch_test_spec_parser.cpp +// start catch_timer.cpp + +#include + +static const uint64_t nanosecondsInSecond = 1000000000; + +namespace Catch { + + auto getCurrentNanosecondsSinceEpoch() -> uint64_t { + return std::chrono::duration_cast( std::chrono::high_resolution_clock::now().time_since_epoch() ).count(); + } + + auto estimateClockResolution() -> uint64_t { + uint64_t sum = 0; + static const uint64_t iterations = 1000000; + + auto startTime = getCurrentNanosecondsSinceEpoch(); + + for( std::size_t i = 0; i < iterations; ++i ) { + + uint64_t ticks; + uint64_t baseTicks = getCurrentNanosecondsSinceEpoch(); + do { + ticks = getCurrentNanosecondsSinceEpoch(); + } while( ticks == baseTicks ); + + auto delta = ticks - baseTicks; + sum += delta; + + // If we have been calibrating for over 3 seconds -- the clock + // is terrible and we should move on. + // TBD: How to signal that the measured resolution is probably wrong? + if (ticks > startTime + 3 * nanosecondsInSecond) { + return sum / i; + } + } + + // We're just taking the mean, here. To do better we could take the std. dev and exclude outliers + // - and potentially do more iterations if there's a high variance. + return sum/iterations; + } + auto getEstimatedClockResolution() -> uint64_t { + static auto s_resolution = estimateClockResolution(); + return s_resolution; + } + + void Timer::start() { + m_nanoseconds = getCurrentNanosecondsSinceEpoch(); + } + auto Timer::getElapsedNanoseconds() const -> uint64_t { + return getCurrentNanosecondsSinceEpoch() - m_nanoseconds; + } + auto Timer::getElapsedMicroseconds() const -> uint64_t { + return getElapsedNanoseconds()/1000; + } + auto Timer::getElapsedMilliseconds() const -> unsigned int { + return static_cast(getElapsedMicroseconds()/1000); + } + auto Timer::getElapsedSeconds() const -> double { + return getElapsedMicroseconds()/1000000.0; + } + +} // namespace Catch +// end catch_timer.cpp +// start catch_tostring.cpp + +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wexit-time-destructors" +# pragma clang diagnostic ignored "-Wglobal-constructors" +#endif + +// Enable specific decls locally +#if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) +#define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER +#endif + +#include +#include + +namespace Catch { + +namespace Detail { + + const std::string unprintableString = "{?}"; + + namespace { + const int hexThreshold = 255; + + struct Endianness { + enum Arch { Big, Little }; + + static Arch which() { + union _{ + int asInt; + char asChar[sizeof (int)]; + } u; + + u.asInt = 1; + return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; + } + }; + } + + std::string rawMemoryToString( const void *object, std::size_t size ) { + // Reverse order for little endian architectures + int i = 0, end = static_cast( size ), inc = 1; + if( Endianness::which() == Endianness::Little ) { + i = end-1; + end = inc = -1; + } + + unsigned char const *bytes = static_cast(object); + ReusableStringStream rss; + rss << "0x" << std::setfill('0') << std::hex; + for( ; i != end; i += inc ) + rss << std::setw(2) << static_cast(bytes[i]); + return rss.str(); + } +} + +template +std::string fpToString( T value, int precision ) { + if (std::isnan(value)) { + return "nan"; + } + + ReusableStringStream rss; + rss << std::setprecision( precision ) + << std::fixed + << value; + std::string d = rss.str(); + std::size_t i = d.find_last_not_of( '0' ); + if( i != std::string::npos && i != d.size()-1 ) { + if( d[i] == '.' ) + i++; + d = d.substr( 0, i+1 ); + } + return d; +} + +//// ======================================================= //// +// +// Out-of-line defs for full specialization of StringMaker +// +//// ======================================================= //// + +std::string StringMaker::convert(const std::string& str) { + if (!getCurrentContext().getConfig()->showInvisibles()) { + return '"' + str + '"'; + } + + std::string s("\""); + for (char c : str) { + switch (c) { + case '\n': + s.append("\\n"); + break; + case '\t': + s.append("\\t"); + break; + default: + s.push_back(c); + break; + } + } + s.append("\""); + return s; +} + +#ifdef CATCH_CONFIG_WCHAR +std::string StringMaker::convert(const std::wstring& wstr) { + std::string s; + s.reserve(wstr.size()); + for (auto c : wstr) { + s += (c <= 0xff) ? static_cast(c) : '?'; + } + return ::Catch::Detail::stringify(s); +} +#endif + +std::string StringMaker::convert(char const* str) { + if (str) { + return ::Catch::Detail::stringify(std::string{ str }); + } else { + return{ "{null string}" }; + } +} +std::string StringMaker::convert(char* str) { + if (str) { + return ::Catch::Detail::stringify(std::string{ str }); + } else { + return{ "{null string}" }; + } +} +#ifdef CATCH_CONFIG_WCHAR +std::string StringMaker::convert(wchar_t const * str) { + if (str) { + return ::Catch::Detail::stringify(std::wstring{ str }); + } else { + return{ "{null string}" }; + } +} +std::string StringMaker::convert(wchar_t * str) { + if (str) { + return ::Catch::Detail::stringify(std::wstring{ str }); + } else { + return{ "{null string}" }; + } +} +#endif + +std::string StringMaker::convert(int value) { + return ::Catch::Detail::stringify(static_cast(value)); +} +std::string StringMaker::convert(long value) { + return ::Catch::Detail::stringify(static_cast(value)); +} +std::string StringMaker::convert(long long value) { + ReusableStringStream rss; + rss << value; + if (value > Detail::hexThreshold) { + rss << " (0x" << std::hex << value << ')'; + } + return rss.str(); +} + +std::string StringMaker::convert(unsigned int value) { + return ::Catch::Detail::stringify(static_cast(value)); +} +std::string StringMaker::convert(unsigned long value) { + return ::Catch::Detail::stringify(static_cast(value)); +} +std::string StringMaker::convert(unsigned long long value) { + ReusableStringStream rss; + rss << value; + if (value > Detail::hexThreshold) { + rss << " (0x" << std::hex << value << ')'; + } + return rss.str(); +} + +std::string StringMaker::convert(bool b) { + return b ? "true" : "false"; +} + +std::string StringMaker::convert(char value) { + if (value == '\r') { + return "'\\r'"; + } else if (value == '\f') { + return "'\\f'"; + } else if (value == '\n') { + return "'\\n'"; + } else if (value == '\t') { + return "'\\t'"; + } else if ('\0' <= value && value < ' ') { + return ::Catch::Detail::stringify(static_cast(value)); + } else { + char chstr[] = "' '"; + chstr[1] = value; + return chstr; + } +} +std::string StringMaker::convert(signed char c) { + return ::Catch::Detail::stringify(static_cast(c)); +} +std::string StringMaker::convert(unsigned char c) { + return ::Catch::Detail::stringify(static_cast(c)); +} + +std::string StringMaker::convert(std::nullptr_t) { + return "nullptr"; +} + +std::string StringMaker::convert(float value) { + return fpToString(value, 5) + 'f'; +} +std::string StringMaker::convert(double value) { + return fpToString(value, 10); +} + +std::string ratio_string::symbol() { return "a"; } +std::string ratio_string::symbol() { return "f"; } +std::string ratio_string::symbol() { return "p"; } +std::string ratio_string::symbol() { return "n"; } +std::string ratio_string::symbol() { return "u"; } +std::string ratio_string::symbol() { return "m"; } + +} // end namespace Catch + +#if defined(__clang__) +# pragma clang diagnostic pop +#endif + +// end catch_tostring.cpp +// start catch_totals.cpp + +namespace Catch { + + Counts Counts::operator - ( Counts const& other ) const { + Counts diff; + diff.passed = passed - other.passed; + diff.failed = failed - other.failed; + diff.failedButOk = failedButOk - other.failedButOk; + return diff; + } + + Counts& Counts::operator += ( Counts const& other ) { + passed += other.passed; + failed += other.failed; + failedButOk += other.failedButOk; + return *this; + } + + std::size_t Counts::total() const { + return passed + failed + failedButOk; + } + bool Counts::allPassed() const { + return failed == 0 && failedButOk == 0; + } + bool Counts::allOk() const { + return failed == 0; + } + + Totals Totals::operator - ( Totals const& other ) const { + Totals diff; + diff.assertions = assertions - other.assertions; + diff.testCases = testCases - other.testCases; + return diff; + } + + Totals& Totals::operator += ( Totals const& other ) { + assertions += other.assertions; + testCases += other.testCases; + return *this; + } + + Totals Totals::delta( Totals const& prevTotals ) const { + Totals diff = *this - prevTotals; + if( diff.assertions.failed > 0 ) + ++diff.testCases.failed; + else if( diff.assertions.failedButOk > 0 ) + ++diff.testCases.failedButOk; + else + ++diff.testCases.passed; + return diff; + } + +} +// end catch_totals.cpp +// start catch_uncaught_exceptions.cpp + +#include + +namespace Catch { + bool uncaught_exceptions() { +#if defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) + return std::uncaught_exceptions() > 0; +#else + return std::uncaught_exception(); +#endif + } +} // end namespace Catch +// end catch_uncaught_exceptions.cpp +// start catch_version.cpp + +#include + +namespace Catch { + + Version::Version + ( unsigned int _majorVersion, + unsigned int _minorVersion, + unsigned int _patchNumber, + char const * const _branchName, + unsigned int _buildNumber ) + : majorVersion( _majorVersion ), + minorVersion( _minorVersion ), + patchNumber( _patchNumber ), + branchName( _branchName ), + buildNumber( _buildNumber ) + {} + + std::ostream& operator << ( std::ostream& os, Version const& version ) { + os << version.majorVersion << '.' + << version.minorVersion << '.' + << version.patchNumber; + // branchName is never null -> 0th char is \0 if it is empty + if (version.branchName[0]) { + os << '-' << version.branchName + << '.' << version.buildNumber; + } + return os; + } + + Version const& libraryVersion() { + static Version version( 2, 2, 3, "", 0 ); + return version; + } + +} +// end catch_version.cpp +// start catch_wildcard_pattern.cpp + +#include + +namespace Catch { + + WildcardPattern::WildcardPattern( std::string const& pattern, + CaseSensitive::Choice caseSensitivity ) + : m_caseSensitivity( caseSensitivity ), + m_pattern( adjustCase( pattern ) ) + { + if( startsWith( m_pattern, '*' ) ) { + m_pattern = m_pattern.substr( 1 ); + m_wildcard = WildcardAtStart; + } + if( endsWith( m_pattern, '*' ) ) { + m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); + m_wildcard = static_cast( m_wildcard | WildcardAtEnd ); + } + } + + bool WildcardPattern::matches( std::string const& str ) const { + switch( m_wildcard ) { + case NoWildcard: + return m_pattern == adjustCase( str ); + case WildcardAtStart: + return endsWith( adjustCase( str ), m_pattern ); + case WildcardAtEnd: + return startsWith( adjustCase( str ), m_pattern ); + case WildcardAtBothEnds: + return contains( adjustCase( str ), m_pattern ); + default: + CATCH_INTERNAL_ERROR( "Unknown enum" ); + } + } + + std::string WildcardPattern::adjustCase( std::string const& str ) const { + return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; + } +} +// end catch_wildcard_pattern.cpp +// start catch_xmlwriter.cpp + +#include + +using uchar = unsigned char; + +namespace Catch { + +namespace { + + size_t trailingBytes(unsigned char c) { + if ((c & 0xE0) == 0xC0) { + return 2; + } + if ((c & 0xF0) == 0xE0) { + return 3; + } + if ((c & 0xF8) == 0xF0) { + return 4; + } + CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); + } + + uint32_t headerValue(unsigned char c) { + if ((c & 0xE0) == 0xC0) { + return c & 0x1F; + } + if ((c & 0xF0) == 0xE0) { + return c & 0x0F; + } + if ((c & 0xF8) == 0xF0) { + return c & 0x07; + } + CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered"); + } + + void hexEscapeChar(std::ostream& os, unsigned char c) { + os << "\\x" + << std::uppercase << std::hex << std::setfill('0') << std::setw(2) + << static_cast(c); + } + +} // anonymous namespace + + XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat ) + : m_str( str ), + m_forWhat( forWhat ) + {} + + void XmlEncode::encodeTo( std::ostream& os ) const { + // Apostrophe escaping not necessary if we always use " to write attributes + // (see: http://www.w3.org/TR/xml/#syntax) + + for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) { + uchar c = m_str[idx]; + switch (c) { + case '<': os << "<"; break; + case '&': os << "&"; break; + + case '>': + // See: http://www.w3.org/TR/xml/#syntax + if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']') + os << ">"; + else + os << c; + break; + + case '\"': + if (m_forWhat == ForAttributes) + os << """; + else + os << c; + break; + + default: + // Check for control characters and invalid utf-8 + + // Escape control characters in standard ascii + // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 + if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) { + hexEscapeChar(os, c); + break; + } + + // Plain ASCII: Write it to stream + if (c < 0x7F) { + os << c; + break; + } + + // UTF-8 territory + // Check if the encoding is valid and if it is not, hex escape bytes. + // Important: We do not check the exact decoded values for validity, only the encoding format + // First check that this bytes is a valid lead byte: + // This means that it is not encoded as 1111 1XXX + // Or as 10XX XXXX + if (c < 0xC0 || + c >= 0xF8) { + hexEscapeChar(os, c); + break; + } + + auto encBytes = trailingBytes(c); + // Are there enough bytes left to avoid accessing out-of-bounds memory? + if (idx + encBytes - 1 >= m_str.size()) { + hexEscapeChar(os, c); + break; + } + // The header is valid, check data + // The next encBytes bytes must together be a valid utf-8 + // This means: bitpattern 10XX XXXX and the extracted value is sane (ish) + bool valid = true; + uint32_t value = headerValue(c); + for (std::size_t n = 1; n < encBytes; ++n) { + uchar nc = m_str[idx + n]; + valid &= ((nc & 0xC0) == 0x80); + value = (value << 6) | (nc & 0x3F); + } + + if ( + // Wrong bit pattern of following bytes + (!valid) || + // Overlong encodings + (value < 0x80) || + (0x80 <= value && value < 0x800 && encBytes > 2) || + (0x800 < value && value < 0x10000 && encBytes > 3) || + // Encoded value out of range + (value >= 0x110000) + ) { + hexEscapeChar(os, c); + break; + } + + // If we got here, this is in fact a valid(ish) utf-8 sequence + for (std::size_t n = 0; n < encBytes; ++n) { + os << m_str[idx + n]; + } + idx += encBytes - 1; + break; + } + } + } + + std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { + xmlEncode.encodeTo( os ); + return os; + } + + XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer ) + : m_writer( writer ) + {} + + XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept + : m_writer( other.m_writer ){ + other.m_writer = nullptr; + } + XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept { + if ( m_writer ) { + m_writer->endElement(); + } + m_writer = other.m_writer; + other.m_writer = nullptr; + return *this; + } + + XmlWriter::ScopedElement::~ScopedElement() { + if( m_writer ) + m_writer->endElement(); + } + + XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, bool indent ) { + m_writer->writeText( text, indent ); + return *this; + } + + XmlWriter::XmlWriter( std::ostream& os ) : m_os( os ) + { + writeDeclaration(); + } + + XmlWriter::~XmlWriter() { + while( !m_tags.empty() ) + endElement(); + } + + XmlWriter& XmlWriter::startElement( std::string const& name ) { + ensureTagClosed(); + newlineIfNecessary(); + m_os << m_indent << '<' << name; + m_tags.push_back( name ); + m_indent += " "; + m_tagIsOpen = true; + return *this; + } + + XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name ) { + ScopedElement scoped( this ); + startElement( name ); + return scoped; + } + + XmlWriter& XmlWriter::endElement() { + newlineIfNecessary(); + m_indent = m_indent.substr( 0, m_indent.size()-2 ); + if( m_tagIsOpen ) { + m_os << "/>"; + m_tagIsOpen = false; + } + else { + m_os << m_indent << ""; + } + m_os << std::endl; + m_tags.pop_back(); + return *this; + } + + XmlWriter& XmlWriter::writeAttribute( std::string const& name, std::string const& attribute ) { + if( !name.empty() && !attribute.empty() ) + m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; + return *this; + } + + XmlWriter& XmlWriter::writeAttribute( std::string const& name, bool attribute ) { + m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"'; + return *this; + } + + XmlWriter& XmlWriter::writeText( std::string const& text, bool indent ) { + if( !text.empty() ){ + bool tagWasOpen = m_tagIsOpen; + ensureTagClosed(); + if( tagWasOpen && indent ) + m_os << m_indent; + m_os << XmlEncode( text ); + m_needsNewline = true; + } + return *this; + } + + XmlWriter& XmlWriter::writeComment( std::string const& text ) { + ensureTagClosed(); + m_os << m_indent << ""; + m_needsNewline = true; + return *this; + } + + void XmlWriter::writeStylesheetRef( std::string const& url ) { + m_os << "\n"; + } + + XmlWriter& XmlWriter::writeBlankLine() { + ensureTagClosed(); + m_os << '\n'; + return *this; + } + + void XmlWriter::ensureTagClosed() { + if( m_tagIsOpen ) { + m_os << ">" << std::endl; + m_tagIsOpen = false; + } + } + + void XmlWriter::writeDeclaration() { + m_os << "\n"; + } + + void XmlWriter::newlineIfNecessary() { + if( m_needsNewline ) { + m_os << std::endl; + m_needsNewline = false; + } + } +} +// end catch_xmlwriter.cpp +// start catch_reporter_bases.cpp + +#include +#include +#include +#include +#include + +namespace Catch { + void prepareExpandedExpression(AssertionResult& result) { + result.getExpandedExpression(); + } + + // Because formatting using c++ streams is stateful, drop down to C is required + // Alternatively we could use stringstream, but its performance is... not good. + std::string getFormattedDuration( double duration ) { + // Max exponent + 1 is required to represent the whole part + // + 1 for decimal point + // + 3 for the 3 decimal places + // + 1 for null terminator + const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; + char buffer[maxDoubleSize]; + + // Save previous errno, to prevent sprintf from overwriting it + ErrnoGuard guard; +#ifdef _MSC_VER + sprintf_s(buffer, "%.3f", duration); +#else + sprintf(buffer, "%.3f", duration); +#endif + return std::string(buffer); + } + + TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config) + :StreamingReporterBase(_config) {} + + void TestEventListenerBase::assertionStarting(AssertionInfo const &) {} + + bool TestEventListenerBase::assertionEnded(AssertionStats const &) { + return false; + } + +} // end namespace Catch +// end catch_reporter_bases.cpp +// start catch_reporter_compact.cpp + +namespace { + +#ifdef CATCH_PLATFORM_MAC + const char* failedString() { return "FAILED"; } + const char* passedString() { return "PASSED"; } +#else + const char* failedString() { return "failed"; } + const char* passedString() { return "passed"; } +#endif + + // Colour::LightGrey + Catch::Colour::Code dimColour() { return Catch::Colour::FileName; } + + std::string bothOrAll( std::size_t count ) { + return count == 1 ? std::string() : + count == 2 ? "both " : "all " ; + } + +} // anon namespace + +namespace Catch { +namespace { +// Colour, message variants: +// - white: No tests ran. +// - red: Failed [both/all] N test cases, failed [both/all] M assertions. +// - white: Passed [both/all] N test cases (no assertions). +// - red: Failed N tests cases, failed M assertions. +// - green: Passed [both/all] N tests cases with M assertions. +void printTotals(std::ostream& out, const Totals& totals) { + if (totals.testCases.total() == 0) { + out << "No tests ran."; + } else if (totals.testCases.failed == totals.testCases.total()) { + Colour colour(Colour::ResultError); + const std::string qualify_assertions_failed = + totals.assertions.failed == totals.assertions.total() ? + bothOrAll(totals.assertions.failed) : std::string(); + out << + "Failed " << bothOrAll(totals.testCases.failed) + << pluralise(totals.testCases.failed, "test case") << ", " + "failed " << qualify_assertions_failed << + pluralise(totals.assertions.failed, "assertion") << '.'; + } else if (totals.assertions.total() == 0) { + out << + "Passed " << bothOrAll(totals.testCases.total()) + << pluralise(totals.testCases.total(), "test case") + << " (no assertions)."; + } else if (totals.assertions.failed) { + Colour colour(Colour::ResultError); + out << + "Failed " << pluralise(totals.testCases.failed, "test case") << ", " + "failed " << pluralise(totals.assertions.failed, "assertion") << '.'; + } else { + Colour colour(Colour::ResultSuccess); + out << + "Passed " << bothOrAll(totals.testCases.passed) + << pluralise(totals.testCases.passed, "test case") << + " with " << pluralise(totals.assertions.passed, "assertion") << '.'; + } +} + +// Implementation of CompactReporter formatting +class AssertionPrinter { +public: + AssertionPrinter& operator= (AssertionPrinter const&) = delete; + AssertionPrinter(AssertionPrinter const&) = delete; + AssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages) + : stream(_stream) + , result(_stats.assertionResult) + , messages(_stats.infoMessages) + , itMessage(_stats.infoMessages.begin()) + , printInfoMessages(_printInfoMessages) {} + + void print() { + printSourceInfo(); + + itMessage = messages.begin(); + + switch (result.getResultType()) { + case ResultWas::Ok: + printResultType(Colour::ResultSuccess, passedString()); + printOriginalExpression(); + printReconstructedExpression(); + if (!result.hasExpression()) + printRemainingMessages(Colour::None); + else + printRemainingMessages(); + break; + case ResultWas::ExpressionFailed: + if (result.isOk()) + printResultType(Colour::ResultSuccess, failedString() + std::string(" - but was ok")); + else + printResultType(Colour::Error, failedString()); + printOriginalExpression(); + printReconstructedExpression(); + printRemainingMessages(); + break; + case ResultWas::ThrewException: + printResultType(Colour::Error, failedString()); + printIssue("unexpected exception with message:"); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::FatalErrorCondition: + printResultType(Colour::Error, failedString()); + printIssue("fatal error condition with message:"); + printMessage(); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::DidntThrowException: + printResultType(Colour::Error, failedString()); + printIssue("expected exception, got none"); + printExpressionWas(); + printRemainingMessages(); + break; + case ResultWas::Info: + printResultType(Colour::None, "info"); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::Warning: + printResultType(Colour::None, "warning"); + printMessage(); + printRemainingMessages(); + break; + case ResultWas::ExplicitFailure: + printResultType(Colour::Error, failedString()); + printIssue("explicitly"); + printRemainingMessages(Colour::None); + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + printResultType(Colour::Error, "** internal error **"); + break; + } + } + +private: + void printSourceInfo() const { + Colour colourGuard(Colour::FileName); + stream << result.getSourceInfo() << ':'; + } + + void printResultType(Colour::Code colour, std::string const& passOrFail) const { + if (!passOrFail.empty()) { + { + Colour colourGuard(colour); + stream << ' ' << passOrFail; + } + stream << ':'; + } + } + + void printIssue(std::string const& issue) const { + stream << ' ' << issue; + } + + void printExpressionWas() { + if (result.hasExpression()) { + stream << ';'; + { + Colour colour(dimColour()); + stream << " expression was:"; + } + printOriginalExpression(); + } + } + + void printOriginalExpression() const { + if (result.hasExpression()) { + stream << ' ' << result.getExpression(); + } + } + + void printReconstructedExpression() const { + if (result.hasExpandedExpression()) { + { + Colour colour(dimColour()); + stream << " for: "; + } + stream << result.getExpandedExpression(); + } + } + + void printMessage() { + if (itMessage != messages.end()) { + stream << " '" << itMessage->message << '\''; + ++itMessage; + } + } + + void printRemainingMessages(Colour::Code colour = dimColour()) { + if (itMessage == messages.end()) + return; + + // using messages.end() directly yields (or auto) compilation error: + std::vector::const_iterator itEnd = messages.end(); + const std::size_t N = static_cast(std::distance(itMessage, itEnd)); + + { + Colour colourGuard(colour); + stream << " with " << pluralise(N, "message") << ':'; + } + + for (; itMessage != itEnd; ) { + // If this assertion is a warning ignore any INFO messages + if (printInfoMessages || itMessage->type != ResultWas::Info) { + stream << " '" << itMessage->message << '\''; + if (++itMessage != itEnd) { + Colour colourGuard(dimColour()); + stream << " and"; + } + } + } + } + +private: + std::ostream& stream; + AssertionResult const& result; + std::vector messages; + std::vector::const_iterator itMessage; + bool printInfoMessages; +}; + +} // anon namespace + + std::string CompactReporter::getDescription() { + return "Reports test results on a single line, suitable for IDEs"; + } + + ReporterPreferences CompactReporter::getPreferences() const { + ReporterPreferences prefs; + prefs.shouldRedirectStdOut = false; + return prefs; + } + + void CompactReporter::noMatchingTestCases( std::string const& spec ) { + stream << "No test cases matched '" << spec << '\'' << std::endl; + } + + void CompactReporter::assertionStarting( AssertionInfo const& ) {} + + bool CompactReporter::assertionEnded( AssertionStats const& _assertionStats ) { + AssertionResult const& result = _assertionStats.assertionResult; + + bool printInfoMessages = true; + + // Drop out if result was successful and we're not printing those + if( !m_config->includeSuccessfulResults() && result.isOk() ) { + if( result.getResultType() != ResultWas::Warning ) + return false; + printInfoMessages = false; + } + + AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); + printer.print(); + + stream << std::endl; + return true; + } + + void CompactReporter::sectionEnded(SectionStats const& _sectionStats) { + if (m_config->showDurations() == ShowDurations::Always) { + stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; + } + } + + void CompactReporter::testRunEnded( TestRunStats const& _testRunStats ) { + printTotals( stream, _testRunStats.totals ); + stream << '\n' << std::endl; + StreamingReporterBase::testRunEnded( _testRunStats ); + } + + CompactReporter::~CompactReporter() {} + + CATCH_REGISTER_REPORTER( "compact", CompactReporter ) + +} // end namespace Catch +// end catch_reporter_compact.cpp +// start catch_reporter_console.cpp + +#include +#include + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch + // Note that 4062 (not all labels are handled + // and default is missing) is enabled +#endif + +namespace Catch { + +namespace { + +// Formatter impl for ConsoleReporter +class ConsoleAssertionPrinter { +public: + ConsoleAssertionPrinter& operator= (ConsoleAssertionPrinter const&) = delete; + ConsoleAssertionPrinter(ConsoleAssertionPrinter const&) = delete; + ConsoleAssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages) + : stream(_stream), + stats(_stats), + result(_stats.assertionResult), + colour(Colour::None), + message(result.getMessage()), + messages(_stats.infoMessages), + printInfoMessages(_printInfoMessages) { + switch (result.getResultType()) { + case ResultWas::Ok: + colour = Colour::Success; + passOrFail = "PASSED"; + //if( result.hasMessage() ) + if (_stats.infoMessages.size() == 1) + messageLabel = "with message"; + if (_stats.infoMessages.size() > 1) + messageLabel = "with messages"; + break; + case ResultWas::ExpressionFailed: + if (result.isOk()) { + colour = Colour::Success; + passOrFail = "FAILED - but was ok"; + } else { + colour = Colour::Error; + passOrFail = "FAILED"; + } + if (_stats.infoMessages.size() == 1) + messageLabel = "with message"; + if (_stats.infoMessages.size() > 1) + messageLabel = "with messages"; + break; + case ResultWas::ThrewException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to unexpected exception with "; + if (_stats.infoMessages.size() == 1) + messageLabel += "message"; + if (_stats.infoMessages.size() > 1) + messageLabel += "messages"; + break; + case ResultWas::FatalErrorCondition: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "due to a fatal error condition"; + break; + case ResultWas::DidntThrowException: + colour = Colour::Error; + passOrFail = "FAILED"; + messageLabel = "because no exception was thrown where one was expected"; + break; + case ResultWas::Info: + messageLabel = "info"; + break; + case ResultWas::Warning: + messageLabel = "warning"; + break; + case ResultWas::ExplicitFailure: + passOrFail = "FAILED"; + colour = Colour::Error; + if (_stats.infoMessages.size() == 1) + messageLabel = "explicitly with message"; + if (_stats.infoMessages.size() > 1) + messageLabel = "explicitly with messages"; + break; + // These cases are here to prevent compiler warnings + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + passOrFail = "** internal error **"; + colour = Colour::Error; + break; + } + } + + void print() const { + printSourceInfo(); + if (stats.totals.assertions.total() > 0) { + if (result.isOk()) + stream << '\n'; + printResultType(); + printOriginalExpression(); + printReconstructedExpression(); + } else { + stream << '\n'; + } + printMessage(); + } + +private: + void printResultType() const { + if (!passOrFail.empty()) { + Colour colourGuard(colour); + stream << passOrFail << ":\n"; + } + } + void printOriginalExpression() const { + if (result.hasExpression()) { + Colour colourGuard(Colour::OriginalExpression); + stream << " "; + stream << result.getExpressionInMacro(); + stream << '\n'; + } + } + void printReconstructedExpression() const { + if (result.hasExpandedExpression()) { + stream << "with expansion:\n"; + Colour colourGuard(Colour::ReconstructedExpression); + stream << Column(result.getExpandedExpression()).indent(2) << '\n'; + } + } + void printMessage() const { + if (!messageLabel.empty()) + stream << messageLabel << ':' << '\n'; + for (auto const& msg : messages) { + // If this assertion is a warning ignore any INFO messages + if (printInfoMessages || msg.type != ResultWas::Info) + stream << Column(msg.message).indent(2) << '\n'; + } + } + void printSourceInfo() const { + Colour colourGuard(Colour::FileName); + stream << result.getSourceInfo() << ": "; + } + + std::ostream& stream; + AssertionStats const& stats; + AssertionResult const& result; + Colour::Code colour; + std::string passOrFail; + std::string messageLabel; + std::string message; + std::vector messages; + bool printInfoMessages; +}; + +std::size_t makeRatio(std::size_t number, std::size_t total) { + std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number / total : 0; + return (ratio == 0 && number > 0) ? 1 : ratio; +} + +std::size_t& findMax(std::size_t& i, std::size_t& j, std::size_t& k) { + if (i > j && i > k) + return i; + else if (j > k) + return j; + else + return k; +} + +struct ColumnInfo { + enum Justification { Left, Right }; + std::string name; + int width; + Justification justification; +}; +struct ColumnBreak {}; +struct RowBreak {}; + +class Duration { + enum class Unit { + Auto, + Nanoseconds, + Microseconds, + Milliseconds, + Seconds, + Minutes + }; + static const uint64_t s_nanosecondsInAMicrosecond = 1000; + static const uint64_t s_nanosecondsInAMillisecond = 1000 * s_nanosecondsInAMicrosecond; + static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond; + static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond; + + uint64_t m_inNanoseconds; + Unit m_units; + +public: + explicit Duration(uint64_t inNanoseconds, Unit units = Unit::Auto) + : m_inNanoseconds(inNanoseconds), + m_units(units) { + if (m_units == Unit::Auto) { + if (m_inNanoseconds < s_nanosecondsInAMicrosecond) + m_units = Unit::Nanoseconds; + else if (m_inNanoseconds < s_nanosecondsInAMillisecond) + m_units = Unit::Microseconds; + else if (m_inNanoseconds < s_nanosecondsInASecond) + m_units = Unit::Milliseconds; + else if (m_inNanoseconds < s_nanosecondsInAMinute) + m_units = Unit::Seconds; + else + m_units = Unit::Minutes; + } + + } + + auto value() const -> double { + switch (m_units) { + case Unit::Microseconds: + return m_inNanoseconds / static_cast(s_nanosecondsInAMicrosecond); + case Unit::Milliseconds: + return m_inNanoseconds / static_cast(s_nanosecondsInAMillisecond); + case Unit::Seconds: + return m_inNanoseconds / static_cast(s_nanosecondsInASecond); + case Unit::Minutes: + return m_inNanoseconds / static_cast(s_nanosecondsInAMinute); + default: + return static_cast(m_inNanoseconds); + } + } + auto unitsAsString() const -> std::string { + switch (m_units) { + case Unit::Nanoseconds: + return "ns"; + case Unit::Microseconds: + return "µs"; + case Unit::Milliseconds: + return "ms"; + case Unit::Seconds: + return "s"; + case Unit::Minutes: + return "m"; + default: + return "** internal error **"; + } + + } + friend auto operator << (std::ostream& os, Duration const& duration) -> std::ostream& { + return os << duration.value() << " " << duration.unitsAsString(); + } +}; +} // end anon namespace + +class TablePrinter { + std::ostream& m_os; + std::vector m_columnInfos; + std::ostringstream m_oss; + int m_currentColumn = -1; + bool m_isOpen = false; + +public: + TablePrinter( std::ostream& os, std::vector columnInfos ) + : m_os( os ), + m_columnInfos( std::move( columnInfos ) ) {} + + auto columnInfos() const -> std::vector const& { + return m_columnInfos; + } + + void open() { + if (!m_isOpen) { + m_isOpen = true; + *this << RowBreak(); + for (auto const& info : m_columnInfos) + *this << info.name << ColumnBreak(); + *this << RowBreak(); + m_os << Catch::getLineOfChars<'-'>() << "\n"; + } + } + void close() { + if (m_isOpen) { + *this << RowBreak(); + m_os << std::endl; + m_isOpen = false; + } + } + + template + friend TablePrinter& operator << (TablePrinter& tp, T const& value) { + tp.m_oss << value; + return tp; + } + + friend TablePrinter& operator << (TablePrinter& tp, ColumnBreak) { + auto colStr = tp.m_oss.str(); + // This takes account of utf8 encodings + auto strSize = Catch::StringRef(colStr).numberOfCharacters(); + tp.m_oss.str(""); + tp.open(); + if (tp.m_currentColumn == static_cast(tp.m_columnInfos.size() - 1)) { + tp.m_currentColumn = -1; + tp.m_os << "\n"; + } + tp.m_currentColumn++; + + auto colInfo = tp.m_columnInfos[tp.m_currentColumn]; + auto padding = (strSize + 2 < static_cast(colInfo.width)) + ? std::string(colInfo.width - (strSize + 2), ' ') + : std::string(); + if (colInfo.justification == ColumnInfo::Left) + tp.m_os << colStr << padding << " "; + else + tp.m_os << padding << colStr << " "; + return tp; + } + + friend TablePrinter& operator << (TablePrinter& tp, RowBreak) { + if (tp.m_currentColumn > 0) { + tp.m_os << "\n"; + tp.m_currentColumn = -1; + } + return tp; + } +}; + +ConsoleReporter::ConsoleReporter(ReporterConfig const& config) + : StreamingReporterBase(config), + m_tablePrinter(new TablePrinter(config.stream(), + { + { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 32, ColumnInfo::Left }, + { "iters", 8, ColumnInfo::Right }, + { "elapsed ns", 14, ColumnInfo::Right }, + { "average", 14, ColumnInfo::Right } + })) {} +ConsoleReporter::~ConsoleReporter() = default; + +std::string ConsoleReporter::getDescription() { + return "Reports test results as plain lines of text"; +} + +void ConsoleReporter::noMatchingTestCases(std::string const& spec) { + stream << "No test cases matched '" << spec << '\'' << std::endl; +} + +void ConsoleReporter::assertionStarting(AssertionInfo const&) {} + +bool ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) { + AssertionResult const& result = _assertionStats.assertionResult; + + bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); + + // Drop out if result was successful but we're not printing them. + if (!includeResults && result.getResultType() != ResultWas::Warning) + return false; + + lazyPrint(); + + ConsoleAssertionPrinter printer(stream, _assertionStats, includeResults); + printer.print(); + stream << std::endl; + return true; +} + +void ConsoleReporter::sectionStarting(SectionInfo const& _sectionInfo) { + m_headerPrinted = false; + StreamingReporterBase::sectionStarting(_sectionInfo); +} +void ConsoleReporter::sectionEnded(SectionStats const& _sectionStats) { + m_tablePrinter->close(); + if (_sectionStats.missingAssertions) { + lazyPrint(); + Colour colour(Colour::ResultError); + if (m_sectionStack.size() > 1) + stream << "\nNo assertions in section"; + else + stream << "\nNo assertions in test case"; + stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; + } + if (m_config->showDurations() == ShowDurations::Always) { + stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; + } + if (m_headerPrinted) { + m_headerPrinted = false; + } + StreamingReporterBase::sectionEnded(_sectionStats); +} + +void ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info) { + lazyPrintWithoutClosingBenchmarkTable(); + + auto nameCol = Column( info.name ).width( static_cast( m_tablePrinter->columnInfos()[0].width - 2 ) ); + + bool firstLine = true; + for (auto line : nameCol) { + if (!firstLine) + (*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak(); + else + firstLine = false; + + (*m_tablePrinter) << line << ColumnBreak(); + } +} +void ConsoleReporter::benchmarkEnded(BenchmarkStats const& stats) { + Duration average(stats.elapsedTimeInNanoseconds / stats.iterations); + (*m_tablePrinter) + << stats.iterations << ColumnBreak() + << stats.elapsedTimeInNanoseconds << ColumnBreak() + << average << ColumnBreak(); +} + +void ConsoleReporter::testCaseEnded(TestCaseStats const& _testCaseStats) { + m_tablePrinter->close(); + StreamingReporterBase::testCaseEnded(_testCaseStats); + m_headerPrinted = false; +} +void ConsoleReporter::testGroupEnded(TestGroupStats const& _testGroupStats) { + if (currentGroupInfo.used) { + printSummaryDivider(); + stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; + printTotals(_testGroupStats.totals); + stream << '\n' << std::endl; + } + StreamingReporterBase::testGroupEnded(_testGroupStats); +} +void ConsoleReporter::testRunEnded(TestRunStats const& _testRunStats) { + printTotalsDivider(_testRunStats.totals); + printTotals(_testRunStats.totals); + stream << std::endl; + StreamingReporterBase::testRunEnded(_testRunStats); +} + +void ConsoleReporter::lazyPrint() { + + m_tablePrinter->close(); + lazyPrintWithoutClosingBenchmarkTable(); +} + +void ConsoleReporter::lazyPrintWithoutClosingBenchmarkTable() { + + if (!currentTestRunInfo.used) + lazyPrintRunInfo(); + if (!currentGroupInfo.used) + lazyPrintGroupInfo(); + + if (!m_headerPrinted) { + printTestCaseAndSectionHeader(); + m_headerPrinted = true; + } +} +void ConsoleReporter::lazyPrintRunInfo() { + stream << '\n' << getLineOfChars<'~'>() << '\n'; + Colour colour(Colour::SecondaryText); + stream << currentTestRunInfo->name + << " is a Catch v" << libraryVersion() << " host application.\n" + << "Run with -? for options\n\n"; + + if (m_config->rngSeed() != 0) + stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; + + currentTestRunInfo.used = true; +} +void ConsoleReporter::lazyPrintGroupInfo() { + if (!currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1) { + printClosedHeader("Group: " + currentGroupInfo->name); + currentGroupInfo.used = true; + } +} +void ConsoleReporter::printTestCaseAndSectionHeader() { + assert(!m_sectionStack.empty()); + printOpenHeader(currentTestCaseInfo->name); + + if (m_sectionStack.size() > 1) { + Colour colourGuard(Colour::Headers); + + auto + it = m_sectionStack.begin() + 1, // Skip first section (test case) + itEnd = m_sectionStack.end(); + for (; it != itEnd; ++it) + printHeaderString(it->name, 2); + } + + SourceLineInfo lineInfo = m_sectionStack.back().lineInfo; + + if (!lineInfo.empty()) { + stream << getLineOfChars<'-'>() << '\n'; + Colour colourGuard(Colour::FileName); + stream << lineInfo << '\n'; + } + stream << getLineOfChars<'.'>() << '\n' << std::endl; +} + +void ConsoleReporter::printClosedHeader(std::string const& _name) { + printOpenHeader(_name); + stream << getLineOfChars<'.'>() << '\n'; +} +void ConsoleReporter::printOpenHeader(std::string const& _name) { + stream << getLineOfChars<'-'>() << '\n'; + { + Colour colourGuard(Colour::Headers); + printHeaderString(_name); + } +} + +// if string has a : in first line will set indent to follow it on +// subsequent lines +void ConsoleReporter::printHeaderString(std::string const& _string, std::size_t indent) { + std::size_t i = _string.find(": "); + if (i != std::string::npos) + i += 2; + else + i = 0; + stream << Column(_string).indent(indent + i).initialIndent(indent) << '\n'; +} + +struct SummaryColumn { + + SummaryColumn( std::string _label, Colour::Code _colour ) + : label( std::move( _label ) ), + colour( _colour ) {} + SummaryColumn addRow( std::size_t count ) { + ReusableStringStream rss; + rss << count; + std::string row = rss.str(); + for (auto& oldRow : rows) { + while (oldRow.size() < row.size()) + oldRow = ' ' + oldRow; + while (oldRow.size() > row.size()) + row = ' ' + row; + } + rows.push_back(row); + return *this; + } + + std::string label; + Colour::Code colour; + std::vector rows; + +}; + +void ConsoleReporter::printTotals( Totals const& totals ) { + if (totals.testCases.total() == 0) { + stream << Colour(Colour::Warning) << "No tests ran\n"; + } else if (totals.assertions.total() > 0 && totals.testCases.allPassed()) { + stream << Colour(Colour::ResultSuccess) << "All tests passed"; + stream << " (" + << pluralise(totals.assertions.passed, "assertion") << " in " + << pluralise(totals.testCases.passed, "test case") << ')' + << '\n'; + } else { + + std::vector columns; + columns.push_back(SummaryColumn("", Colour::None) + .addRow(totals.testCases.total()) + .addRow(totals.assertions.total())); + columns.push_back(SummaryColumn("passed", Colour::Success) + .addRow(totals.testCases.passed) + .addRow(totals.assertions.passed)); + columns.push_back(SummaryColumn("failed", Colour::ResultError) + .addRow(totals.testCases.failed) + .addRow(totals.assertions.failed)); + columns.push_back(SummaryColumn("failed as expected", Colour::ResultExpectedFailure) + .addRow(totals.testCases.failedButOk) + .addRow(totals.assertions.failedButOk)); + + printSummaryRow("test cases", columns, 0); + printSummaryRow("assertions", columns, 1); + } +} +void ConsoleReporter::printSummaryRow(std::string const& label, std::vector const& cols, std::size_t row) { + for (auto col : cols) { + std::string value = col.rows[row]; + if (col.label.empty()) { + stream << label << ": "; + if (value != "0") + stream << value; + else + stream << Colour(Colour::Warning) << "- none -"; + } else if (value != "0") { + stream << Colour(Colour::LightGrey) << " | "; + stream << Colour(col.colour) + << value << ' ' << col.label; + } + } + stream << '\n'; +} + +void ConsoleReporter::printTotalsDivider(Totals const& totals) { + if (totals.testCases.total() > 0) { + std::size_t failedRatio = makeRatio(totals.testCases.failed, totals.testCases.total()); + std::size_t failedButOkRatio = makeRatio(totals.testCases.failedButOk, totals.testCases.total()); + std::size_t passedRatio = makeRatio(totals.testCases.passed, totals.testCases.total()); + while (failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1) + findMax(failedRatio, failedButOkRatio, passedRatio)++; + while (failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1) + findMax(failedRatio, failedButOkRatio, passedRatio)--; + + stream << Colour(Colour::Error) << std::string(failedRatio, '='); + stream << Colour(Colour::ResultExpectedFailure) << std::string(failedButOkRatio, '='); + if (totals.testCases.allPassed()) + stream << Colour(Colour::ResultSuccess) << std::string(passedRatio, '='); + else + stream << Colour(Colour::Success) << std::string(passedRatio, '='); + } else { + stream << Colour(Colour::Warning) << std::string(CATCH_CONFIG_CONSOLE_WIDTH - 1, '='); + } + stream << '\n'; +} +void ConsoleReporter::printSummaryDivider() { + stream << getLineOfChars<'-'>() << '\n'; +} + +CATCH_REGISTER_REPORTER("console", ConsoleReporter) + +} // end namespace Catch + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif +// end catch_reporter_console.cpp +// start catch_reporter_junit.cpp + +#include +#include +#include +#include + +namespace Catch { + + namespace { + std::string getCurrentTimestamp() { + // Beware, this is not reentrant because of backward compatibility issues + // Also, UTC only, again because of backward compatibility (%z is C++11) + time_t rawtime; + std::time(&rawtime); + auto const timeStampSize = sizeof("2017-01-16T17:06:45Z"); + +#ifdef _MSC_VER + std::tm timeInfo = {}; + gmtime_s(&timeInfo, &rawtime); +#else + std::tm* timeInfo; + timeInfo = std::gmtime(&rawtime); +#endif + + char timeStamp[timeStampSize]; + const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; + +#ifdef _MSC_VER + std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); +#else + std::strftime(timeStamp, timeStampSize, fmt, timeInfo); +#endif + return std::string(timeStamp); + } + + std::string fileNameTag(const std::vector &tags) { + auto it = std::find_if(begin(tags), + end(tags), + [] (std::string const& tag) {return tag.front() == '#'; }); + if (it != tags.end()) + return it->substr(1); + return std::string(); + } + } // anonymous namespace + + JunitReporter::JunitReporter( ReporterConfig const& _config ) + : CumulativeReporterBase( _config ), + xml( _config.stream() ) + { + m_reporterPrefs.shouldRedirectStdOut = true; + } + + JunitReporter::~JunitReporter() {} + + std::string JunitReporter::getDescription() { + return "Reports test results in an XML format that looks like Ant's junitreport target"; + } + + void JunitReporter::noMatchingTestCases( std::string const& /*spec*/ ) {} + + void JunitReporter::testRunStarting( TestRunInfo const& runInfo ) { + CumulativeReporterBase::testRunStarting( runInfo ); + xml.startElement( "testsuites" ); + } + + void JunitReporter::testGroupStarting( GroupInfo const& groupInfo ) { + suiteTimer.start(); + stdOutForSuite.clear(); + stdErrForSuite.clear(); + unexpectedExceptions = 0; + CumulativeReporterBase::testGroupStarting( groupInfo ); + } + + void JunitReporter::testCaseStarting( TestCaseInfo const& testCaseInfo ) { + m_okToFail = testCaseInfo.okToFail(); + } + + bool JunitReporter::assertionEnded( AssertionStats const& assertionStats ) { + if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail ) + unexpectedExceptions++; + return CumulativeReporterBase::assertionEnded( assertionStats ); + } + + void JunitReporter::testCaseEnded( TestCaseStats const& testCaseStats ) { + stdOutForSuite += testCaseStats.stdOut; + stdErrForSuite += testCaseStats.stdErr; + CumulativeReporterBase::testCaseEnded( testCaseStats ); + } + + void JunitReporter::testGroupEnded( TestGroupStats const& testGroupStats ) { + double suiteTime = suiteTimer.getElapsedSeconds(); + CumulativeReporterBase::testGroupEnded( testGroupStats ); + writeGroup( *m_testGroups.back(), suiteTime ); + } + + void JunitReporter::testRunEndedCumulative() { + xml.endElement(); + } + + void JunitReporter::writeGroup( TestGroupNode const& groupNode, double suiteTime ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); + TestGroupStats const& stats = groupNode.value; + xml.writeAttribute( "name", stats.groupInfo.name ); + xml.writeAttribute( "errors", unexpectedExceptions ); + xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); + xml.writeAttribute( "tests", stats.totals.assertions.total() ); + xml.writeAttribute( "hostname", "tbd" ); // !TBD + if( m_config->showDurations() == ShowDurations::Never ) + xml.writeAttribute( "time", "" ); + else + xml.writeAttribute( "time", suiteTime ); + xml.writeAttribute( "timestamp", getCurrentTimestamp() ); + + // Write test cases + for( auto const& child : groupNode.children ) + writeTestCase( *child ); + + xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite ), false ); + xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite ), false ); + } + + void JunitReporter::writeTestCase( TestCaseNode const& testCaseNode ) { + TestCaseStats const& stats = testCaseNode.value; + + // All test cases have exactly one section - which represents the + // test case itself. That section may have 0-n nested sections + assert( testCaseNode.children.size() == 1 ); + SectionNode const& rootSection = *testCaseNode.children.front(); + + std::string className = stats.testInfo.className; + + if( className.empty() ) { + className = fileNameTag(stats.testInfo.tags); + if ( className.empty() ) + className = "global"; + } + + if ( !m_config->name().empty() ) + className = m_config->name() + "." + className; + + writeSection( className, "", rootSection ); + } + + void JunitReporter::writeSection( std::string const& className, + std::string const& rootName, + SectionNode const& sectionNode ) { + std::string name = trim( sectionNode.stats.sectionInfo.name ); + if( !rootName.empty() ) + name = rootName + '/' + name; + + if( !sectionNode.assertions.empty() || + !sectionNode.stdOut.empty() || + !sectionNode.stdErr.empty() ) { + XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); + if( className.empty() ) { + xml.writeAttribute( "classname", name ); + xml.writeAttribute( "name", "root" ); + } + else { + xml.writeAttribute( "classname", className ); + xml.writeAttribute( "name", name ); + } + xml.writeAttribute( "time", ::Catch::Detail::stringify( sectionNode.stats.durationInSeconds ) ); + + writeAssertions( sectionNode ); + + if( !sectionNode.stdOut.empty() ) + xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); + if( !sectionNode.stdErr.empty() ) + xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); + } + for( auto const& childNode : sectionNode.childSections ) + if( className.empty() ) + writeSection( name, "", *childNode ); + else + writeSection( className, name, *childNode ); + } + + void JunitReporter::writeAssertions( SectionNode const& sectionNode ) { + for( auto const& assertion : sectionNode.assertions ) + writeAssertion( assertion ); + } + + void JunitReporter::writeAssertion( AssertionStats const& stats ) { + AssertionResult const& result = stats.assertionResult; + if( !result.isOk() ) { + std::string elementName; + switch( result.getResultType() ) { + case ResultWas::ThrewException: + case ResultWas::FatalErrorCondition: + elementName = "error"; + break; + case ResultWas::ExplicitFailure: + elementName = "failure"; + break; + case ResultWas::ExpressionFailed: + elementName = "failure"; + break; + case ResultWas::DidntThrowException: + elementName = "failure"; + break; + + // We should never see these here: + case ResultWas::Info: + case ResultWas::Warning: + case ResultWas::Ok: + case ResultWas::Unknown: + case ResultWas::FailureBit: + case ResultWas::Exception: + elementName = "internalError"; + break; + } + + XmlWriter::ScopedElement e = xml.scopedElement( elementName ); + + xml.writeAttribute( "message", result.getExpandedExpression() ); + xml.writeAttribute( "type", result.getTestMacroName() ); + + ReusableStringStream rss; + if( !result.getMessage().empty() ) + rss << result.getMessage() << '\n'; + for( auto const& msg : stats.infoMessages ) + if( msg.type == ResultWas::Info ) + rss << msg.message << '\n'; + + rss << "at " << result.getSourceInfo(); + xml.writeText( rss.str(), false ); + } + } + + CATCH_REGISTER_REPORTER( "junit", JunitReporter ) + +} // end namespace Catch +// end catch_reporter_junit.cpp +// start catch_reporter_listening.cpp + +#include + +namespace Catch { + + void ListeningReporter::addListener( IStreamingReporterPtr&& listener ) { + m_listeners.push_back( std::move( listener ) ); + } + + void ListeningReporter::addReporter(IStreamingReporterPtr&& reporter) { + assert(!m_reporter && "Listening reporter can wrap only 1 real reporter"); + m_reporter = std::move( reporter ); + } + + ReporterPreferences ListeningReporter::getPreferences() const { + return m_reporter->getPreferences(); + } + + std::set ListeningReporter::getSupportedVerbosities() { + return std::set{ }; + } + + void ListeningReporter::noMatchingTestCases( std::string const& spec ) { + for ( auto const& listener : m_listeners ) { + listener->noMatchingTestCases( spec ); + } + m_reporter->noMatchingTestCases( spec ); + } + + void ListeningReporter::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) { + for ( auto const& listener : m_listeners ) { + listener->benchmarkStarting( benchmarkInfo ); + } + m_reporter->benchmarkStarting( benchmarkInfo ); + } + void ListeningReporter::benchmarkEnded( BenchmarkStats const& benchmarkStats ) { + for ( auto const& listener : m_listeners ) { + listener->benchmarkEnded( benchmarkStats ); + } + m_reporter->benchmarkEnded( benchmarkStats ); + } + + void ListeningReporter::testRunStarting( TestRunInfo const& testRunInfo ) { + for ( auto const& listener : m_listeners ) { + listener->testRunStarting( testRunInfo ); + } + m_reporter->testRunStarting( testRunInfo ); + } + + void ListeningReporter::testGroupStarting( GroupInfo const& groupInfo ) { + for ( auto const& listener : m_listeners ) { + listener->testGroupStarting( groupInfo ); + } + m_reporter->testGroupStarting( groupInfo ); + } + + void ListeningReporter::testCaseStarting( TestCaseInfo const& testInfo ) { + for ( auto const& listener : m_listeners ) { + listener->testCaseStarting( testInfo ); + } + m_reporter->testCaseStarting( testInfo ); + } + + void ListeningReporter::sectionStarting( SectionInfo const& sectionInfo ) { + for ( auto const& listener : m_listeners ) { + listener->sectionStarting( sectionInfo ); + } + m_reporter->sectionStarting( sectionInfo ); + } + + void ListeningReporter::assertionStarting( AssertionInfo const& assertionInfo ) { + for ( auto const& listener : m_listeners ) { + listener->assertionStarting( assertionInfo ); + } + m_reporter->assertionStarting( assertionInfo ); + } + + // The return value indicates if the messages buffer should be cleared: + bool ListeningReporter::assertionEnded( AssertionStats const& assertionStats ) { + for( auto const& listener : m_listeners ) { + static_cast( listener->assertionEnded( assertionStats ) ); + } + return m_reporter->assertionEnded( assertionStats ); + } + + void ListeningReporter::sectionEnded( SectionStats const& sectionStats ) { + for ( auto const& listener : m_listeners ) { + listener->sectionEnded( sectionStats ); + } + m_reporter->sectionEnded( sectionStats ); + } + + void ListeningReporter::testCaseEnded( TestCaseStats const& testCaseStats ) { + for ( auto const& listener : m_listeners ) { + listener->testCaseEnded( testCaseStats ); + } + m_reporter->testCaseEnded( testCaseStats ); + } + + void ListeningReporter::testGroupEnded( TestGroupStats const& testGroupStats ) { + for ( auto const& listener : m_listeners ) { + listener->testGroupEnded( testGroupStats ); + } + m_reporter->testGroupEnded( testGroupStats ); + } + + void ListeningReporter::testRunEnded( TestRunStats const& testRunStats ) { + for ( auto const& listener : m_listeners ) { + listener->testRunEnded( testRunStats ); + } + m_reporter->testRunEnded( testRunStats ); + } + + void ListeningReporter::skipTest( TestCaseInfo const& testInfo ) { + for ( auto const& listener : m_listeners ) { + listener->skipTest( testInfo ); + } + m_reporter->skipTest( testInfo ); + } + + bool ListeningReporter::isMulti() const { + return true; + } + +} // end namespace Catch +// end catch_reporter_listening.cpp +// start catch_reporter_xml.cpp + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch + // Note that 4062 (not all labels are handled + // and default is missing) is enabled +#endif + +namespace Catch { + XmlReporter::XmlReporter( ReporterConfig const& _config ) + : StreamingReporterBase( _config ), + m_xml(_config.stream()) + { + m_reporterPrefs.shouldRedirectStdOut = true; + } + + XmlReporter::~XmlReporter() = default; + + std::string XmlReporter::getDescription() { + return "Reports test results as an XML document"; + } + + std::string XmlReporter::getStylesheetRef() const { + return std::string(); + } + + void XmlReporter::writeSourceInfo( SourceLineInfo const& sourceInfo ) { + m_xml + .writeAttribute( "filename", sourceInfo.file ) + .writeAttribute( "line", sourceInfo.line ); + } + + void XmlReporter::noMatchingTestCases( std::string const& s ) { + StreamingReporterBase::noMatchingTestCases( s ); + } + + void XmlReporter::testRunStarting( TestRunInfo const& testInfo ) { + StreamingReporterBase::testRunStarting( testInfo ); + std::string stylesheetRef = getStylesheetRef(); + if( !stylesheetRef.empty() ) + m_xml.writeStylesheetRef( stylesheetRef ); + m_xml.startElement( "Catch" ); + if( !m_config->name().empty() ) + m_xml.writeAttribute( "name", m_config->name() ); + } + + void XmlReporter::testGroupStarting( GroupInfo const& groupInfo ) { + StreamingReporterBase::testGroupStarting( groupInfo ); + m_xml.startElement( "Group" ) + .writeAttribute( "name", groupInfo.name ); + } + + void XmlReporter::testCaseStarting( TestCaseInfo const& testInfo ) { + StreamingReporterBase::testCaseStarting(testInfo); + m_xml.startElement( "TestCase" ) + .writeAttribute( "name", trim( testInfo.name ) ) + .writeAttribute( "description", testInfo.description ) + .writeAttribute( "tags", testInfo.tagsAsString() ); + + writeSourceInfo( testInfo.lineInfo ); + + if ( m_config->showDurations() == ShowDurations::Always ) + m_testCaseTimer.start(); + m_xml.ensureTagClosed(); + } + + void XmlReporter::sectionStarting( SectionInfo const& sectionInfo ) { + StreamingReporterBase::sectionStarting( sectionInfo ); + if( m_sectionDepth++ > 0 ) { + m_xml.startElement( "Section" ) + .writeAttribute( "name", trim( sectionInfo.name ) ) + .writeAttribute( "description", sectionInfo.description ); + writeSourceInfo( sectionInfo.lineInfo ); + m_xml.ensureTagClosed(); + } + } + + void XmlReporter::assertionStarting( AssertionInfo const& ) { } + + bool XmlReporter::assertionEnded( AssertionStats const& assertionStats ) { + + AssertionResult const& result = assertionStats.assertionResult; + + bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); + + if( includeResults || result.getResultType() == ResultWas::Warning ) { + // Print any info messages in tags. + for( auto const& msg : assertionStats.infoMessages ) { + if( msg.type == ResultWas::Info && includeResults ) { + m_xml.scopedElement( "Info" ) + .writeText( msg.message ); + } else if ( msg.type == ResultWas::Warning ) { + m_xml.scopedElement( "Warning" ) + .writeText( msg.message ); + } + } + } + + // Drop out if result was successful but we're not printing them. + if( !includeResults && result.getResultType() != ResultWas::Warning ) + return true; + + // Print the expression if there is one. + if( result.hasExpression() ) { + m_xml.startElement( "Expression" ) + .writeAttribute( "success", result.succeeded() ) + .writeAttribute( "type", result.getTestMacroName() ); + + writeSourceInfo( result.getSourceInfo() ); + + m_xml.scopedElement( "Original" ) + .writeText( result.getExpression() ); + m_xml.scopedElement( "Expanded" ) + .writeText( result.getExpandedExpression() ); + } + + // And... Print a result applicable to each result type. + switch( result.getResultType() ) { + case ResultWas::ThrewException: + m_xml.startElement( "Exception" ); + writeSourceInfo( result.getSourceInfo() ); + m_xml.writeText( result.getMessage() ); + m_xml.endElement(); + break; + case ResultWas::FatalErrorCondition: + m_xml.startElement( "FatalErrorCondition" ); + writeSourceInfo( result.getSourceInfo() ); + m_xml.writeText( result.getMessage() ); + m_xml.endElement(); + break; + case ResultWas::Info: + m_xml.scopedElement( "Info" ) + .writeText( result.getMessage() ); + break; + case ResultWas::Warning: + // Warning will already have been written + break; + case ResultWas::ExplicitFailure: + m_xml.startElement( "Failure" ); + writeSourceInfo( result.getSourceInfo() ); + m_xml.writeText( result.getMessage() ); + m_xml.endElement(); + break; + default: + break; + } + + if( result.hasExpression() ) + m_xml.endElement(); + + return true; + } + + void XmlReporter::sectionEnded( SectionStats const& sectionStats ) { + StreamingReporterBase::sectionEnded( sectionStats ); + if( --m_sectionDepth > 0 ) { + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); + e.writeAttribute( "successes", sectionStats.assertions.passed ); + e.writeAttribute( "failures", sectionStats.assertions.failed ); + e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); + + m_xml.endElement(); + } + } + + void XmlReporter::testCaseEnded( TestCaseStats const& testCaseStats ) { + StreamingReporterBase::testCaseEnded( testCaseStats ); + XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); + e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); + + if ( m_config->showDurations() == ShowDurations::Always ) + e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); + + if( !testCaseStats.stdOut.empty() ) + m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false ); + if( !testCaseStats.stdErr.empty() ) + m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false ); + + m_xml.endElement(); + } + + void XmlReporter::testGroupEnded( TestGroupStats const& testGroupStats ) { + StreamingReporterBase::testGroupEnded( testGroupStats ); + // TODO: Check testGroupStats.aborting and act accordingly. + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) + .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) + .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); + m_xml.endElement(); + } + + void XmlReporter::testRunEnded( TestRunStats const& testRunStats ) { + StreamingReporterBase::testRunEnded( testRunStats ); + m_xml.scopedElement( "OverallResults" ) + .writeAttribute( "successes", testRunStats.totals.assertions.passed ) + .writeAttribute( "failures", testRunStats.totals.assertions.failed ) + .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); + m_xml.endElement(); + } + + CATCH_REGISTER_REPORTER( "xml", XmlReporter ) + +} // end namespace Catch + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif +// end catch_reporter_xml.cpp + +namespace Catch { + LeakDetector leakDetector; +} + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +// end catch_impl.hpp +#endif + +#ifdef CATCH_CONFIG_MAIN +// start catch_default_main.hpp + +#ifndef __OBJC__ + +#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) +// Standard C/C++ Win32 Unicode wmain entry point +extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) { +#else +// Standard C/C++ main entry point +int main (int argc, char * argv[]) { +#endif + + return Catch::Session().run( argc, argv ); +} + +#else // __OBJC__ + +// Objective-C entry point +int main (int argc, char * const argv[]) { +#if !CATCH_ARC_ENABLED + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; +#endif + + Catch::registerTestMethods(); + int result = Catch::Session().run( argc, (char**)argv ); + +#if !CATCH_ARC_ENABLED + [pool drain]; +#endif + + return result; +} + +#endif // __OBJC__ + +// end catch_default_main.hpp +#endif + +#if !defined(CATCH_CONFIG_IMPL_ONLY) + +#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED +# undef CLARA_CONFIG_MAIN +#endif + +#if !defined(CATCH_CONFIG_DISABLE) +////// +// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ +#ifdef CATCH_CONFIG_PREFIX_ALL + +#define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) +#define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) + +#define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", __VA_ARGS__ ) +#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) +#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) +#endif// CATCH_CONFIG_DISABLE_MATCHERS +#define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) + +#define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) +#define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) + +#define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", __VA_ARGS__ ) +#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) +#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) + +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) + +#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) +#endif // CATCH_CONFIG_DISABLE_MATCHERS + +#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) +#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) +#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) ) + +#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) +#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) +#define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) +#define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) +#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) +#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) +#define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) + +#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() + +// "BDD-style" convenience wrappers +#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) +#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc ) +#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc ) +#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc ) +#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc ) +#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc ) + +// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required +#else + +#define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ ) +#define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) + +#define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ ) +#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) +#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr ) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ ) + +#define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ ) +#define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ ) + +#define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) +#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) + +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) + +#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) +#endif // CATCH_CONFIG_DISABLE_MATCHERS + +#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) +#define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) +#define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << ::Catch::Detail::stringify(msg) ) + +#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) +#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) +#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) +#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) +#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) +#define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) +#define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) +#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE() + +#endif + +#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) + +// "BDD-style" convenience wrappers +#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) +#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) + +#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc ) +#define WHEN( desc ) SECTION( std::string(" When: ") + desc ) +#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc ) +#define THEN( desc ) SECTION( std::string(" Then: ") + desc ) +#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc ) + +using Catch::Detail::Approx; + +#else +////// +// If this config identifier is defined then all CATCH macros are prefixed with CATCH_ +#ifdef CATCH_CONFIG_PREFIX_ALL + +#define CATCH_REQUIRE( ... ) (void)(0) +#define CATCH_REQUIRE_FALSE( ... ) (void)(0) + +#define CATCH_REQUIRE_THROWS( ... ) (void)(0) +#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) +#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) +#endif// CATCH_CONFIG_DISABLE_MATCHERS +#define CATCH_REQUIRE_NOTHROW( ... ) (void)(0) + +#define CATCH_CHECK( ... ) (void)(0) +#define CATCH_CHECK_FALSE( ... ) (void)(0) +#define CATCH_CHECKED_IF( ... ) if (__VA_ARGS__) +#define CATCH_CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) +#define CATCH_CHECK_NOFAIL( ... ) (void)(0) + +#define CATCH_CHECK_THROWS( ... ) (void)(0) +#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0) +#define CATCH_CHECK_THROWS_WITH( expr, matcher ) (void)(0) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define CATCH_CHECK_NOTHROW( ... ) (void)(0) + +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CATCH_CHECK_THAT( arg, matcher ) (void)(0) + +#define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0) +#endif // CATCH_CONFIG_DISABLE_MATCHERS + +#define CATCH_INFO( msg ) (void)(0) +#define CATCH_WARN( msg ) (void)(0) +#define CATCH_CAPTURE( msg ) (void)(0) + +#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define CATCH_METHOD_AS_TEST_CASE( method, ... ) +#define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0) +#define CATCH_SECTION( ... ) +#define CATCH_FAIL( ... ) (void)(0) +#define CATCH_FAIL_CHECK( ... ) (void)(0) +#define CATCH_SUCCEED( ... ) (void)(0) + +#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) + +// "BDD-style" convenience wrappers +#define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) +#define CATCH_GIVEN( desc ) +#define CATCH_WHEN( desc ) +#define CATCH_AND_WHEN( desc ) +#define CATCH_THEN( desc ) +#define CATCH_AND_THEN( desc ) + +// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required +#else + +#define REQUIRE( ... ) (void)(0) +#define REQUIRE_FALSE( ... ) (void)(0) + +#define REQUIRE_THROWS( ... ) (void)(0) +#define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0) +#define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define REQUIRE_NOTHROW( ... ) (void)(0) + +#define CHECK( ... ) (void)(0) +#define CHECK_FALSE( ... ) (void)(0) +#define CHECKED_IF( ... ) if (__VA_ARGS__) +#define CHECKED_ELSE( ... ) if (!(__VA_ARGS__)) +#define CHECK_NOFAIL( ... ) (void)(0) + +#define CHECK_THROWS( ... ) (void)(0) +#define CHECK_THROWS_AS( expr, exceptionType ) (void)(0) +#define CHECK_THROWS_WITH( expr, matcher ) (void)(0) +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0) +#endif // CATCH_CONFIG_DISABLE_MATCHERS +#define CHECK_NOTHROW( ... ) (void)(0) + +#if !defined(CATCH_CONFIG_DISABLE_MATCHERS) +#define CHECK_THAT( arg, matcher ) (void)(0) + +#define REQUIRE_THAT( arg, matcher ) (void)(0) +#endif // CATCH_CONFIG_DISABLE_MATCHERS + +#define INFO( msg ) (void)(0) +#define WARN( msg ) (void)(0) +#define CAPTURE( msg ) (void)(0) + +#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) +#define METHOD_AS_TEST_CASE( method, ... ) +#define REGISTER_TEST_CASE( Function, ... ) (void)(0) +#define SECTION( ... ) +#define FAIL( ... ) (void)(0) +#define FAIL_CHECK( ... ) (void)(0) +#define SUCCEED( ... ) (void)(0) +#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )) + +#endif + +#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) + +// "BDD-style" convenience wrappers +#define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) ) +#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className ) + +#define GIVEN( desc ) +#define WHEN( desc ) +#define AND_WHEN( desc ) +#define THEN( desc ) +#define AND_THEN( desc ) + +using Catch::Detail::Approx; + +#endif + +#endif // ! CATCH_CONFIG_IMPL_ONLY + +// start catch_reenable_warnings.h + + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(pop) +# else +# pragma clang diagnostic pop +# endif +#elif defined __GNUC__ +# pragma GCC diagnostic pop +#endif + +// end catch_reenable_warnings.h +// end catch.hpp +#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED diff --git a/bls/contrib/relic/include/low/relic_bn_low.h b/bls/contrib/relic/include/low/relic_bn_low.h new file mode 100644 index 00000000..9f224ffb --- /dev/null +++ b/bls/contrib/relic/include/low/relic_bn_low.h @@ -0,0 +1,306 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 + * + * Interface of the low-level multiple precision integer arithmetic module. + * + * All functions assume that the destination has enough capacity to store + * the result of the computation. + * + * @ingroup bn + */ + +#ifndef RLC_BN_LOW_H +#define RLC_BN_LOW_H + +/*============================================================================*/ +/* Constant definitions */ +/*============================================================================*/ + +#ifdef ASM + +#include "relic_conf.h" + +#if (BN_PRECI % WSIZE) > 0 +#define RLC_BN_DIGS (BN_PRECI/WSIZE + 1) +#else +#define RLC_BN_DIGS (BN_PRECI/WSIZE) +#endif + +#if BN_MAGNI == DOUBLE +#define RLC_BN_SIZE (2 * RLC_BN_DIGS + 2) +#elif BN_MAGNI == CARRY +#define RLC_BN_SIZE ((RLC_BN_DIGS + 1) +#elif BN_MAGNI == SINGLE +#define RLC_BN_SIZE (RLC_BN_DIGS) +#endif + +#else + +#include "relic_types.h" + +/*============================================================================*/ +/* Function prototypes */ +/*============================================================================*/ + +/** + * Adds a digit to a digit vector. Computes c = a + digit. + * + * @param[out] c - the result. + * @param[in] a - the first digit vector to add. + * @param[in] digit - the digit to add. + * @param[in] size - the number of digits in the first operand. + * @return the carry of the last digit addition. + */ +dig_t bn_add1_low(dig_t *c, const dig_t *a, const dig_t digit, const int size); + +/** + * Adds two digit vectors of the same size. Computes c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the first digit vector to add. + * @param[in] b - the second digit vector to add. + * @param[in] size - the number of digits to add. + * @return the carry of the last digit addition. + */ +dig_t bn_addn_low(dig_t *c, const dig_t *a, const dig_t *b, int size); + +/** + * Subtracts a digit from a digit vector. Computes c = a - digit. + * + * @param[out] c - the result. + * @param[in] a - the digit vector. + * @param[in] digit - the digit to subtract. + * @param[in] size - the number of digits in a. + * @return the carry of the last digit subtraction. + */ +dig_t bn_sub1_low(dig_t *c, const dig_t *a, dig_t digit, int size); + +/** + * Subtracts a digit vector from another digit vector. Computes c = a - b. + * + * @param[out] c - the result. + * @param[in] a - the digit vector. + * @param[in] b - the digit vector to subtract. + * @param[in] size - the number of digits to subtract. + * @return the carry of the last digit subtraction. + */ +dig_t bn_subn_low(dig_t *c, const dig_t *a, const dig_t *b, int size); + +/** + * Compares two digits. + * + * @param[in] a - the first digit to compare. + * @param[in] b - the second digit to compare. + * @return BN_LT if a < b, BN_EQ if a == b and BN_GT if a > b. + */ +int bn_cmp1_low(dig_t a, dig_t b); + +/** + * Compares two digit vectors of the same size. + * + * @param[in] a - the first digit vector to compare. + * @param[in] b - the second digit vector to compare. + * @param[in] size - the number of digits to compare. + * @return BN_LT if a < b, BN_EQ if a == b and BN_GT if a > b. + */ +int bn_cmpn_low(const dig_t *a, const dig_t *b, int size); + +/** + * Shifts a digit vector to the left by 1 bit. Computes c = a << 1. + * + * @param[out] c - the result + * @param[in] a - the digit vector to shift. + * @param[in] size - the number of digits to shift. + * @return the carry of the last digit shift. + */ +dig_t bn_lsh1_low(dig_t *c, const dig_t *a, int size); + +/** + * Shifts a digit vector to the left by an amount smaller than a digit. Computes + * c = a << bits. + * + * @param[out] c - the result + * @param[in] a - the 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_lshb_low(dig_t *c, const dig_t *a, int size, int bits); + +/** + * Shifts a digit vector to the left by some digits. + * Computes c = a << (digits * RLC_DIG). + * + * @param[out] c - the result. + * @param[in] a - the multiple precision integer to shift. + * @param[in] size - the number of digits to shift. + * @param[in] digits - the shift amount. + */ +void bn_lshd_low(dig_t *c, const dig_t *a, int size, int digits); + +/** + * Shifts a digit vector to the right by 1 bit. Computes c = a >> 1. + * + * @param[out] c - the result + * @param[in] a - the digit vector to shift. + * @param[in] size - the number of digits to shift. + * @return the carry of the last digit shift. + */ +dig_t bn_rsh1_low(dig_t *c, const dig_t *a, int size); + +/** + * Shifts a 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 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_rshb_low(dig_t *c, const dig_t *a, int size, int bits); + +/** + * Shifts a digit vector to the right by some digits. + * Computes c = a >> (digits * RLC_DIG). + * + * @param[out] c - the result. + * @param[in] a - the multiple precision integer to shift. + * @param[in] size - the number of digits to shift. + * @param[in] digits - the shift amount. + */ +void bn_rshd_low(dig_t *c, const dig_t *a, int size, int digits); + +/** + * Multiplies a digit vector by a digit and adds this result to another digit + * vector. Computes c = c + a * digit. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to multiply. + * @param[in] digit - the digit to multiply. + * @param[in] size - the number of digits to multiply. + * @return the carry of the addition. + */ +dig_t bn_mula_low(dig_t *c, const dig_t *a, dig_t digit, int size); + +/** + * Multiplies a digit vector by a digit and stores this result in another digit + * vector. Computes c = a * digit. + * + * @param[out] c - the result. + * @param[in] a - the first digit vector to multiply. + * @param[in] digit - the digit to multiply. + * @param[in] size - the number of digits to multiply. + * @return the most significant digit. + */ +dig_t bn_mul1_low(dig_t *c, const dig_t *a, dig_t digit, int size); + +/** + * Multiplies two digit vectors of the same size. Computes c = a * b. + * + * @param[out] c - the result. + * @param[in] a - the first digit vector to multiply. + * @param[in] b - the second digit vector to multiply. + * @param[in] size - the number of digits to multiply. + */ +void bn_muln_low(dig_t *c, const dig_t *a, const dig_t *b, int size); + +/** + * Multiplies two digit vectors of different sizes, with sa > sb. Computes + * c = a * b. This function outputs as result only the digits between low and + * high, inclusive, with high > sa and low < sb. + * + * @param[out] c - the result. + * @param[in] a - the first digit vector to multiply. + * @param[in] b - the second digit vector to multiply. + * @param[in] sa - the number of digits in the first operand. + * @param[in] sb - the number of digits in the second operand. + * @param[in] low - the first digit to compute. + * @param[in] high - the last digit to compute. + */ +void bn_muld_low(dig_t *c, const dig_t *a, int sa, const dig_t *b, int sb, + int low, int high); + +/** + * Squares a digit vector and adds this result to another digit vector. + * Computes c = c + a * a. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to square. + * @param[in] size - the number of digitss to square. + */ +void bn_sqra_low(dig_t *c, const dig_t *a, int size); + +/** + * Squares a digit vector. Computes c = a * a. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to square. + * @param[in] size - the number of digits to square. + */ +void bn_sqrn_low(dig_t *c, const dig_t *a, int size); + +/** + * Divides a digit vector by another digit vector. Computes c = floor(a / b) and + * d = a mod b. The dividend and divisor may be destroyed inside the function. + * + * @param[out] c - the quotient. + * @param[out] d - the remainder. + * @param[in,out] a - the dividend. + * @param[in] sa - the size of the dividend. + * @param[in,out] b - the divisor. + * @param[in] sb - the size of the divisor. + */ +void bn_divn_low(dig_t *c, dig_t *d, dig_t *a, int sa, dig_t *b, int sb); + +/** + * Divides a digit vector by a digit. Computes c = floor(a / digit) and + * d = a mod digit. + * + * @param[out] c - the quotient. + * @param[out] d - the remainder. + * @param[in] a - the dividend. + * @param[in] size - the size of the dividend. + * @param[in] digit - the divisor. + */ +void bn_div1_low(dig_t *c, dig_t *d, const dig_t *a, int size, dig_t digit); + +/** + * Reduces a digit vector modulo m by Montgomery's algorithm. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to reduce. + * @param[in] sa - the number of digits to reduce + * @param[in] m - the modulus. + * @param[in] sm - the size of the modulus. + * @param[in] u - the reciprocal of the modulus. + */ +void bn_modn_low(dig_t *c, const dig_t *a, int sa, const dig_t *m, int sm, + dig_t u); + +#endif /* !ASM */ + +#endif /* !RLC_BN_LOW_H */ diff --git a/bls/contrib/relic/include/low/relic_dv_low.h b/bls/contrib/relic/include/low/relic_dv_low.h new file mode 100644 index 00000000..4f25d5e7 --- /dev/null +++ b/bls/contrib/relic/include/low/relic_dv_low.h @@ -0,0 +1,82 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 + * + * Interface of the low-level digit vector module. + * + * @ingroup dv + */ + +#ifndef RELIC_DV_LOW_H +#define RELIC_DV_LOW_H + +#include "relic_bn_low.h" +#include "relic_fb_low.h" +#include "relic_fp_low.h" + +/*============================================================================*/ +/* Constant definitions */ +/*============================================================================*/ + +#ifdef ASM + +/** + * Size in digits of a squaring result in a prime field. + */ +#ifdef WITH_FP +#define DV_FP (2 * FP_DIGS + 1) +#else +#define DV_FP (0) +#endif + +/** + * Size in digits of a squaring result in a binary field. + */ +#ifdef WITH_FB +#define DV_FB (2 * FB_DIGS) +#else +#define DV_FB (0) +#endif + +/** + * Size in digits of a temporary vector. + * + * A temporary vector has enough size to store a multiplication/squaring/cubing + * result in any finite field. + */ +#if DV_FB > DV_FP +#define RLC_DV_DIGS DV_FB +#else +#define RLC_DV_DIGS DV_FP +#endif + +#if RLC_BN_SIZE > DV_DIGS +#undef RLC_DV_DIGS +#define RLC_DV_DIGS RLC_BN_SIZE +#endif + +#endif /* ASM */ + +#endif /* !RELIC_DV_LOW_H */ diff --git a/bls/contrib/relic/include/low/relic_fb_low.h b/bls/contrib/relic/include/low/relic_fb_low.h new file mode 100644 index 00000000..9b7cb9d7 --- /dev/null +++ b/bls/contrib/relic/include/low/relic_fb_low.h @@ -0,0 +1,290 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 + * + * Interface of the low-level binary field arithmetic module. + * + * All functions assume a configured polynomial basis f(z) and that the + * destination has enough capacity to store the result of the computation. + * + * @ingroup fb + */ + +#ifndef RLC_FB_LOW_H +#define RLC_FB_LOW_H + +/*============================================================================*/ +/* Constant definitions */ +/*============================================================================*/ + +#ifdef ASM + +#include "relic_conf.h" + +#undef RLC_FB_DIGS +#if (FB_POLYN % WSIZE) > 0 +#define RLC_FB_DIGS (FB_POLYN/WSIZE + 1) +#else +#define RLC_FB_DIGS (FB_POLYN/WSIZE) +#endif + +#else + +#include "relic_types.h" + +/*============================================================================*/ +/* Function prototypes */ +/*============================================================================*/ + +/** + * Adds a digit vector and a digit. Computes c = a + digit. + * + * @param[out] c - the result. + * @param[in] a - the first digit vector to add. + * @param[in] digit - the digit to add. + */ +void fb_add1_low(dig_t *c, const dig_t *a, dig_t digit); + +/** + * Adds two digit vectors of the same size. Computes c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the first digit vector to add. + * @param[in] b - the second digit vector to add. + */ +void fb_addn_low(dig_t *c, const dig_t *a, const dig_t *b); + +/** + * Adds two digit vectors of the same size, with this size different than the + * standard precision and specified in the last parameter. Computes c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the first digit vector to add. + * @param[in] b - the second digit vector to add. + * @param[in] size - the number of digits to add. + */ +void fb_addd_low(dig_t *c, const dig_t *a, const dig_t *b, int size); + +/** + * Shifts a digit vector to the left by 1 bit. Computes c = a * z. + * + * @param[out] c - the result + * @param[in] a - the digit vector to shift. + * @return the carry of the last digit shift. + */ +dig_t fb_lsh1_low(dig_t *c, const dig_t *a); + +/** + * Shifts a digit vector to the left by an amount smaller than a digit. + * The shift amount must be bigger than 0 and smaller than RLC_DIG. Computes + * c = a * z^bits. + * + * @param[out] c - the result + * @param[in] a - the digit vector to shift. + * @param[in] bits - the shift ammount. + * @return the carry of the last digit shift. + */ +dig_t fb_lshb_low(dig_t *c, const dig_t *a, int bits); + +/** + * Shifts a digit vector to the left by some digits. + * Computes c = a * z^(digits * RLC_DIG). + * + * @param[out] c - the result. + * @param[in] a - the multiple precision integer to shift. + * @param[in] digits - the shift amount. + */ +void fb_lshd_low(dig_t *c, const dig_t *a, int digits); + +/** + * Shifts a digit vector to the right by 1 bit. Computes c = a / z. + * + * @param[out] c - the result + * @param[in] a - the digit vector to shift. + * @return the carry of the last digit shift. + */ +dig_t fb_rsh1_low(dig_t *c, const dig_t *a); + +/** + * Shifts a digit vector to the right by an amount smaller than a digit. + * The shift amount must be bigger than 0 and smaller than RLC_DIG. + * Computes c = a / (z^bits). + * + * @param[out] c - the result + * @param[in] a - the digit vector to shift. + * @param[in] bits - the shift amount. + * @return the carry of the last digit shift. + */ +dig_t fb_rshb_low(dig_t *c, const dig_t *a, int bits); + +/** + * Shifts a digit vector to the right by some digits. + * Computes c = a / z^(digits * RLC_DIG). + * + * @param[out] c - the result. + * @param[in] a - the multiple precision integer to shift. + * @param[in] digits - the shift amount. + */ +void fb_rshd_low(dig_t *c, const dig_t *a, int digits); + +/** + * Adds a left-shifted digit vector to another digit vector. + * The shift amount must be shorter than the digit size. + * Computes c = c + (a * z^bits). + * + * @param[out] c - the result. + * @param[in] a - the digit vector to shift and add. + * @param[in] size - the number of digits to add. + * @param[in] bits - the shift amount. + * @return the carry of the last shift. + */ +dig_t fb_lsha_low(dig_t *c, const dig_t *a, int bits, int size); + +/** + * Multiplies a digit vector by a digit. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to multiply. + * @param[in] digit - the digit to multiply. + */ +void fb_mul1_low(dig_t *c, const dig_t *a, dig_t digit); + +/** + * Multiplies two digit vectors of the same size. + * + * @param[out] c - the result. + * @param[in] a - the first digit vector to multiply. + * @param[in] b - the second digit vector to multiply. + */ +void fb_muln_low(dig_t *c, const dig_t *a, const dig_t *b); + +/** + * Multiplies two digit vectors of the same size but smaller than the standard + * precision. + * + * @param[out] c - the result. + * @param[in] a - the first digit vector to multiply. + * @param[in] b - the second digit vector to multiply. + * @param[in] size - the size of the digit vectors. + */ +void fb_muld_low(dig_t *c, const dig_t *a, const dig_t *b, int size); + +/** + * Multiplies two digit vectors of the same size with embedded modular + * reduction. + * + * @param[out] c - the result. + * @param[in] a - the first digit vector to multiply. + * @param[in] b - the second digit vector to multiply. + */ +void fb_mulm_low(dig_t *c, const dig_t *a, const dig_t *b); + +/** + * Squares a digit vector using bit manipulation. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to square. + */ +void fb_sqrn_low(dig_t *c, const dig_t *a); + +/** + * Squares a digit vector using a lookup table. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to square. + */ +void fb_sqrl_low(dig_t *c, const dig_t *a); + +/** + * Squares a digit vector with embedded modular reduction. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to square. + */ +void fb_sqrm_low(dig_t *c, const dig_t *a); + +/** + * Exponentiates consecutively a digit vector to a fixed power 2^k/2^-k given a + * precomputed table. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to square. + * @param[in] t - the + */ +void fb_itrn_low(dig_t *c, const dig_t *a, dig_t *t); + +/** + * Extracts the square root of a digit vector. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to extract the square root. + */ +void fb_srtn_low(dig_t *c, const dig_t *a); + +/** + * Solves a quadratic equation for c^2 + c = a. + * + * @param[out] c - the result. + * @param[in] a - the digit vector. + */ +void fb_slvn_low(dig_t *c, const dig_t *a); + +/** + * Computes the trace of a digit vector. + * + * @param[in] a - the digit vector. + * @return the trace of the argument. + */ +dig_t fb_trcn_low(const dig_t *a); + +/** + * Reduces a digit vector modulo the configured irreducible polynomial. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to reduce. + */ +void fb_rdcn_low(dig_t *c, dig_t *a); + +/** + * Reduces the most significant bits of a digit vector modulo the configured + * irreducible polynomial. The maximum number of bits to be reduced is equal + * to the size of the digit. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to reduce. + */ +void fb_rdc1_low(dig_t *c, dig_t *a); + +/** + * Inverts a digit vector modulo the configured irreducible polynomial. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to invert. + */ +void fb_invn_low(dig_t *c, const dig_t *a); + +#endif /* !ASM */ + +#endif /* !RLC_FB_LOW_H */ diff --git a/bls/contrib/relic/include/low/relic_fp_low.h b/bls/contrib/relic/include/low/relic_fp_low.h new file mode 100644 index 00000000..0b12cd06 --- /dev/null +++ b/bls/contrib/relic/include/low/relic_fp_low.h @@ -0,0 +1,346 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 + * + * Interface of the low-level prime field arithmetic module. + * + * @ingroup fp + */ + +#ifndef RLC_FP_LOW_H +#define RLC_FP_LOW_H + +/*============================================================================*/ +/* Constant definitions */ +/*============================================================================*/ + +#ifdef ASM + +#include "relic_conf.h" +#include "relic_label.h" + +#if (FP_PRIME % WSIZE) > 0 +#define RLC_FP_DIGS (FP_PRIME/WSIZE + 1) +#else +#define RLC_FP_DIGS (FP_PRIME/WSIZE) +#endif +#else + +/*============================================================================*/ +/* Function prototypes */ +/*============================================================================*/ + +/** + * Adds a digit vector and a digit. Computes c = a + digit. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to add. + * @param[in] digit - the digit to add. + * @return the carry of the last digit addition. + */ +dig_t fp_add1_low(dig_t *c, const dig_t *a, dig_t digit); + +/** + * Adds two digit vectors of the same size. Computes c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the first digit vector to add. + * @param[in] b - the second digit vector to add. + * @return the carry of the last digit addition. + */ +dig_t fp_addn_low(dig_t *c, const dig_t *a, const dig_t *b); + +/** + * Adds two digit vectors of the same size with integrated modular reduction. + * Computes c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the first digit vector to add. + * @param[in] b - the second digit vector to add. + */ +void fp_addm_low(dig_t *c, const dig_t *a, const dig_t *b); + +/** + * Adds two double-length digit vectors. Computes c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the first digit vector to add. + * @param[in] b - the second digit vector to add. + * @return the carry of the last digit addition. + */ +dig_t fp_addd_low(dig_t *c, const dig_t *a, const dig_t *b); + +/** + * Adds two double-length digit vectors and reduces modulo p * R. Computes + * c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the first digit vector to add. + * @param[in] b - the second digit vector to add. + */ +void fp_addc_low(dig_t *c, const dig_t *a, const dig_t *b); + +/** + * Subtracts a digit from a digit vector. Computes c = a - digit. + * + * @param[out] c - the result. + * @param[in] a - the digit vector. + * @param[in] digit - the digit to subtract. + * @return the carry of the last digit subtraction. + */ +dig_t fp_sub1_low(dig_t *c, const dig_t *a, dig_t digit); + +/** + * Subtracts a digit vector from another digit vector. Computes c = a - b. + * + * @param[out] c - the result. + * @param[in] a - the digit vector. + * @param[in] b - the digit vector to subtract. + * @return the carry of the last digit subtraction. + */ +dig_t fp_subn_low(dig_t *c, const dig_t *a, const dig_t *b); + +/** + * Subtracts two digit vectors of the same size with integrated modular + * reduction. + * Computes c = a - b. + * + * @param[out] c - the result. + * @param[in] a - the first digit vector to add. + * @param[in] b - the second digit vector to add. + */ +void fp_subm_low(dig_t *c, const dig_t *a, const dig_t *b); + +/** + * Subtracts a double-length digit vector from another digit vector. + * Computes c = a - b. + * + * @param[out] c - the result. + * @param[in] a - the first digit vector to add. + * @param[in] b - the second digit vector to add. + * @return the carry of the last digit subtraction. + */ +dig_t fp_subd_low(dig_t *c, const dig_t *a, const dig_t *b); + +/** + * Subtracts a double-length digit vector from another digit vector. + * Computes c = a - b. This version of the function should handle possible + * carries by adding p * R. + * + * @param[out] c - the result. + * @param[in] a - the first digit vector to add. + * @param[in] b - the second digit vector to add. + */ +void fp_subc_low(dig_t *c, const dig_t *a, const dig_t *b); + +/** + * Negates a digit vector. Computes c = -a. + * + * @param[out] c - the result. + * @param[out] a - the prime field element to negate. + */ +void fp_negm_low(dig_t *c, const dig_t *a); + +/** + * Doubles a digit vector. Computes c = a + a. + * + * @param[out] c - the result. + * @param[in] a - the digit vector. + * @return the carry of the last digit doubling. + */ +dig_t fp_dbln_low(dig_t *c, const dig_t *a); + +/** + * Doubles a digit vector with integrated modular reduction. + * Computes c = a + a. + * + * @param[out] c - the result. + * @param[in] a - the first digit vector to add. + */ +void fp_dblm_low(dig_t *c, const dig_t *a); + +/** + * Halves a digit vector with integrated modular reduction. + * Computes c = a/2. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to halve. + */ +void fp_hlvm_low(dig_t *c, const dig_t *a); + +/** + * Halves a double-precision digit vector. Computes c = a/2. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to halve. + */ +void fp_hlvd_low(dig_t *c, const dig_t *a); + +/** + * Shifts a digit vector to the left by 1 bits. Computes c = a << 1. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to shift. + * @return the carry of the last digit shift. + */ +dig_t fp_lsh1_low(dig_t *c, const dig_t *a); + +/** + * Shifts a digit vector to the left by an amount smaller than a digit. Computes + * c = a << bits. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to shift. + * @param[in] bits - the shift amount. + * @return the carry of the last digit shift. + */ +dig_t fp_lshb_low(dig_t *c, const dig_t *a, int bits); + +/** + * Shifts a digit vector to the left by some digits. + * Computes c = a << (digits * RLC_DIG). + * + * @param[out] c - the result. + * @param[in] a - the multiple precision integer to shift. + * @param[in] digits - the shift ammount. + */ +void fp_lshd_low(dig_t *c, const dig_t *a, int digits); + +/** + * Shifts a digit vector to the right by 1 bit. Computes c = a >> 1. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to shift. + * @return the carry of the last digit shift. + */ +dig_t fp_rsh1_low(dig_t *c, const dig_t *a); + +/** + * Shifts a 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 digit vector to shift. + * @param[in] bits - the shift amount. + * @return the carry of the last digit shift. + */ +dig_t fp_rshb_low(dig_t *c, const dig_t *a, int bits); + +/** + * Shifts a digit vector to the right by some digits. + * Computes c = a >> (digits * RLC_DIG). + * + * @param[out] c - the result. + * @param[in] a - the multiple precision integer to shift. + * @param[in] digits - the shift amount. + */ +void fp_rshd_low(dig_t *c, const dig_t *a, int digits); + +/** + * Multiplies a digit vector by a digit and adds this result to another digit + * vector. Computes c = c + a * digit. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to multiply. + * @param[in] digit - the digit to multiply. + * @return the carry of the addition. + */ +dig_t fp_mula_low(dig_t *c, const dig_t *a, dig_t digit); + +/** + * Multiplies a digit vector by a digit and stores this result in another digit + * vector. Computes c = a * digit. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to multiply. + * @param[in] digit - the digit to multiply. + * @return the most significant digit. + */ +dig_t fp_mul1_low(dig_t *c, const dig_t *a, dig_t digit); + +/** + * Multiplies two digit vectors of the same size. Computes c = a * b. + * + * @param[out] c - the result. + * @param[in] a - the first digit vector to multiply. + * @param[in] b - the second digit vector to multiply. + */ +void fp_muln_low(dig_t *c, const dig_t *a, const dig_t *b); + +/** + * Multiplies two digit vectors of the same size with embedded modular + * reduction. Computes c = (a * b) mod p. + * + * @param[out] c - the result. + * @param[in] a - the first digit vector to multiply. + * @param[in] b - the second digit vector to multiply. + */ +void fp_mulm_low(dig_t *c, const dig_t *a, const dig_t *b); + +/** + * Squares a digit vector. Computes c = a * a. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to square. + */ +void fp_sqrn_low(dig_t *c, const dig_t *a); + +/** + * Squares a digit vector with embedded modular reduction. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to square. + */ +void fp_sqrm_low(dig_t *c, const dig_t *a); + +/** + * Reduces a digit vector modulo m represented in special form. + * Computes c = a mod m. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to reduce. + * @param[in] m - the modulus. + */ +void fp_rdcs_low(dig_t *c, const dig_t *a, const dig_t *m); + +/** + * Reduces a digit vector modulo the configured prime p. Computes c = a mod p. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to reduce. + */ +void fp_rdcn_low(dig_t *c, dig_t *a); + +/** + * Inverts a digit vector modulo the configured prime. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to invert. + */ +void fp_invm_low(dig_t *c, const dig_t *a); + +#endif /* ASM */ + +#endif /* !RLC_FP_LOW_H */ diff --git a/bls/contrib/relic/include/low/relic_fpx_low.h b/bls/contrib/relic/include/low/relic_fpx_low.h new file mode 100644 index 00000000..981818e1 --- /dev/null +++ b/bls/contrib/relic/include/low/relic_fpx_low.h @@ -0,0 +1,390 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 + * + * Interface of the low-level prime extension field arithmetic module. + * + * @ingroup fpx + */ + +#ifndef RLC_FPX_LOW_H +#define RLC_FPX_LOW_H + +#include "relic_fpx.h" + +/*============================================================================*/ +/* Function prototypes */ +/*============================================================================*/ + +/** + * Adds two quadratic extension field elements of the same size. + * Computes c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the first field element to add. + * @param[in] b - the second field element to add. + */ +void fp2_addn_low(fp2_t c, fp2_t a, fp2_t b); + +/** + * Adds two quadratic extension field elements of the same size with integrated + * modular reduction. Computes c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the first field element to add. + * @param[in] b - the second field element to add. + */ +void fp2_addm_low(fp2_t c, fp2_t a, fp2_t b); + +/** + * Adds two double-precision quadratic extension field elements of the same + * size. Computes c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the first field element to add. + * @param[in] b - the second field element to add. + */ +void fp2_addd_low(dv2_t c, dv2_t a, dv2_t b); + +/** + * Adds two double-precision quadratic extension field elements of the same size + * and corrects the result by conditionally adding 2^(RLC_FP_DIGS * WSIZE) * p. + * Computes c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the first field element to add. + * @param[in] b - the second field element to add. + */ +void fp2_addc_low(dv2_t c, dv2_t a, dv2_t b); + +/** + * Subtracts a quadratic extension field element from another of the same size. + * Computes c = a - b. + * + * @param[out] c - the result. + * @param[in] a - the first field element. + * @param[in] b - the field element to subtract. + */ +void fp2_subn_low(fp2_t c, fp2_t a, fp2_t b); + +/** + * Subtracts a quadratic extension field element from another of the same size + * with integrated modular reduction. Computes c = a - b. + * + * @param[out] c - the result. + * @param[in] a - the first field element. + * @param[in] b - the field element to subtract. + */ +void fp2_subm_low(fp2_t c, fp2_t a, fp2_t b); + +/** + * Subtracts a double-precision quadratic extension field element from another + * of the same size. Computes c = a - b. + * + * @param[out] c - the result. + * @param[in] a - the first field element to add. + * @param[in] b - the second field element to add. + */ +void fp2_subd_low(dv2_t c, dv2_t a, dv2_t b); + +/** + * Subtracts a double-precision quadratic extension field element from another + * of the same size and corrects the result by conditionally adding + * 2^(RLC_FP_DIGS * WSIZE) * p. Computes c = a - b. + * + * @param[out] c - the result. + * @param[in] a - the first field element to add. + * @param[in] b - the second field element to add. + */ +void fp2_subc_low(dv2_t c, dv2_t a, dv2_t b); + +/** + * Doubles a quadratic extension field element. Computes c = a + a. + * + * @param[out] c - the result. + * @param[in] a - the first field element to multiply. + */ +void fp2_dbln_low(fp2_t c, fp2_t a); + +/** + * Doubles a quadratic extension field element with integrated modular + * reduction. Computes c = a + a. + * + * @param[out] c - the result. + * @param[in] a - the field element to double. + */ +void fp2_dblm_low(fp2_t c, fp2_t a); + +/** + * Multiplies a quadratic extension field element by the quadratic + * non-residue. Computes c = a * E. + * + * @param[out] c - the result. + * @param[in] a - the field element to multiply. + */ +void fp2_norm_low(fp2_t c, fp2_t a); + +/** + * Multiplies a double-precision quadratic extension field element by the + * quadratic non-residue, reducing only half of the result. Computes + * c = a * E. + * + * @param[out] c - the result. + * @param[in] a - the field element to multiply. + */ +void fp2_norh_low(dv2_t c, dv2_t a); + +/** + * Multiplies a double-precision quadratic extension field element by the + * quadratic non-residue. Computes c = a * E. + * + * @param[out] c - the result. + * @param[in] a - the field element to multiply. + */ +void fp2_nord_low(dv2_t c, dv2_t a); + +/** + * Multiplies two quadratic extension field elements of the same size. + * Computes c = a * b. + * + * @param[out] c - the result. + * @param[in] a - the first field element to multiply. + * @param[in] b - the second field element to multiply. + */ +void fp2_muln_low(dv2_t c, fp2_t a, fp2_t b); + +/** + * Multiplies two quadratic extension elements of the same size and corrects + * the result by adding (2^(RLC_FP_DIGS * WSIZE) * p)/4. This function should + * be used when the RLC_FP_ROOM optimization is detected. Computes c = a * b. + * + * @param[out] c - the result. + * @param[in] a - the first field element to multiply. + * @param[in] b - the second field element to multiply. + */ +void fp2_mulc_low(dv2_t c, fp2_t a, fp2_t b); + +/** + * Multiplies two quadratic extension field elements of the same size with + * embedded modular reduction. Computes c = (a * b) mod p. + * + * @param[out] c - the result. + * @param[in] a - the first field element to multiply. + * @param[in] b - the second field element to multiply. + */ +void fp2_mulm_low(fp2_t c, fp2_t a, fp2_t b); + +/** + * Squares a quadratic extension element. Computes c = a * a. + * + * @param[out] c - the result. + * @param[in] a - the field element to square. + */ +void fp2_sqrn_low(dv2_t c, fp2_t a); + +/** + * Squares a quadratic extension field element with integrated modular + * reduction. Computes c = (a * a) mod p. + * + * @param[out] c - the result. + * @param[in] a - the field element to square. + */ +void fp2_sqrm_low(fp2_t c, fp2_t a); + +/** + * Reduces a quadratic extension element modulo the configured prime p. + * Computes c = a mod p. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to reduce. + */ +void fp2_rdcn_low(fp2_t c, dv2_t a); + +/** + * Adds two cubic extension field elements of the same size. + * Computes c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the first field element to add. + * @param[in] b - the second field element to add. + */ +void fp3_addn_low(fp3_t c, fp3_t a, fp3_t b); + +/** + * Adds two cubic extension field elements of the same size with integrated + * modular reduction. Computes c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the first field element to add. + * @param[in] b - the second field element to add. + */ +void fp3_addm_low(fp3_t c, fp3_t a, fp3_t b); + +/** + * Adds two double-precision cubic extension field elements of the same + * size. Computes c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the first field element to add. + * @param[in] b - the second field element to add. + */ +void fp3_addd_low(dv3_t c, dv3_t a, dv3_t b); + +/** + * Adds two double-precision cubic extension field elements of the same size + * and corrects the result by conditionally adding 3^(RLC_FP_DIGS * WSIZE) * p. + * Computes c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the first field element to add. + * @param[in] b - the second field element to add. + */ +void fp3_addc_low(dv3_t c, dv3_t a, dv3_t b); + +/** + * Subtracts a cubic extension field element from another of the same size. + * Computes c = a - b. + * + * @param[out] c - the result. + * @param[in] a - the first field element. + * @param[in] b - the field element to subtract. + */ +void fp3_subn_low(fp3_t c, fp3_t a, fp3_t b); + +/** + * Subtracts a cubic extension field element from another of the same size + * with integrated modular reduction. Computes c = a - b. + * + * @param[out] c - the result. + * @param[in] a - the first field element. + * @param[in] b - the field element to subtract. + */ +void fp3_subm_low(fp3_t c, fp3_t a, fp3_t b); + +/** + * Subtracts a double-precision cubic extension field element from another + * of the same size. Computes c = a - b. + * + * @param[out] c - the result. + * @param[in] a - the first field element to add. + * @param[in] b - the second field element to add. + */ +void fp3_subd_low(dv3_t c, dv3_t a, dv3_t b); + +/** + * Subtracts a double-precision cubic extension field element from another + * of the same size and corrects the result by conditionally adding + * 3^(RLC_FP_DIGS * WSIZE) * p. Computes c = a - b. + * + * @param[out] c - the result. + * @param[in] a - the first field element to add. + * @param[in] b - the second field element to add. + */ +void fp3_subc_low(dv3_t c, dv3_t a, dv3_t b); + +/** + * Doubles a cubic extension field element. Computes c = a + a. + * + * @param[out] c - the result. + * @param[in] a - the first field element to multiply. + */ +void fp3_dbln_low(fp3_t c, fp3_t a); + +/** + * Doubles a cubic extension field element with integrated modular + * reduction. Computes c = a + a. + * + * @param[out] c - the result. + * @param[in] a - the field element to double. + */ +void fp3_dblm_low(fp3_t c, fp3_t a); + +/** + * Multiplies a double-precision cubic extension field element by the + * cubic non-residue. Computes c = a * E. + * + * @param[out] c - the result. + * @param[in] a - the field element to multiply. + */ +void fp3_nord_low(dv3_t c, dv3_t a); + +/** + * Multiplies two cubic extension field elements of the same size. + * Computes c = a * b. + * + * @param[out] c - the result. + * @param[in] a - the first field element to multiply. + * @param[in] b - the second field element to multiply. + */ +void fp3_muln_low(dv3_t c, fp3_t a, fp3_t b); + +/** + * Multiplies two cubic extension elements of the same size and corrects + * the result by adding (2^(RLC_FP_DIGS * WSIZE) * p)/4. This function should + * be used when the RLC_FP_ROOM optimization is detected. Computes c = a * b. + * + * @param[out] c - the result. + * @param[in] a - the first field element to multiply. + * @param[in] b - the second field element to multiply. + */ +void fp3_mulc_low(dv3_t c, fp3_t a, fp3_t b); + +/** + * Multiplies two cubic extension field elements of the same size with + * embedded modular reduction. Computes c = (a * b) mod p. + * + * @param[out] c - the result. + * @param[in] a - the first field element to multiply. + * @param[in] b - the second field element to multiply. + */ +void fp3_mulm_low(fp3_t c, fp3_t a, fp3_t b); + +/** + * Squares a cubic extension element. Computes c = a * a. + * + * @param[out] c - the result. + * @param[in] a - the field element to square. + */ +void fp3_sqrn_low(dv2_t c, fp3_t a); + +/** + * Squares a cubic extension field element with integrated modular + * reduction. Computes c = (a * a) mod p. + * + * @param[out] c - the result. + * @param[in] a - the field element to square. + */ +void fp3_sqrm_low(fp3_t c, fp3_t a); + +/** + * Reduces a cubic extension element modulo the configured prime p. + * Computes c = a mod p. + * + * @param[out] c - the result. + * @param[in] a - the digit vector to reduce. + */ +void fp3_rdcn_low(fp3_t c, dv3_t a); + +#endif /* !RLC_FPX_LOW_H */ diff --git a/bls/contrib/relic/include/relic.h b/bls/contrib/relic/include/relic.h new file mode 100644 index 00000000..ca362962 --- /dev/null +++ b/bls/contrib/relic/include/relic.h @@ -0,0 +1,112 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 . + */ + +/** + * @mainpage + * + * 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. + * + * @section goals_sec Goals + * + * RELIC is an ongoing project and features will be added on demand. + * The focus is to provide: + * + *
    + *
  • Ease of portability and inclusion of architecture-dependent code + *
  • Simple experimentation with alternative implementations + *
  • Tests and benchmarks for every implemented function + *
  • Flexible configuration + *
  • Maximum efficiency + *
+ * + * @section algo_sec Algorithms + * + * RELIC implements to date: + * + *
    + *
  • Multiple-precision integer arithmetic + *
  • Prime and Binary field arithmetic + *
  • Elliptic curves over prime and binary fields (NIST curves and + * pairing-friendly curves) + *
  • Bilinear maps and related extension fields + *
  • Cryptographic protocols + *
+ * + * @section lic_sec Licensing + * + * RELIC is dual-licensed under Apache 2.0 and LGPL 2.1-or-above to encourage + * collaboration with other research groups and contributions from the industry. + * You can choose between one of them. + * + * @section disc_sec Disclaimer + * + * RELIC is at most alpha-quality software. Implementations may not be correct + * or secure and may include patented algorithms. There are many configuration + * options which make the library horribly insecure. Backward API compatibility + * with early versions may not necessarily be maintained. Use at your own risk. + */ + +/** + * @file + * + * Library interface. + * + */ + +#ifndef RLC_H +#define RLC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "relic_arch.h" +#include "relic_conf.h" +#include "relic_core.h" +#include "relic_types.h" +#include "relic_bn.h" +#include "relic_dv.h" +#include "relic_fp.h" +#include "relic_fpx.h" +#include "relic_fb.h" +#include "relic_fbx.h" +#include "relic_ep.h" +#include "relic_eb.h" +#include "relic_ed.h" +#include "relic_ec.h" +#include "relic_pp.h" +#include "relic_pc.h" +#include "relic_cp.h" +#include "relic_bc.h" +#include "relic_md.h" +#include "relic_err.h" +#include "relic_rand.h" +#include "relic_util.h" + +#ifdef __cplusplus +} +#endif + +#endif /* !RLC_H */ diff --git a/bls/contrib/relic/include/relic_alloc.h b/bls/contrib/relic/include/relic_alloc.h new file mode 100644 index 00000000..caebe38d --- /dev/null +++ b/bls/contrib/relic/include/relic_alloc.h @@ -0,0 +1,87 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 auxiliary memory allocation functions. + * + * @ingroup utils + */ + +#include "relic_conf.h" + +#ifdef _MSC_VER + +#include + +/* + * Dynamiclly allocates an array of "Type" with the specified size on the stack. + * This memory will be automaticlly deallocated from the stack when the function + * frame is returned from. + * Note: This is the Windows specific implementation. + * + * @param[in] T - the type of each object. + * @param[in] S - the number of obecs to allocate. + */ +#if ALLOC == DYNAMIC +#define RLC_ALLOCA(T, S) (T*) calloc((S), sizeof(T)) +#else +#define RLC_ALLOCA(T, S) (T*) _alloca((S) * sizeof(T)) +#endif + +#else /* _MSC_VER */ + +#include + +/* + * Dynamiclly allocates an array of "Type" with the specified size on the stack. + * This memory will be automaticlly deallocated from the stack when the function + * frame is returned from. + * Note: This is the POSIX specific implementation. + * + * @param[in] T - the type of each object. + * @param[in] S - the number of obecs to allocate. + */ +#if ALLOC == DYNAMIC +#define RLC_ALLOCA(T, S) (T*) malloc((S) * sizeof(T)) +#else +#define RLC_ALLOCA(T, S) (T*) alloca((S) * sizeof(T)) +#endif + +#endif + +/* + * Free memory allocated with RLC_ALLOCA. + * + * @param[in] A - the variable to free. + */ +#if ALLOC == DYNAMIC +#define RLC_FREE(A) \ + if (A != NULL) { \ + free(A); \ + A = NULL; \ + } +#else +#define RLC_FREE(A) (void)A; +#endif diff --git a/bls/contrib/relic/include/relic_arch.h b/bls/contrib/relic/include/relic_arch.h new file mode 100644 index 00000000..9990a693 --- /dev/null +++ b/bls/contrib/relic/include/relic_arch.h @@ -0,0 +1,106 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 . + */ + +/** + * @defgroup arch Architecture-dependent utilities + */ + +/** + * @file + * + * Interface of architecture-dependent functions. + * + * @ingroup arch + */ + +#ifndef RLC_ARCH_H +#define RLC_ARCH_H + +#include "relic_types.h" +#include "relic_label.h" + +#if ARCH == AVR +#include +#endif + +/*============================================================================*/ +/* Macro definitions */ +/*============================================================================*/ + +/** + * Chooses a proper way to store a string in the target architecture. + * + * @param[in] S - the string to store. + */ +#if ARCH == AVR +#define RLC_STR(S) PSTR(S) +#else +#define RLC_STR(S) S +#endif + +/** + * Fetches a constant string to be used by the library. + * + * @param[out] S - the resulting prepared parameter. + * @param[in] ID - the parameter represented as a string. + * @param[in] L - the length of the string. + */ +#if ARCH == AVR +#define RLC_GET(S, ID, L) arch_copy_rom(S, RLC_STR(ID), L); +#else +#define RLC_GET(S, ID, L) memcpy(S, ID, L); +#endif + +/*============================================================================*/ +/* Function prototypes */ +/*============================================================================*/ + +/** + * Performs architecture-dependent initialization. + */ +void arch_init(void); + +/** + * Performs architecture-dependent finalization. + */ +void arch_clean(void); + +/** + * Return the number of elapsed cycles. + */ +ull_t arch_cycles(void); + +#if ARCH == AVR + +/** + * Copies a string from the text section to the destination vector. + * + * @param[out] dest - the destination vector. + * @param[in] src - the pointer to the string stored on the text section. + * @param[in] len - the length of the string. + */ +void arch_copy_rom(char *dest, const char *src, int len); + +#endif + +#endif /* !RLC_ARCH_H */ diff --git a/bls/contrib/relic/include/relic_bc.h b/bls/contrib/relic/include/relic_bc.h new file mode 100644 index 00000000..46457de3 --- /dev/null +++ b/bls/contrib/relic/include/relic_bc.h @@ -0,0 +1,84 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 . + */ + +/** + * @defgroup bc Block ciphers + */ + +/** + * @file + * + * Interface of the module for encrypting with block ciphers. + * + * @ingroup bc + */ + +#ifndef RLC_BC_H +#define RLC_BC_H + +#include "relic_conf.h" +#include "relic_types.h" +#include "relic_label.h" + +/*============================================================================*/ +/* Constant definitions */ +/*============================================================================*/ + +/** + * Length in bytes of the default block cipher length. + */ +#define RLC_BC_LEN 16 + +/*============================================================================*/ +/* Function prototypes */ +/*============================================================================*/ + +/** + * Encrypts with AES in CBC mode. + * + * @param[out] out - the resulting ciphertext. + * @param[in,out] out_len - the buffer capacity and number of bytes written. + * @param[in] in - the bytes to be encrypted. + * @param[in] in_len - the number of bytes to encrypt. + * @param[in] key - the key. + * @param[in] key_len - the key size in bytes. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int bc_aes_cbc_enc(uint8_t *out, int *out_len, uint8_t *in, + int in_len, uint8_t *key, int key_len, uint8_t *iv); + +/** + * Decrypts with AES in CBC mode. + * + * @param[out] out - the resulting plaintext. + * @param[in,out] out_len - the buffer capacity and number of bytes written. + * @param[in] in - the bytes to be decrypted. + * @param[in] in_len - the number of bytes to decrypt. + * @param[in] key - the key. + * @param[in] key_len - the key size in bytes. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int bc_aes_cbc_dec(uint8_t *out, int *out_len, uint8_t *in, + int in_len, uint8_t *key, int key_len, uint8_t *iv); + +#endif /* !RLC_BC_H */ diff --git a/bls/contrib/relic/include/relic_bench.h b/bls/contrib/relic/include/relic_bench.h new file mode 100644 index 00000000..2ccdd09e --- /dev/null +++ b/bls/contrib/relic/include/relic_bench.h @@ -0,0 +1,202 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 . + */ + +/** + * @defgroup bench Automated benchmarks + */ + +/** + * @file + * + * Interface of useful routines for benchmarking. + * + * @ingroup bench + */ + +#ifndef RLC_BENCH_H +#define RLC_BENCH_H + +#include "relic_conf.h" +#include "relic_label.h" +#include "relic_util.h" + +/*============================================================================*/ +/* Macro definitions */ +/*============================================================================*/ + +/** + * Runs a new benchmark once. + * + * @param[in] LABEL - the label for this benchmark. + * @param[in] FUNCTION - the function to benchmark. + */ +#define BENCH_ONCE(LABEL, FUNCTION) \ + bench_reset(); \ + util_print("BENCH: " LABEL "%*c = ", (int)(32 - strlen(LABEL)), ' '); \ + bench_before(); \ + FUNCTION; \ + bench_after(); \ + bench_compute(1); \ + bench_print(); \ + +/** + * Runs a new benchmark a small number of times. + * + * @param[in] LABEL - the label for this benchmark. + * @param[in] FUNCTION - the function to benchmark. + */ +#define BENCH_SMALL(LABEL, FUNCTION) \ + bench_reset(); \ + util_print("BENCH: " LABEL "%*c = ", (int)(32 - strlen(LABEL)), ' '); \ + bench_before(); \ + for (int i = 0; i < BENCH; i++) { \ + FUNCTION; \ + } \ + bench_after(); \ + bench_compute(BENCH); \ + bench_print(); \ + +/** + * Runs a new benchmark. + * + * @param[in] LABEL - the label for this benchmark. + */ +#define BENCH_BEGIN(LABEL) \ + bench_reset(); \ + util_print("BENCH: " LABEL "%*c = ", (int)(32 - strlen(LABEL)), ' '); \ + for (int _b = 0; _b < BENCH; _b++) { \ + +/** + * Prints the average timing of each execution in the chosen metric. + */ +#define BENCH_END \ + } \ + bench_compute(BENCH * BENCH); \ + bench_print() \ + +/** + * Prints the average timing of each execution amortized by N. + * + * @param N - the amortization factor. + */ +#define BENCH_DIV(N) \ + } \ + bench_compute(BENCH * BENCH * N); \ + bench_print() \ + +/** + * Measures the time of one execution and adds it to the benchmark total. + * + * @param[in] FUNCTION - the function executed. + */ +#define BENCH_ADD(FUNCTION) \ + FUNCTION; \ + bench_before(); \ + for (int _b = 0; _b < BENCH; _b++) { \ + FUNCTION; \ + } \ + bench_after(); \ + +/*============================================================================*/ +/* Type definitions */ +/*============================================================================*/ + +/** + * Timer type. + */ +#if OPSYS == DUINO && TIMER == HREAL + +typedef uint32_t bench_t; + +#elif TIMER == HREAL || TIMER == HPROC || TIMER == HTHRD + +#include +#include +typedef struct timespec bench_t; + +#elif TIMER == ANSI + +#include +typedef clock_t bench_t; + +#elif TIMER == POSIX + +#include +typedef struct timeval bench_t; + +#elif TIMER == CYCLE + +typedef unsigned long long bench_t; + +#else + +typedef unsigned long long bench_t; + +#endif + +/*============================================================================*/ +/* Function prototypes */ +/*============================================================================*/ + +/** + * Measures and prints benchmarking overhead. + */ +void bench_overhead(void); + +/** + * Resets the benchmark data. + * + * @param[in] label - the benchmark label. + */ +void bench_reset(void); + +/** + * Measures the time before a benchmark is executed. + */ +void bench_before(void); + +/** + * Measures the time after a benchmark was started and adds it to the total. + */ +void bench_after(void); + +/** + * Computes the mean elapsed time between the start and the end of a benchmark. + * + * @param benches - the number of executed benchmarks. + */ +void bench_compute(int benches); + +/** + * Prints the last benchmark. + */ +void bench_print(void); + +/** + * Returns the result of the last benchmark. + * + * @return the last benchmark. + */ +ull_t bench_total(void); + +#endif /* !RLC_BENCH_H */ diff --git a/bls/contrib/relic/include/relic_bn.h b/bls/contrib/relic/include/relic_bn.h new file mode 100644 index 00000000..adbdac72 --- /dev/null +++ b/bls/contrib/relic/include/relic_bn.h @@ -0,0 +1,1377 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 . + */ + +/** + * @defgroup bn Multiple precision integer arithmetic + */ + +/** + * @file + * + * Interface of the module for multiple precision integer arithmetic. + * + * @ingroup bn + */ + +#ifndef RLC_BN_H +#define RLC_BN_H + +#include "relic_conf.h" +#include "relic_util.h" +#include "relic_types.h" +#include "relic_label.h" + +/*============================================================================*/ +/* Constant definitions */ +/*============================================================================*/ + +/** + * Precision in bits of a multiple precision integer. + * + * If the library is built with support for dynamic allocation, this constant + * represents the size in bits of the memory block allocated each time a + * multiple precision integer must grow. Otherwise, it represents the fixed + * fixed precision. + */ +#define RLC_BN_BITS ((int)BN_PRECI) + +/** + * Size in digits of a block sufficient to store the required precision. + */ +#define RLC_BN_DIGS ((int)RLC_CEIL(BN_PRECI, RLC_DIG)) + +/** + * Size in digits of a block sufficient to store a multiple precision integer. + */ +#if BN_MAGNI == DOUBLE +#define RLC_BN_SIZE ((int)(2 * RLC_BN_DIGS + 2)) +#elif BN_MAGNI == CARRY +#define RLC_BN_SIZE ((int)(RLC_BN_DIGS + 1)) +#elif BN_MAGNI == SINGLE +#define RLC_BN_SIZE ((int)RLC_BN_DIGS) +#endif + +/** + * Positive sign of a multiple precision integer. + */ +#define RLC_POS 0 + +/** + * Negative sign of a multiple precision integer. + */ +#define RLC_NEG 1 + +/*============================================================================*/ +/* Type definitions */ +/*============================================================================*/ + +/** + * Represents a multiple precision integer. + * + * The field dp points to a vector of digits. These digits are organized + * in little-endian format, that is, the least significant digits are + * stored in the first positions of the vector. + */ +typedef struct { + /** The number of digits allocated to this multiple precision integer. */ + int alloc; + /** The number of digits actually used. */ + int used; + /** The sign of this multiple precision integer. */ + int sign; +#if ALLOC == DYNAMIC + /** The sequence of contiguous digits that forms this integer. */ + dig_t *dp; +#elif ALLOC == STACK || ALLOC == AUTO + /** The sequence of contiguous digits that forms this integer. */ + rlc_align dig_t dp[RLC_BN_SIZE]; +#endif +} bn_st; + +/** + * Pointer to a multiple precision integer structure. + */ +#if ALLOC == AUTO +typedef bn_st bn_t[1]; +#else +typedef bn_st *bn_t; +#endif + +/*============================================================================*/ +/* Macro definitions */ +/*============================================================================*/ + +/** + * Initializes a multiple precision integer with a null value. + * + * @param[out] A - the multiple precision integer to initialize. + */ +#if ALLOC == AUTO +#define bn_null(A) /* empty */ +#else +#define bn_null(A) A = NULL; +#endif + +/** + * Calls a function to allocate and initialize a multiple precision integer. + * + * @param[in,out] A - the multiple precision integer to initialize. + * @throw ERR_NO_MEMORY - if there is no available memory. + */ +#if ALLOC == DYNAMIC +#define bn_new(A) \ + A = (bn_t)calloc(1, sizeof(bn_st)); \ + if ((A) == NULL) { \ + THROW(ERR_NO_MEMORY); \ + } \ + bn_init(A, RLC_BN_SIZE); \ + +#elif ALLOC == AUTO +#define bn_new(A) \ + bn_init(A, RLC_BN_SIZE); \ + +#elif ALLOC == STACK +#define bn_new(A) \ + A = (bn_t)alloca(sizeof(bn_st)); \ + bn_init(A, RLC_BN_SIZE); \ + +#endif + +/** + * Calls a function to allocate and initialize a multiple precision integer + * with the required precision in digits. + * + * @param[in,out] A - the multiple precision integer to initialize. + * @param[in] D - the precision in digits. + * @throw ERR_NO_MEMORY - if there is no available memory. + * @throw ERR_PRECISION - if the required precision cannot be represented + * by the library. + */ +#if ALLOC == DYNAMIC +#define bn_new_size(A, D) \ + A = (bn_t)calloc(1, sizeof(bn_st)); \ + if (A == NULL) { \ + THROW(ERR_NO_MEMORY); \ + } \ + bn_init(A, D); \ + +#elif ALLOC == AUTO +#define bn_new_size(A, D) \ + bn_init(A, D); \ + +#elif ALLOC == STACK +#define bn_new_size(A, D) \ + A = (bn_t)alloca(sizeof(bn_st)); \ + bn_init(A, D); \ + +#endif + +/** + * Calls a function to clean and free a multiple precision integer. + * + * @param[in,out] A - the multiple precision integer to free. + */ +#if ALLOC == DYNAMIC +#define bn_free(A) \ + if (A != NULL) { \ + bn_clean(A); \ + free(A); \ + A = NULL; \ + } + +#elif ALLOC == AUTO +#define bn_free(A) /* empty */ \ + +#elif ALLOC == STACK +#define bn_free(A) \ + A = NULL; \ + +#endif + +/** + * Multiples two multiple precision integers. Computes c = a * b. + * + * @param[out] C - the result. + * @param[in] A - the first multiple precision integer to multiply. + * @param[in] B - the second multiple precision integer to multiply. + */ +#if BN_KARAT > 0 +#define bn_mul(C, A, B) bn_mul_karat(C, A, B) +#elif BN_MUL == BASIC +#define bn_mul(C, A, B) bn_mul_basic(C, A, B) +#elif BN_MUL == COMBA +#define bn_mul(C, A, B) bn_mul_comba(C, A, B) +#endif + +/** + * Computes the square of a multiple precision integer. Computes c = a * a. + * + * @param[out] C - the result. + * @param[in] A - the multiple precision integer to square. + */ +#if BN_KARAT > 0 +#define bn_sqr(C, A) bn_sqr_karat(C, A) +#elif BN_SQR == BASIC +#define bn_sqr(C, A) bn_sqr_basic(C, A) +#elif BN_SQR == COMBA +#define bn_sqr(C, A) bn_sqr_comba(C, A) +#elif BN_SQR == MULTP +#define bn_sqr(C, A) bn_mul(C, A, A) +#endif + +/** + * Computes the auxiliar value derived from the modulus to be used during + * modular reduction. + * + * @param[out] U - the result. + * @param[in] M - the modulus. + */ +#if BN_MOD == BASIC +#define bn_mod_pre(U, M) (void)(U), (void)(M) +#elif BN_MOD == BARRT +#define bn_mod_pre(U, M) bn_mod_pre_barrt(U, M) +#elif BN_MOD == MONTY +#define bn_mod_pre(U, M) bn_mod_pre_monty(U, M) +#elif BN_MOD == PMERS +#define bn_mod_pre(U, M) bn_mod_pre_pmers(U, M) +#endif + +/** + * Reduces a multiple precision integer modulo another integer. If the number + * of arguments is 3, then simple division is used. If the number of arguments + * is 4, then a modular reduction algorithm is used and the fourth argument + * is an auxiliary value derived from the modulus. The variant with 4 arguments + * should be used when several modular reductions are computed with the same + * modulus. Computes c = a mod m. + * + * @param[out] C - the result. + * @param[in] A - the multiple precision integer to reduce. + * @param[in] ... - the modulus and an optional argument. + */ +#define bn_mod(C, A, ...) RLC_CAT(bn_mod, RLC_OPT(__VA_ARGS__))(C, A, __VA_ARGS__) + +/** + * Reduces a multiple precision integer modulo another integer. This macro + * should not be called directly. Use bn_mod with 4 arguments instead. + * + * @param[out] C - the result. + * @param[in] A - the the multiple precision integer to reduce. + * @param[in] M - the modulus. + * @param[in] U - the auxiliar value derived from the modulus. + */ +#if BN_MOD == BASIC +#define bn_mod_imp(C, A, M, U) bn_mod_basic(C, A, M) +#elif BN_MOD == BARRT +#define bn_mod_imp(C, A, M, U) bn_mod_barrt(C, A, M, U) +#elif BN_MOD == MONTY +#define bn_mod_imp(C, A, M, U) bn_mod_monty(C, A, M, U) +#elif BN_MOD == PMERS +#define bn_mod_imp(C, A, M, U) bn_mod_pmers(C, A, M, U) +#endif + +/** + * Reduces a multiple precision integer modulo a positive integer using + * Montgomery reduction. Computes c = a * u^(-1) (mod m). + * + * @param[out] C - the result. + * @param[in] A - the multiple precision integer to reduce. + * @param[in] M - the modulus. + * @param[in] U - the reciprocal of the modulus. + */ +#if BN_MUL == BASIC +#define bn_mod_monty(C, A, M, U) bn_mod_monty_basic(C, A, M, U) +#elif BN_MUL == COMBA +#define bn_mod_monty(C, A, M, U) bn_mod_monty_comba(C, A, M, U) +#endif + +/** + * Exponentiates a multiple precision integer modulo another multiple precision + * integer. Computes c = a^b mod m. If Montgomery reduction is used, the basis + * must not be in Montgomery form. + * + * @param[out] C - the result. + * @param[in] A - the basis. + * @param[in] B - the exponent. + * @param[in] M - the modulus. + */ +#if BN_MXP == BASIC +#define bn_mxp(C, A, B, M) bn_mxp_basic(C, A, B, M) +#elif BN_MXP == SLIDE +#define bn_mxp(C, A, B, M) bn_mxp_slide(C, A, B, M) +#elif BN_MXP == MONTY +#define bn_mxp(C, A, B, M) bn_mxp_monty(C, A, B, M) +#endif + +/** + * Computes the greatest common divisor of two multiple precision integers. + * Computes c = gcd(a, b). + * + * @param[out] C - the result; + * @param[in] A - the first multiple precision integer. + * @param[in] B - the second multiple precision integer. + */ +#if BN_GCD == BASIC +#define bn_gcd(C, A, B) bn_gcd_basic(C, A, B) +#elif BN_GCD == LEHME +#define bn_gcd(C, A, B) bn_gcd_lehme(C, A, B) +#elif BN_GCD == STEIN +#define bn_gcd(C, A, B) bn_gcd_stein(C, A, B) +#endif + +/** + * Computes the extended greatest common divisor of two multiple precision + * integers. This function can be used to compute multiplicative inverses. + * Computes c = gcd(a, b) and c = a * d + b * e. + * + * @param[out] C - the result; + * @param[out] D - the cofactor of the first operand, cannot be NULL. + * @param[out] E - the cofactor of the second operand, can be NULL. + * @param[in] A - the first multiple precision integer. + * @param[in] B - the second multiple precision integer. + */ +#if BN_GCD == BASIC +#define bn_gcd_ext(C, D, E, A, B) bn_gcd_ext_basic(C, D, E, A, B) +#elif BN_GCD == LEHME +#define bn_gcd_ext(C, D, E, A, B) bn_gcd_ext_lehme(C, D, E, A, B) +#elif BN_GCD == STEIN +#define bn_gcd_ext(C, D, E, A, B) bn_gcd_ext_stein(C, D, E, A, B) +#endif + +/** + * Generates a probable prime number. + * + * @param[out] A - the result. + * @param[in] B - the length of the number in bits. + */ +#if BN_GEN == BASIC +#define bn_gen_prime(A, B) bn_gen_prime_basic(A, B) +#elif BN_GEN == SAFEP +#define bn_gen_prime(A, B) bn_gen_prime_safep(A, B) +#elif BN_GEN == STRON +#define bn_gen_prime(A, B) bn_gen_prime_stron(A, B) +#endif + +/*============================================================================*/ +/* Function prototypes */ +/*============================================================================*/ + +/** + * Initializes a previously allocated multiple precision integer. + * + * @param[out] a - the multiple precision integer to initialize. + * @param[in] digits - the required precision in digits. + * @throw ERR_NO_MEMORY - if there is no available memory. + * @throw ERR_PRECISION - if the required precision cannot be represented + * by the library. + */ +void bn_init(bn_t a, int digits); + +/** + * Cleans a multiple precision integer. + * + * @param[out] a - the multiple precision integer to free. + */ +void bn_clean(bn_t a); + +/** + * Checks the current precision of a multiple precision integer and optionally + * expands its precision to a given size in digits. + * + * @param[out] a - the multiple precision integer to expand. + * @param[in] digits - the number of digits to expand. + * @throw ERR_NO_MEMORY - if there is no available memory. + * @throw ERR_PRECISION - if the required precision cannot be represented + * by the library. + */ +void bn_grow(bn_t a, int digits); + +/** + * Adjust the number of valid digits of a multiple precision integer. + * + * @param[out] a - the multiple precision integer to adjust. + */ +void bn_trim(bn_t a); + +/** + * Copies the second argument to the first argument. + * + * @param[out] c - the result. + * @param[in] a - the multiple precision integer to copy. + */ +void bn_copy(bn_t c, const bn_t a); + +/** + * Returns the absolute value of a multiple precision integer. + * + * @param[out] c - the result. + * @param[in] a - the argument of the absolute function. + */ +void bn_abs(bn_t c, const bn_t a); + +/** + * Inverts the sign of a multiple precision integer. + * + * @param[out] c - the result. + * @param[out] a - the multiple precision integer to negate. + */ +void bn_neg(bn_t c, const bn_t a); + +/** + * Returns the sign of a multiple precision integer. + * + * @param[in] a - the multiple precision integer. + * @return RLC_POS if the argument is positive and RLC_NEG otherwise. + */ +int bn_sign(const bn_t a); + +/** + * Assigns zero to a multiple precision integer. + * + * @param[out] a - the multiple precision integer to assign. + */ +void bn_zero(bn_t a); + +/** + * Tests if a multiple precision integer is zero or not. + * + * @param[in] a - the multiple precision integer to test. + * @return 1 if the argument is zero, 0 otherwise. + */ +int bn_is_zero(const bn_t a); + +/** + * Tests if a multiple precision integer is even or odd. + * + * @param[in] a - the multiple precision integer to test. + * @return 1 if the argument is even, 0 otherwise. + */ +int bn_is_even(const bn_t a); + +/** + * Returns the number of bits of a multiple precision integer. + * + * @param[in] a - the multiple precision integer. + * @return number of bits. + */ +int bn_bits(const bn_t a); + +/** + * Returns the bit stored in the given position on a multiple precision integer. + * + * @param[in] a - the multiple precision integer. + * @param[in] bit - the bit position to read. + * @return the bit value. + */ +int bn_get_bit(const bn_t a, int bit); + +/** + * Stores a bit in a given position on a multiple precision integer. + * + * @param[out] a - the multiple precision integer. + * @param[in] bit - the bit position to store. + * @param[in] value - the bit value. + */ +void bn_set_bit(bn_t a, int bit, int value); + +/** + * Returns the Hamming weight of a multiple precision integer. + * + * @param[in] a - the multiple precision integer. + * @return the number of non-zero bits. + */ +int bn_ham(const bn_t a); + +/** + * Reads the first digit in a multiple precision integer. + * + * @param[out] digit - the result. + * @param[in] a - the multiple precision integer. + */ +void bn_get_dig(dig_t *digit, const bn_t a); + +/** + * Assigns a small positive constant to a multiple precision integer. + * + * The constant must fit on a multiple precision digit, or dig_t type using + * only the number of bits specified on RLC_DIG. + * + * @param[out] a - the result. + * @param[in] digit - the constant to assign. + */ +void bn_set_dig(bn_t a, dig_t digit); + +/** + * Assigns a multiple precision integer to 2^b. + * + * @param[out] a - the result. + * @param[in] b - the power of 2 to assign. + */ +void bn_set_2b(bn_t a, int b); + +/** + * Assigns a random value to a multiple precision integer. + * + * @param[out] a - the multiple precision integer to assign. + * @param[in] sign - the sign to be assigned (RLC_NEG or RLC_POS). + * @param[in] bits - the number of bits. + */ +void bn_rand(bn_t a, int sign, int bits); + +/** + * Assigns a non-zero random value to a multiple precision integer with absolute + * value smaller than a given modulus. + * + * @param[out] a - the multiple precision integer to assign. + * @param[in] b - the modulus. + */ +void bn_rand_mod(bn_t a, bn_t b); + +/** + * Prints a multiple precision integer to standard output. + * + * @param[in] a - the multiple precision integer to print. + */ +void bn_print(const bn_t a); + +/** + * Returns the number of digits in radix necessary to store a multiple precision + * integer. The radix must be included in the interval [2, 64]. + * + * @param[in] a - the multiple precision integer. + * @param[in] radix - the radix. + * @throw ERR_NO_VALID - if the radix is invalid. + * @return the number of digits in the given radix. + */ +int bn_size_str(const bn_t a, int radix); + +/** + * Reads a multiple precision integer from a string in a given radix. The radix + * must be included in the interval [2, 64]. + * + * @param[out] a - the result. + * @param[in] str - the string. + * @param[in] len - the size of the string. + * @param[in] radix - the radix. + * @throw ERR_NO_VALID - if the radix is invalid. + */ +void bn_read_str(bn_t a, const char *str, int len, int radix); + +/** + * Writes a multiple precision integer to a string in a given radix. The radix + * must be included in the interval [2, 64]. + * + * @param[out] str - the string. + * @param[in] len - the buffer capacity. + * @param[in] a - the multiple integer to write. + * @param[in] radix - the radix. + * @throw ERR_NO_BUFFER - if the buffer capacity is insufficient. + * @throw ERR_NO_VALID - if the radix is invalid. + */ +void bn_write_str(char *str, int len, const bn_t a, int radix); + +/** + * Returns the number of bytes necessary to store a multiple precision integer. + * + * @param[in] a - the multiple precision integer. + * @return the number of bytes. + */ +int bn_size_bin(const bn_t a); + +/** + * Reads a positive multiple precision integer 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. + */ +void bn_read_bin(bn_t a, const uint8_t *bin, int len); + +/** + * Writes a positive multiple precision integer to a byte vector in big-endian + * format. + * + * @param[out] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @param[in] a - the multiple integer to write. + * @throw ERR_NO_BUFFER - if the buffer capacity is insufficient. + */ +void bn_write_bin(uint8_t *bin, int len, const bn_t a); + +/** + * Returns the number of digits necessary to store a multiple precision integer. + * + * @param[in] a - the multiple precision integer. + * @return the number of digits. + */ +int bn_size_raw(const bn_t a); + +/** + * Reads a positive multiple precision integer from a digit vector. + * + * @param[out] a - the result. + * @param[in] raw - the digit vector. + * @param[in] len - the size of the string. + */ +void bn_read_raw(bn_t a, const dig_t *raw, int len); + +/** + * Writes a positive multiple precision integer to a byte vector. + * + * @param[out] raw - the digit vector. + * @param[in] len - the buffer capacity. + * @param[in] a - the multiple integer to write. + * @throw ERR_NO_BUFFER - if the buffer capacity is insufficient. + */ +void bn_write_raw(dig_t *raw, int len, const bn_t a); + +/** + * Returns the result of an unsigned comparison between two multiple precision + * integers. + * + * @param[in] a - the first multiple precision integer. + * @param[in] b - the second multiple precision integer. + * @return RLC_LT if a < b, RLC_EQ if a == b and RLC_GT if a > b. + */ +int bn_cmp_abs(const bn_t a, const bn_t b); + +/** + * Returns the result of a signed comparison between a multiple precision + * integer and a digit. + * + * @param[in] a - the multiple precision integer. + * @param[in] b - the digit. + * @return RLC_LT if a < b, RLC_EQ if a == b and RLC_GT if a > b. + */ +int bn_cmp_dig(const bn_t a, dig_t b); + +/** + * Returns the result of a signed comparison between two multiple precision + * integers. + * + * @param[in] a - the first multiple precision integer. + * @param[in] b - the second multiple precision integer. + * @return RLC_LT if a < b, RLC_EQ if a == b and RLC_GT if a > b. + */ +int bn_cmp(const bn_t a, const bn_t b); + +/** + * Adds two multiple precision integers. Computes c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the first multiple precision integer to add. + * @param[in] b - the second multiple precision integer to add. + */ +void bn_add(bn_t c, const bn_t a, const bn_t b); + +/** + * Adds a multiple precision integers and a digit. Computes c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the multiple precision integer to add. + * @param[in] b - the digit to add. + */ +void bn_add_dig(bn_t c, const bn_t a, dig_t b); + +/** + * Subtracts a multiple precision integer from another, that is, computes + * c = a - b. + * + * @param[out] c - the result. + * @param[in] a - the multiple precision integer. + * @param[in] b - the multiple precision integer to subtract. + */ +void bn_sub(bn_t c, const bn_t a, const bn_t b); + +/** + * Subtracts a digit from a multiple precision integer. Computes c = a - b. + * + * @param[out] c - the result. + * @param[in] a - the multiple precision integer. + * @param[in] b - the digit to subtract. + */ +void bn_sub_dig(bn_t c, const bn_t a, const dig_t b); + +/** + * Multiplies a multiple precision integer by a digit. Computes c = a * b. + * + * @param[out] c - the result. + * @param[in] a - the multiple precision integer to multiply. + * @param[in] b - the digit to multiply. + */ +void bn_mul_dig(bn_t c, const bn_t a, dig_t b); + +/** + * Multiplies two multiple precision integers using Schoolbook multiplication. + * + * @param[out] c - the result. + * @param[in] a - the first multiple precision integer to multiply. + * @param[in] b - the second multiple precision integer to multiply. + */ +void bn_mul_basic(bn_t c, const bn_t a, const bn_t b); + +/** + * Multiplies two multiple precision integers using Comba multiplication. + * + * @param[out] c - the result. + * @param[in] a - the first multiple precision integer to multiply. + * @param[in] b - the second multiple precision integer to multiply. + */ +void bn_mul_comba(bn_t c, const bn_t a, const bn_t b); + +/** + * Multiplies two multiple precision integers using Karatsuba multiplication. + * + * @param[out] c - the result. + * @param[in] a - the first multiple precision integer to multiply. + * @param[in] b - the second multiple precision integer to multiply. + */ +void bn_mul_karat(bn_t c, const bn_t a, const bn_t b); + +/** + * Computes the square of a multiple precision integer using Schoolbook + * squaring. + * + * @param[out] c - the result. + * @param[in] a - the multiple precision integer to square. + */ +void bn_sqr_basic(bn_t c, const bn_t a); + +/** + * Computes the square of a multiple precision integer using Comba squaring. + * + * @param[out] c - the result. + * @param[in] a - the multiple precision integer to square. + */ +void bn_sqr_comba(bn_t c, const bn_t a); + +/** + * Computes the square of a multiple precision integer using Karatsuba squaring. + * + * @param[out] c - the result. + * @param[in] a - the multiple precision integer to square. + */ +void bn_sqr_karat(bn_t c, const bn_t a); + +/** + * Doubles a multiple precision. Computes c = a + a. + * + * @param[out] c - the result. + * @param[in] a - the multiple precision integer to double. + */ +void bn_dbl(bn_t c, const bn_t a); + +/** + * Halves a multiple precision. Computes c = floor(a / 2) + * + * @param[out] c - the result. + * @param[in] a - the multiple precision integer to halve. + */ +void bn_hlv(bn_t c, const bn_t a); + +/** + * Shifts a multiple precision number to the left. Computes c = a * 2^bits. + * c = a * 2^bits. + * + * @param[out] c - the result. + * @param[in] a - the multiple precision integer to shift. + * @param[in] bits - the number of bits to shift. + */ +void bn_lsh(bn_t c, const bn_t a, int bits); + +/** + * Shifts a multiple precision number to the right. Computes + * c = floor(a / 2^bits). + * + * @param[out] c - the result. + * @param[in] a - the multiple precision integer to shift. + * @param[in] bits - the number of bits to shift. + */ +void bn_rsh(bn_t c, const bn_t a, int bits); + +/** + * Divides a multiple precision integer by another multiple precision integer + * without producing the positive remainder. Computes c = floor(a / b). + * + * @param[out] c - the resulting quotient. + * @param[in] a - the dividend. + * @param[in] b - the divisor. + * @throw ERR_NO_VALID - if the divisor is zero. + */ +void bn_div(bn_t c, const bn_t a, const bn_t b); + +/** + * Divides a multiple precision integer by another multiple precision integer + * and produces a positive remainder. Computes c = floor(a / b) and d = a mod b. + * + * @param[out] c - the resulting quotient. + * @param[out] d - the positive remainder. + * @param[in] a - the dividend. + * @param[in] b - the divisor. + * @throw ERR_NO_VALID - if the divisor is zero. + */ +void bn_div_rem(bn_t c, bn_t d, const bn_t a, const bn_t b); + +/** + * Divides a multiple precision integers by a digit without computing the + * remainder. Computes c = floor(a / b). + * + * @param[out] c - the resulting quotient. + * @param[out] d - the remainder. + * @param[in] a - the dividend. + * @param[in] b - the divisor. + * @throw ERR_NO_VALID - if the divisor is zero. + */ +void bn_div_dig(bn_t c, const bn_t a, dig_t b); + +/** + * Divides a multiple precision integers by a digit. Computes c = floor(a / b) + * and d = a mod b. + * + * @param[out] c - the resulting quotient. + * @param[out] d - the remainder. + * @param[in] a - the dividend. + * @param[in] b - the divisor. + * @throw ERR_NO_VALID - if the divisor is zero. + */ +void bn_div_rem_dig(bn_t c, dig_t *d, const bn_t a, const dig_t b); + +/** + * Reduces a multiple precision integer modulo a power of 2. Computes + * c = a mod 2^b. + * + * @param[out] c - the result. + * @param[in] a - the dividend. + * @param[in] b - the exponent of the divisor. + */ +void bn_mod_2b(bn_t c, const bn_t a, int b); + +/** + * Reduces a multiple precision integer modulo a digit. Computes c = a mod b. + * + * @param[out] c - the result. + * @param[in] a - the dividend. + * @param[in] b - the divisor. + */ +void bn_mod_dig(dig_t *c, const bn_t a, dig_t b); + +/** + * Reduces a multiple precision integer modulo an integer using straightforward + * division. + * + * @param[out] c - the result. + * @param[in] a - the multiple precision integer to reduce. + * @param[in] m - the modulus. + */ +void bn_mod_basic(bn_t c, const bn_t a, const bn_t m); + +/** + * Computes the reciprocal of the modulus to be used in the Barrett modular + * reduction algorithm. + * + * @param[out] u - the result. + * @param[in] m - the modulus. + */ +void bn_mod_pre_barrt(bn_t u, const bn_t m); + +/** + * Reduces a multiple precision integer modulo a positive integer using Barrett + * reduction. + * + * @param[out] c - the result. + * @param[in] a - the the multiple precision integer to reduce. + * @param[in] m - the modulus. + * @param[in] u - the reciprocal of the modulus. + */ +void bn_mod_barrt(bn_t c, const bn_t a, const bn_t m, const bn_t u); + +/** + * Computes the reciprocal of the modulus to be used in the Montgomery reduction + * algorithm. + * + * @param[out] u - the result. + * @param[in] m - the modulus. + * @throw ERR_NO_VALID - if the modulus is even. + */ +void bn_mod_pre_monty(bn_t u, const bn_t m); + +/** + * Converts a multiple precision integer to Montgomery form. + * + * @param[out] c - the result. + * @param[in] a - the multiple precision integer to convert. + * @param[in] m - the modulus. + */ +void bn_mod_monty_conv(bn_t c, const bn_t a, const bn_t m); + +/** + * Converts a multiple precision integer from Montgomery form. + * + * @param[out] c - the result. + * @param[in] a - the multiple precision integer to convert. + * @param[in] m - the modulus. + */ +void bn_mod_monty_back(bn_t c, const bn_t a, const bn_t m); + +/** + * Reduces a multiple precision integer modulo a positive integer using + * Montgomery reduction with Schoolbook multiplication. + * + * @param[out] c - the result. + * @param[in] a - the multiple precision integer to reduce. + * @param[in] m - the modulus. + * @param[in] u - the reciprocal of the modulus. + */ +void bn_mod_monty_basic(bn_t c, const bn_t a, const bn_t m, const bn_t u); + +/** + * Reduces a multiple precision integer modulo a positive integer using + * Montgomery reduction with Comba multiplication. + * + * @param[out] c - the result. + * @param[in] a - the multiple precision integer to reduce. + * @param[in] m - the modulus. + * @param[in] u - the reciprocal of the modulus. + */ +void bn_mod_monty_comba(bn_t c, const bn_t a, const bn_t m, const bn_t u); + +/** + * Computes u if the modulus has the form 2^b - u. + * + * @param[out] u - the result. + * @param[in] m - the modulus. + */ +void bn_mod_pre_pmers(bn_t u, const bn_t m); + +/** + * Reduces a multiple precision integer modulo a positive integer using + * pseudo-Mersenne modular reduction. + * + * @param[out] c - the result. + * @param[in] a - the multiple precision integer to reduce. + * @param[in] m - the modulus. + * @param[in] u - the auxiliar value derived from the modulus. + */ +void bn_mod_pmers(bn_t c, const bn_t a, const bn_t m, const bn_t u); + +/** + * Exponentiates a multiple precision integer modulo a positive integer using + * the binary method. + * + * @param[out] c - the result. + * @param[in] a - the basis. + * @param[in] b - the exponent. + * @param[in] m - the modulus. + */ +void bn_mxp_basic(bn_t c, const bn_t a, const bn_t b, const bn_t m); + +/** + * Exponentiates a multiple precision integer modulo a positive integer using + * the sliding window method. + * + * @param[out] c - the result. + * @param[in] a - the basis. + * @param[in] b - the exponent. + * @param[in] m - the modulus. + */ +void bn_mxp_slide(bn_t c, const bn_t a, const bn_t b, const bn_t m); + +/** + * Exponentiates a multiple precision integer modulo a positive integer using + * the constant-time Montgomery powering ladder method. + * + * @param[out] c - the result. + * @param[in] a - the basis. + * @param[in] b - the exponent. + * @param[in] m - the modulus. + */ +void bn_mxp_monty(bn_t c, const bn_t a, const bn_t b, const bn_t m); + +/** + * Exponentiates a multiple precision integer by a small power modulo a positive + * integer using the binary method. + * + * @param[out] c - the result. + * @param[in] a - the basis. + * @param[in] b - the exponent. + * @param[in] m - the modulus. + */ +void bn_mxp_dig(bn_t c, const bn_t a, dig_t b, const bn_t m); + +/** + * Extracts an approximate integer square-root of a multiple precision integer. + * + * @param[out] c - the result. + * @param[in] a - the multiple precision integer to extract. + * + * @throw ERR_NO_VALID - if the argument is negative. + */ +void bn_srt(bn_t c, bn_t a); + +/** + * Computes the greatest common divisor of two multiple precision integers + * using the standard Euclidean algorithm. + * + * @param[out] c - the result; + * @param[in] a - the first multiple precision integer. + * @param[in] b - the second multiple precision integer. + */ +void bn_gcd_basic(bn_t c, const bn_t a, const bn_t b); + +/** + * Computes the greatest common divisor of two multiple precision integers + * using Lehmer's GCD algorithm. + * + * @param[out] c - the result; + * @param[in] a - the first multiple precision integer. + * @param[in] b - the second multiple precision integer. + */ +void bn_gcd_lehme(bn_t c, const bn_t a, const bn_t b); + +/** + * Computes the greatest common divisor of two multiple precision integers + * using Stein's binary GCD algorithm. + * + * @param[out] c - the result; + * @param[in] a - the first multiple precision integer. + * @param[in] b - the second multiple precision integer. + */ +void bn_gcd_stein(bn_t c, const bn_t a, const bn_t b); + +/** + * Computes the greatest common divisor of a multiple precision integer and a + * digit. + * + * @param[out] c - the result; + * @param[in] a - the multiple precision integer. + * @param[in] b - the digit. + */ +void bn_gcd_dig(bn_t c, const bn_t a, dig_t b); + +/** + * Computes the extended greatest common divisor of two multiple precision + * integer using the Euclidean algorithm. + * + * @param[out] c - the result. + * @param[out] d - the cofactor of the first operand, can be NULL. + * @param[out] e - the cofactor of the second operand, can be NULL. + * @param[in] a - the first multiple precision integer. + * @param[in] b - the second multiple precision integer. + */ +void bn_gcd_ext_basic(bn_t c, bn_t d, bn_t e, const bn_t a, const bn_t b); + +/** + * Computes the greatest common divisor of two multiple precision integers + * using Lehmer's algorithm. + * + * @param[out] c - the result; + * @param[out] d - the cofactor of the first operand, can be NULL. + * @param[out] e - the cofactor of the second operand, can be NULL. + * @param[in] a - the first multiple precision integer. + * @param[in] b - the second multiple precision integer. + */ +void bn_gcd_ext_lehme(bn_t c, bn_t d, bn_t e, const bn_t a, const bn_t b); + +/** + * Computes the greatest common divisor of two multiple precision integers + * using Stein's binary algorithm. + * + * @param[out] c - the result; + * @param[out] d - the cofactor of the first operand, can be NULL. + * @param[out] e - the cofactor of the second operand, can be NULL. + * @param[in] a - the first multiple precision integer. + * @param[in] b - the second multiple precision integer. + */ +void bn_gcd_ext_stein(bn_t c, bn_t d, bn_t e, const bn_t a, const bn_t b); + +/** + * Computes the extended greatest common divisor of two multiple precision + * integers halfway through the algorithm. Returns also two short vectors + * v1 = (c, d), v2 = (-e, f) useful to decompose an integer k into k0, k1 such + * that k = k_0 + k_1 * a (mod b). + * + * @param[out] c - the first component of the first vector. + * @param[out] d - the second component of the first vector. + * @param[out] e - the first component of the second vector. + * @param[out] f - the second component of the second vector. + * @param[in] a - the first multiple precision integer. + * @param[in] b - the second multiple precision integer. + */ +void bn_gcd_ext_mid(bn_t c, bn_t d, bn_t e, bn_t f, const bn_t a, const bn_t b); + +/** + * Computes the extended greatest common divisor of a multiple precision integer + * and a digit. + * + * @param[out] c - the result. + * @param[out] d - the cofactor of the first operand, can be NULL. + * @param[out] e - the cofactor of the second operand, can be NULL. + * @param[in] a - the multiple precision integer. + * @param[in] b - the digit. + */ +void bn_gcd_ext_dig(bn_t c, bn_t d, bn_t e, const bn_t a, dig_t b); + +/** + * Computes the last common multiple of two multiple precision integers. + * Computes c = lcm(a, b). + * + * @param[out] c - the result. + * @param[in] a - the first integer. + * @param[in] b - the second integer. + */ +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. + */ +void bn_smb_leg(bn_t c, 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. + */ +void bn_smb_jac(bn_t c, const bn_t a, const bn_t b); + +/** + * Returns a small precomputed prime from a given position in the list of prime + * numbers. + * + * @param[in] pos - the position in the prime sequence. + * @return a prime if the position is lower than 512, 0 otherwise. + */ +dig_t bn_get_prime(int pos); + +/** + * Tests if a number is a probable prime. + * + * @param[in] a - the multiple precision integer to test. + * @return 1 if a is prime, 0 otherwise. + */ +int bn_is_prime(const bn_t a); + +/** + * Tests if a number is prime using a series of trial divisions. + * + * @param[in] a - the number to test. + * @return 1 if a is a probable prime, 0 otherwise. + */ +int bn_is_prime_basic(const bn_t a); + +/** + * Tests if a number a > 2 is prime using the Miller-Rabin test with probability + * 2^(-80) of error. + * + * @param[in] a - the number to test. + * @return 1 if a is a probable prime, 0 otherwise. + */ +int bn_is_prime_rabin(const bn_t a); + +/** + * Tests if a number a > 2 is prime using the Solovay-Strassen test with + * probability 2^(-80) of error. + * + * @param[in] a - the number to test. + * @return 1 if a is a probable prime, 0 otherwise. + */ +int bn_is_prime_solov(const bn_t a); + +/** + * Generates a probable prime number. + * + * @param[out] a - the result. + * @param[in] bits - the length of the number in bits. + */ +void bn_gen_prime_basic(bn_t a, int bits); + +/** + * Generates a probable prime number a with (a - 1)/2 also prime. + * + * @param[out] a - the result. + * @param[in] bits - the length of the number in bits. + */ +void bn_gen_prime_safep(bn_t a, int bits); + +/** + * Generates a probable prime number with (a - 1)/2, (a + 1)/2 and + * ((a - 1)/2 - 1)/2 also prime. + * + * @param[out] a - the result. + * @param[in] bits - the length of the number in bits. + */ +void bn_gen_prime_stron(bn_t a, int bits); + +/** + * Tries to factorize an integer using Pollard (p - 1) factoring algorithm. + * The maximum length of the returned factor is 16 bits. + * + * @param[out] c - the resulting factor. + * @param[in] a - the integer to fatorize. + * @return 1 if a factor is found and stored into c; 0 otherwise. + */ +int bn_factor(bn_t c, const bn_t a); + +/** + * Tests if an integer divides other integer. + * + * @param[in] c - the factor. + * @param[in] a - the integer. + * @return 1 if the first integer is a factor; 0 otherwise. + */ +int bn_is_factor(bn_t c, const bn_t a); + +/** + * Recodes a positive integer in window form. If a negative integer is given + * instead, its absolute value is taken. + * + * @param[out] win - the recoded integer. + * @param[out] len - the number of bytes written. + * @param[in] k - the integer to recode. + * @param[in] w - the window size in bits. + * @throw ERR_NO_BUFFER - if the buffer capacity is insufficient. + */ +void bn_rec_win(uint8_t *win, int *len, const bn_t k, int w); + +/** + * Recodes a positive integer in sliding window form. If a negative integer is + * given instead, its absolute value is taken. + * + * @param[out] win - the recoded integer. + * @param[out] len - the number of bytes written. + * @param[in] k - the integer to recode. + * @param[in] w - the window size in bits. + * @throw ERR_NO_BUFFER - if the buffer capacity is insufficient. + */ +void bn_rec_slw(uint8_t *win, int *len, const bn_t k, int w); + +/** + * Recodes a positive integer in width-w Non-Adjacent Form. If a negative + * integer is given instead, its absolute value is taken. + * + * @param[out] naf - the recoded integer. + * @param[out] len - the number of bytes written. + * @param[in] k - the integer to recode. + * @param[in] w - the window size in bits. + * @throw ERR_NO_BUFFER - if the buffer capacity is insufficient. + */ +void bn_rec_naf(int8_t *naf, int *len, const bn_t k, int w); + +/** + * Recodes a positive integer in width-w \tau-NAF. If a negative integer is + * given instead, its absolute value is taken. + * + * @param[out] tnaf - the recoded integer. + * @param[out] len - the number of bytes written. + * @param[in] k - the integer to recode. + * @param[in] u - the u curve parameter. + * @param[in] m - the extension degree of the binary field. + * @param[in] w - the window size in bits. + * @throw ERR_NO_BUFFER - if the buffer capacity is insufficient. + */ +void bn_rec_tnaf(int8_t *tnaf, int *len, const bn_t k, int8_t u, int m, int w); + +/** + * Recodes a positive integer in regular fixed-length width-w \tau-NAF. + * If a negative integer is given instead, its absolute value is taken. + * + * @param[out] tnaf - the recoded integer. + * @param[out] len - the number of bytes written. + * @param[in] k - the integer to recode. + * @param[in] u - the u curve parameter. + * @param[in] m - the extension degree of the binary field. + * @param[in] w - the window size in bits. + * @throw ERR_NO_BUFFER - if the buffer capacity is insufficient. + */ +void bn_rec_rtnaf(int8_t *tnaf, int *len, const bn_t k, int8_t u, int m, int w); + +/** + * Write the constants needed for \tau-NAF recoding as a set of \alpha_u = + * \beta_u + \gamma_u * \tau elements. + * + * @param[out] t - the integer corresponding to \tau. + * @param[out] beta - the first coefficients of the constants. + * @param[out] gama - the second coefficients of the constants. + * @param[in] u - the u curve parameter. + * @param[in] w - the window size in bits. + */ +void bn_rec_tnaf_get(uint8_t *t, int8_t *beta, int8_t *gama, int8_t u, int w); + +/** + * Computes the partial reduction k partmod d = r0 + r1 * t, where + * d = (t^m - 1)/(t - 1). + * + * @param[out] r0 - the first half of the result. + * @param[out] r1 - the second half of the result. + * @param[in] k - the number to reduce. + * @param[in] u - the u curve parameter. + * @param[in] m - the extension degree of the binary field. + */ +void bn_rec_tnaf_mod(bn_t r0, bn_t r1, const bn_t k, int u, int m); + +/** + * Recodes a positive integer in regular fixed-length width-w NAF. If a negative + * integer is given instead, its absolute value is taken. + * + * @param[out] naf - the recoded integer. + * @param[out] len - the number of bytes written. + * @param[in] k - the integer to recode. + * @param[in] n - the length of the recoding. + * @param[in] w - the window size in bits. + * @throw ERR_NO_BUFFER - if the buffer capacity is insufficient. + */ +void bn_rec_reg(int8_t *naf, int *len, const bn_t k, int n, int w); + +/** + * Recodes of a pair of positive integers in Joint Sparse Form. If negative + * integers are given instead, takes their absolute value. + * + * @param[out] jsf - the recoded pair of integers. + * @param[out] len - the number of bytes written. + * @param[in] k - the first integer to recode. + * @param[in] l - the second integer to recode. + * @throw ERR_NO_BUFFER - if the buffer capacity is insufficient. + */ +void bn_rec_jsf(int8_t *jsf, int *len, const bn_t k, const bn_t l); + +/** + * Recodes a positive integer into two parts k0,k1 such that k = k0 + phi(k1), + * where phi is an efficient curve endomorphism. If a negative integer is + * given instead, its absolute value is taken. + * + * @param[out] k0 - the first part of the result. + * @param[out] k1 - the second part of the result. + * @param[in] k - the integer to recode. + * @param[in] n - the group order. + * @param[in] v1 - the set of parameters v1 for the GLV method. + * @param[in] v2 - the set of parameters v2 for the GLV method. + */ +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[]); + +#endif /* !RLC_BN_H */ diff --git a/bls/contrib/relic/include/relic_conf.h.in b/bls/contrib/relic/include/relic_conf.h.in new file mode 100644 index 00000000..b9ef38d8 --- /dev/null +++ b/bls/contrib/relic/include/relic_conf.h.in @@ -0,0 +1,722 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 + * + * Project configuration. + * + * @version $Id: relic_conf.h.in 45 2009-07-04 23:45:48Z dfaranha $ + * @ingroup relic + */ + +#ifndef RLC_CONF_H +#define RLC_CONF_H + +/** Project version. */ +#define RLC_VERSION "@VERSION@" + +/** Debugging support. */ +#cmakedefine DEBUG +/** Profiling support. */ +#cmakedefine PROFL +/** Error handling support. */ +#cmakedefine CHECK +/** Verbose error messages. */ +#cmakedefine VERBS +/** Build with overhead estimation. */ +#cmakedefine OVERH +/** Build documentation. */ +#cmakedefine DOCUM +/** Build only the selected algorithms. */ +#cmakedefine STRIP +/** Build with printing disabled. */ +#cmakedefine QUIET +/** Build with colored output. */ +#cmakedefine COLOR +/** Build with big-endian support. */ +#cmakedefine BIGED +/** Build shared library. */ +#cmakedefine SHLIB +/** Build static library. */ +#cmakedefine STLIB + +/** Number of times each test is ran. */ +#define TESTS @TESTS@ +/** Number of times each benchmark is ran. */ +#define BENCH @BENCH@ + +/** Number of available cores. */ +#define CORES @CORES@ + +/** Atmel AVR ATMega128 8-bit architecture. */ +#define AVR 1 +/** MSP430 16-bit architecture. */ +#define MSP 2 +/** ARM 32-bit architecture. */ +#define ARM 3 +/** Intel x86-compatible 32-bit architecture. */ +#define X86 4 +/** AMD64-compatible 64-bit architecture. */ +#define X64 5 +/** Architecture. */ +#cmakedefine ARCH @ARCH@ + +/** Size of word in this architecture. */ +#define WSIZE @WSIZE@ + +/** Byte boundary to align digit vectors. */ +#define ALIGN @ALIGN@ + +/** Build multiple precision integer module. */ +#cmakedefine WITH_BN +/** Build prime field module. */ +#cmakedefine WITH_FP +/** Build prime field extension module. */ +#cmakedefine WITH_FPX +/** Build binary field module. */ +#cmakedefine WITH_FB +/** Build prime elliptic curve module. */ +#cmakedefine WITH_EP +/** Build prime field extension elliptic curve module. */ +#cmakedefine WITH_EPX +/** Build binary elliptic curve module. */ +#cmakedefine WITH_EB +/** Build elliptic Edwards curve module. */ +#cmakedefine WITH_ED +/** Build elliptic curve cryptography module. */ +#cmakedefine WITH_EC +/** Build pairings over prime curves module. */ +#cmakedefine WITH_PP +/** Build pairing-based cryptography module. */ +#cmakedefine WITH_PC +/** Build block ciphers. */ +#cmakedefine WITH_BC +/** Build hash functions. */ +#cmakedefine WITH_MD +/** Build cryptographic protocols. */ +#cmakedefine WITH_CP + +/** Easy C-only backend. */ +#define EASY 1 +/** GMP backend. */ +#define GMP 2 +/** Arithmetic backend. */ +#define ARITH @ARITH@ + +/** Required precision in bits. */ +#define BN_PRECI @BN_PRECI@ +/** A multiple precision integer can store w words. */ +#define SINGLE 0 +/** A multiple precision integer can store the result of an addition. */ +#define CARRY 1 +/** A multiple precision integer can store the result of a multiplication. */ +#define DOUBLE 2 +/** Effective size of a multiple precision integer. */ +#define BN_MAGNI @BN_MAGNI@ +/** Number of Karatsuba steps. */ +#define BN_KARAT @BN_KARAT@ + +/** Schoolbook multiplication. */ +#define BASIC 1 +/** Comba multiplication. */ +#define COMBA 2 +/** Chosen multiple precision multiplication method. */ +#define BN_MUL @BN_MUL@ + +/** Schoolbook squaring. */ +#define BASIC 1 +/** Comba squaring. */ +#define COMBA 2 +/** Reuse multiplication for squaring. */ +#define MULTP 4 +/** Chosen multiple precision multiplication method. */ +#define BN_SQR @BN_SQR@ + +/** Division modular reduction. */ +#define BASIC 1 +/** Barrett modular reduction. */ +#define BARRT 2 +/** Montgomery modular reduction. */ +#define MONTY 3 +/** Pseudo-Mersenne modular reduction. */ +#define PMERS 4 +/** Chosen multiple precision modular reduction method. */ +#define BN_MOD @BN_MOD@ + +/** Binary modular exponentiation. */ +#define BASIC 1 +/** Sliding window modular exponentiation. */ +#define SLIDE 2 +/** Montgomery powering ladder. */ +#define MONTY 3 +/** Chosen multiple precision modular exponentiation method. */ +#define BN_MXP @BN_MXP@ + +/** Basic Euclidean GCD Algorithm. */ +#define BASIC 1 +/** Lehmer's fast GCD Algorithm. */ +#define LEHME 2 +/** Stein's binary GCD Algorithm. */ +#define STEIN 3 +/** Chosen multiple precision greatest common divisor method. */ +#define BN_GCD @BN_GCD@ + +/** Basic prime generation. */ +#define BASIC 1 +/** Safe prime generation. */ +#define SAFEP 2 +/** Strong prime generation. */ +#define STRON 3 +/** Chosen prime generation algorithm. */ +#define BN_GEN @BN_GEN@ + +/** Multiple precision arithmetic method */ +#define BN_METHD "@BN_METHD@" + +/** Prime field size in bits. */ +#define FP_PRIME @FP_PRIME@ +/** Number of Karatsuba steps. */ +#define FP_KARAT @FP_KARAT@ +/** Prefer Pseudo-Mersenne primes over random primes. */ +#cmakedefine FP_PMERS +/** Use -1 as quadratic non-residue. */ +#cmakedefine FP_QNRES +/** Width of window processing for exponentiation methods. */ +#define FP_WIDTH @FP_WIDTH@ + +/** Schoolbook addition. */ +#define BASIC 1 +/** Integrated modular addtion. */ +#define INTEG 3 +/** Chosen prime field multiplication method. */ +#define FP_ADD @FP_ADD@ + +/** Schoolbook multiplication. */ +#define BASIC 1 +/** Comba multiplication. */ +#define COMBA 2 +/** Integrated modular multiplication. */ +#define INTEG 3 +/** Chosen prime field multiplication method. */ +#define FP_MUL @FP_MUL@ + +/** Schoolbook squaring. */ +#define BASIC 1 +/** Comba squaring. */ +#define COMBA 2 +/** Integrated modular squaring. */ +#define INTEG 3 +/** Reuse multiplication for squaring. */ +#define MULTP 4 +/** Chosen prime field multiplication method. */ +#define FP_SQR @FP_SQR@ + +/** Division-based reduction. */ +#define BASIC 1 +/** Fast reduction modulo special form prime. */ +#define QUICK 2 +/** Montgomery modular reduction. */ +#define MONTY 3 +/** Chosen prime field reduction method. */ +#define FP_RDC @FP_RDC@ + +/** Inversion by Fermat's Little Theorem. */ +#define BASIC 1 +/** Binary inversion. */ +#define BINAR 2 +/** Integrated modular multiplication. */ +#define MONTY 3 +/** Extended Euclidean algorithm. */ +#define EXGCD 4 +/** Constant-time inversion by Bernstein-Yang division steps. */ +#define DIVST 5 +/** Use implementation provided by the lower layer. */ +#define LOWER 8 +/** Chosen prime field inversion method. */ +#define FP_INV @FP_INV@ + +/** Binary modular exponentiation. */ +#define BASIC 1 +/** Sliding window modular exponentiation. */ +#define SLIDE 2 +/** Constant-time Montgomery powering ladder. */ +#define MONTY 3 +/** Chosen multiple precision modular exponentiation method. */ +#define FP_EXP @FP_EXP@ + +/** Prime field arithmetic method */ +#define FP_METHD "@FP_METHD@" + +/** Basic quadratic extension field arithmetic. */ +#define BASIC 1 +/** Integrated extension field arithmetic. */ +#define INTEG 3 +/* Chosen extension field arithmetic method. */ +#define FPX_QDR @FPX_QDR@ + +/** Basic cubic extension field arithmetic. */ +#define BASIC 1 +/** Integrated extension field arithmetic. */ +#define INTEG 3 +/* Chosen extension field arithmetic method. */ +#define FPX_CBC @FPX_CBC@ + +/** Basic quadratic extension field arithmetic. */ +#define BASIC 1 +/** Lazy-reduced extension field arithmetic. */ +#define LAZYR 2 +/* Chosen extension field arithmetic method. */ +#define FPX_RDC @FPX_RDC@ + +/** Prime extension field arithmetic method */ +#define FPX_METHD "@FPX_METHD@" + +/** Irreducible polynomial size in bits. */ +#define FB_POLYN @FB_POLYN@ +/** Number of Karatsuba steps. */ +#define FB_KARAT @FB_KARAT@ +/** Prefer trinomials over pentanomials. */ +#cmakedefine FB_TRINO +/** Prefer square-root friendly polynomials. */ +#cmakedefine FB_SQRTF +/** Precompute multiplication table for sqrt(z). */ +#cmakedefine FB_PRECO +/** Width of window processing for exponentiation methods. */ +#define FB_WIDTH @FB_WIDTH@ + +/** Shift-and-add multiplication. */ +#define BASIC 1 +/** Lopez-Dahab multiplication. */ +#define LODAH 2 +/** Integrated modular multiplication. */ +#define INTEG 3 +/** Chosen binary field multiplication method. */ +#define FB_MUL @FB_MUL@ + +/** Basic squaring. */ +#define BASIC 1 +/** Table-based squaring. */ +#define QUICK 2 +/** Integrated modular squaring. */ +#define INTEG 3 +/** Chosen binary field squaring method. */ +#define FB_SQR @FB_SQR@ + +/** Shift-and-add modular reduction. */ +#define BASIC 1 +/** Fast reduction modulo a trinomial or pentanomial. */ +#define QUICK 2 +/** Chosen binary field modular reduction method. */ +#define FB_RDC @FB_RDC@ + +/** Square root by repeated squaring. */ +#define BASIC 1 +/** Fast square root extraction. */ +#define QUICK 2 +/** Chosen binary field modular reduction method. */ +#define FB_SRT @FB_SRT@ + +/** Trace by repeated squaring. */ +#define BASIC 1 +/** Fast trace computation. */ +#define QUICK 2 +/** Chosen trace computation method. */ +#define FB_TRC @FB_TRC@ + +/** Solve by half-trace computation. */ +#define BASIC 1 +/** Solve with precomputed half-traces. */ +#define QUICK 2 +/** Chosen method to solve a quadratic equation. */ +#define FB_SLV @FB_SLV@ + +/** Inversion by Fermat's Little Theorem. */ +#define BASIC 1 +/** Binary inversion. */ +#define BINAR 2 +/** Almost inverse algorithm. */ +#define ALMOS 3 +/** Extended Euclidean algorithm. */ +#define EXGCD 4 +/** Itoh-Tsuji inversion. */ +#define ITOHT 5 +/** Hardware-friendly inversion by Brunner-Curiger-Hofstetter.*/ +#define BRUCH 6 +/** Constant-time version of almost inverse. */ +#define CTAIA 7 +/** Use implementation provided by the lower layer. */ +#define LOWER 8 +/** Chosen binary field inversion method. */ +#define FB_INV @FB_INV@ + +/** Binary modular exponentiation. */ +#define BASIC 1 +/** Sliding window modular exponentiation. */ +#define SLIDE 2 +/** Constant-time Montgomery powering ladder. */ +#define MONTY 3 +/** Chosen multiple precision modular exponentiation method. */ +#define FB_EXP @FB_EXP@ + +/** Iterated squaring/square-root by consecutive squaring/square-root. */ +#define BASIC 1 +/** Iterated squaring/square-root by table-based method. */ +#define QUICK 2 +/** Chosen method to solve a quadratic equation. */ +#define FB_ITR @FB_ITR@ + +/** Binary field arithmetic method */ +#define FB_METHD "@FB_METHD@" + +/** Support for ordinary curves. */ +#cmakedefine EP_PLAIN +/** Support for supersingular curves. */ +#cmakedefine EP_SUPER +/** Support for prime curves with efficient endormorphisms. */ +#cmakedefine EP_ENDOM +/** Use mixed coordinates. */ +#cmakedefine EP_MIXED +/** Build precomputation table for generator. */ +#cmakedefine EP_PRECO +/** Enable isogeny map for SSWU map-to-curve. */ +#cmakedefine EP_CTMAP +/** Width of precomputation table for fixed point methods. */ +#define EP_DEPTH @EP_DEPTH@ +/** Width of window processing for unknown point methods. */ +#define EP_WIDTH @EP_WIDTH@ + +/** Affine coordinates. */ +#define BASIC 1 +/** Projective coordinates. */ +#define PROJC 2 +/** Chosen prime elliptic curve coordinate method. */ +#define EP_ADD @EP_ADD@ + +/** Binary point multiplication. */ +#define BASIC 1 +/** Sliding window. */ +#define SLIDE 2 +/** Montgomery powering ladder. */ +#define MONTY 3 +/** Left-to-right Width-w NAF. */ +#define LWNAF 4 +/** Left-to-right Width-w NAF. */ +#define LWREG 5 +/** Chosen prime elliptic curve point multiplication method. */ +#define EP_MUL @EP_MUL@ + +/** Binary point multiplication. */ +#define BASIC 1 +/** Single-table comb method. */ +#define COMBS 2 +/** Double-table comb method. */ +#define COMBD 3 +/** Left-to-right Width-w NAF. */ +#define LWNAF 4 +/** Chosen prime elliptic curve point multiplication method. */ +#define EP_FIX @EP_FIX@ + +/** Basic simultaneouns point multiplication. */ +#define BASIC 1 +/** Shamir's trick. */ +#define TRICK 2 +/** Interleaving of w-(T)NAFs. */ +#define INTER 3 +/** Joint sparse form. */ +#define JOINT 4 +/** Chosen prime elliptic curve simulteanous point multiplication method. */ +#define EP_SIM @EP_SIM@ + +/** Prime elliptic curve arithmetic method. */ +#define EP_METHD "@EP_METHD@" + +/** Support for ordinary curves without endormorphisms. */ +#cmakedefine EB_PLAIN +/** Support for Koblitz anomalous binary curves. */ +#cmakedefine EB_KBLTZ +/** Use mixed coordinates. */ +#cmakedefine EB_MIXED +/** Build precomputation table for generator. */ +#cmakedefine EB_PRECO +/** Width of precomputation table for fixed point methods. */ +#define EB_DEPTH @EB_DEPTH@ +/** Width of window processing for unknown point methods. */ +#define EB_WIDTH @EB_WIDTH@ + +/** Binary elliptic curve arithmetic method. */ +#define EB_METHD "@EB_METHD@" + +/** Affine coordinates. */ +#define BASIC 1 +/** López-Dahab Projective coordinates. */ +#define PROJC 2 +/** Chosen binary elliptic curve coordinate method. */ +#define EB_ADD @EB_ADD@ + +/** Binary point multiplication. */ +#define BASIC 1 +/** López-Dahab point multiplication. */ +#define LODAH 2 +/** Halving. */ +#define HALVE 3 +/** Left-to-right width-w (T)NAF. */ +#define LWNAF 4 +/** Right-to-left width-w (T)NAF. */ +#define RWNAF 5 +/** Chosen binary elliptic curve point multiplication method. */ +#define EB_MUL @EB_MUL@ + +/** Binary point multiplication. */ +#define BASIC 1 +/** Single-table comb method. */ +#define COMBS 2 +/** Double-table comb method. */ +#define COMBD 3 +/** Left-to-right Width-w NAF. */ +#define LWNAF 4 +/** Chosen binary elliptic curve point multiplication method. */ +#define EB_FIX @EB_FIX@ + +/** Basic simultaneouns point multiplication. */ +#define BASIC 1 +/** Shamir's trick. */ +#define TRICK 2 +/** Interleaving of w-(T)NAFs. */ +#define INTER 3 +/** Joint sparse form. */ +#define JOINT 4 +/** Chosen binary elliptic curve simulteanous point multiplication method. */ +#define EB_SIM @EB_SIM@ + +/** Build precomputation table for generator. */ +#cmakedefine ED_PRECO +/** Width of precomputation table for fixed point methods. */ +#define ED_DEPTH @ED_DEPTH@ +/** Width of window processing for unknown point methods. */ +#define ED_WIDTH @ED_WIDTH@ + +/** Edwards elliptic curve arithmetic method. */ +#define ED_METHD "@ED_METHD@" + +/** Affine coordinates. */ +#define BASIC 1 +/** Simple projective twisted Edwards coordinates */ +#define PROJC 2 +/** Extended projective twisted Edwards coordinates */ +#define EXTND 3 +/** Chosen binary elliptic curve coordinate method. */ +#define ED_ADD @ED_ADD@ + +/** Binary point multiplication. */ +#define BASIC 1 +/** Sliding window. */ +#define SLIDE 2 +/** Montgomery powering ladder. */ +#define MONTY 3 +/** Left-to-right Width-w NAF. */ +#define LWNAF 4 +/** Left-to-right Width-w NAF. */ +#define LWREG 5 +/** Chosen prime elliptic twisted Edwards curve point multiplication method. */ +#define ED_MUL @ED_MUL@ + +/** Binary point multiplication. */ +#define BASIC 1 +/** Single-table comb method. */ +#define COMBS 2 +/** Double-table comb method. */ +#define COMBD 3 +/** Left-to-right Width-w NAF. */ +#define LWNAF 4 +/** Chosen prime elliptic twisted Edwards curve point multiplication method. */ +#define ED_FIX @ED_FIX@ + +/** Basic simultaneouns point multiplication. */ +#define BASIC 1 +/** Shamir's trick. */ +#define TRICK 2 +/** Interleaving of w-(T)NAFs. */ +#define INTER 3 +/** Joint sparse form. */ +#define JOINT 4 +/** Chosen prime elliptic curve simulteanous point multiplication method. */ +#define ED_SIM @ED_SIM@ + +/** Prime curves. */ +#define PRIME 1 +/** Binary curves. */ +#define CHAR2 2 +/** Edwards curves */ +#define EDDIE 3 +/** Chosen elliptic curve type. */ +#define EC_CUR @EC_CUR@ + +/** Chosen elliptic curve cryptography method. */ +#define EC_METHD "@EC_METHD@" +/** Prefer curves with efficient endomorphisms. */ +#cmakedefine EC_ENDOM + +/** Basic quadratic extension field arithmetic. */ +#define BASIC 1 +/** Lazy-reduced extension field arithmetic. */ +#define LAZYR 2 +/* Chosen extension field arithmetic method. */ +#define PP_EXT @PP_EXT@ + +/** Bilinear pairing method. */ +#define PP_METHD "@PP_METHD@" + +/** Tate pairing. */ +#define TATEP 1 +/** Weil pairing. */ +#define WEILP 2 +/** Optimal ate pairing. */ +#define OATEP 3 +/** Chosen pairing method over prime elliptic curves. */ +#define PP_MAP @PP_MAP@ + +/** SHA-224 hash function. */ +#define SH224 2 +/** SHA-256 hash function. */ +#define SH256 3 +/** SHA-384 hash function. */ +#define SH384 4 +/** SHA-512 hash function. */ +#define SH512 5 +/** BLAKE2s-160 hash function. */ +#define B2S160 6 +/** BLAKE2s-256 hash function. */ +#define B2S256 7 +/** Chosen hash function. */ +#define MD_MAP @MD_MAP@ + +/** Choice of hash function. */ +#define MD_METHD "@MD_METHD@" + +/** RSA without padding. */ +#define BASIC 1 +/** RSA PKCS#1 v1.5 padding. */ +#define PKCS1 2 +/** RSA PKCS#1 v2.1 padding. */ +#define PKCS2 3 +/** Chosen RSA padding method. */ +#define CP_RSAPD @CP_RSAPD@ + +/** Slow RSA decryption/signature. */ +#define BASIC 1 +/** Fast RSA decryption/signature with CRT. */ +#define QUICK 2 +/** Chosen RSA method. */ +#define CP_RSA @CP_RSA@ + +/** Standard ECDSA. */ +#define BASIC 1 +/** ECDSA with fast verification. */ +#define QUICK 2 +/** Chosen ECDSA method. */ +#define CP_ECDSA @CP_ECDSA@ + +/** Automatic memory allocation. */ +#define AUTO 1 +/** Dynamic memory allocation. */ +#define DYNAMIC 2 +/** Stack memory allocation. */ +#define STACK 3 +/** Chosen memory allocation policy. */ +#define ALLOC @ALLOC@ + +/** NIST HASH-DRBG generator. */ +#define HASHD 1 +/** Intel RdRand instruction. */ +#define RDRND 2 +/** Operating system underlying generator. */ +#define UDEV 3 +/** Override library generator with the callback. */ +#define CALL 4 +/** Chosen random generator. */ +#define RAND @RAND@ + +/** Standard C library generator. */ +#define LIBC 1 +/** Intel RdRand instruction. */ +#define RDRND 2 +/** Device node generator. */ +#define UDEV 3 +/** Use Windows' CryptGenRandom. */ +#define WCGR 4 +/** Chosen random generator seeder. */ +#cmakedefine SEED @SEED@ + +/** GNU/Linux operating system. */ +#define LINUX 1 +/** FreeBSD operating system. */ +#define FREEBSD 2 +/** Windows operating system. */ +#define MACOSX 3 +/** Windows operating system. */ +#define WINDOWS 4 +/** Android operating system. */ +#define DROID 5 +/* Arduino platform. */ +#define DUINO 6 +/** Detected operation system. */ +#cmakedefine OPSYS @OPSYS@ + +/** OpenMP multithreading support. */ +#define OPENMP 1 +/** POSIX multithreading support. */ +#define PTHREAD 2 +/** Chosen multithreading API. */ +#cmakedefine MULTI @MULTI@ + +/** Per-process high-resolution timer. */ +#define HREAL 1 +/** Per-process high-resolution timer. */ +#define HPROC 2 +/** Per-thread high-resolution timer. */ +#define HTHRD 3 +/** POSIX-compatible timer. */ +#define POSIX 4 +/** ANSI-compatible timer. */ +#define ANSI 5 +/** Cycle-counting timer. */ +#define CYCLE 6 +/** Chosen timer. */ +#cmakedefine TIMER @TIMER@ + +/** Prefix to identity this build of the library. */ +#cmakedefine LABEL @LABEL@ + +#ifndef ASM + +#include "relic_label.h" + +/** + * Prints the project options selected at build time. + */ +void conf_print(void); + +#endif /* ASM */ + +#endif /* !RLC_CONF_H */ diff --git a/bls/contrib/relic/include/relic_core.h b/bls/contrib/relic/include/relic_core.h new file mode 100644 index 00000000..4a0fa488 --- /dev/null +++ b/bls/contrib/relic/include/relic_core.h @@ -0,0 +1,464 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 . + */ + +/** + * @defgroup relic Core functions + */ + +/** + * @file + * + * Interface of the library core functions. + * + * @ingroup relic + */ + +#ifndef RLC_CORE_H +#define RLC_CORE_H + +#include +#include +#include +#include + +#include "relic_err.h" +#include "relic_bn.h" +#include "relic_eb.h" +#include "relic_epx.h" +#include "relic_ed.h" +#include "relic_conf.h" +#include "relic_bench.h" +#include "relic_rand.h" +#include "relic_label.h" +#include "relic_alloc.h" + +#if defined(MULTI) +#include +#if MULTI == OPENMP +#include +#elif MULTI == PTHREAD +#include +#endif /* OPENMP */ +#endif /* MULTI */ + +/*============================================================================*/ +/* Constant definitions */ +/*============================================================================*/ + +/** + * Indicates that the function executed correctly. + */ +#define RLC_OK 0 + +/** + * Indicates that an error occurred during the function execution. + */ +#define RLC_ERR 1 + +/** + * Indicates that a comparison returned that the first argument was lesser than + * the second argument. + */ +#define RLC_LT -1 + +/** + * Indicates that a comparison returned that the first argument was equal to + * the second argument. + */ +#define RLC_EQ 0 + +/** + * Indicates that a comparison returned that the first argument was greater than + * the second argument. + */ +#define RLC_GT 1 + +/** + * Indicates that two incomparable elements are not equal. + */ +#define RLC_NE 2 + +/** + * Optimization identifer for the case where a coefficient is 0. + */ +#define RLC_ZERO 0 + +/** + * Optimization identifer for the case where a coefficient is 1. + */ +#define RLC_ONE 1 + +/** + * Optimization identifer for the case where a coefficient is 2. + */ +#define RLC_TWO 2 + +/** + * Optimization identifier for the case where a coefficient is -3. + */ +#define RLC_MIN3 3 + +/** + * Optimization identifer for the case where a coefficient is small. + */ +#define RLC_TINY 4 + +/** + * Optimization identifier for the case where the coefficient is arbitrary. + */ +#define RLC_HUGE 5 + +/** + * Maximum number of terms to describe a sparse object. + */ +#define RLC_TERMS 16 + +/*============================================================================*/ +/* Type definitions */ +/*============================================================================*/ + +/** + * Library context. + */ +typedef struct _ctx_t { + /** The value returned by the last call, can be RLC_OK or RLC_ERR. */ + int code; + +#ifdef CHECK + /** The state of the last error caught. */ + sts_t *last; + /** Error state to be used outside try-catch blocks. */ + sts_t error; + /** Error number to be used outside try-catch blocks. */ + err_t number; + /** The error message respective to the last error. */ + char *reason[ERR_MAX]; + /** A flag to indicate if the last error was already caught. */ + int caught; +#endif /* CHECK */ + +#ifdef WITH_FB + /** Identifier of the currently configured binary field. */ + int fb_id; + /** Irreducible binary polynomial. */ + fb_st fb_poly; + /** Non-zero coefficients of a trinomial or pentanomial. */ + int fb_pa, fb_pb, fb_pc; + /** Positions of the non-zero coefficients of trinomials or pentanomials. */ + int fb_na, fb_nb, fb_nc; +#if FB_TRC == QUICK || !defined(STRIP) + /** Powers of z with non-zero traces. */ + int fb_ta, fb_tb, fb_tc; +#endif /* FB_TRC == QUICK */ +#if FB_SLV == QUICK || !defined(STRIP) + /** Table of precomputed half-traces. */ + fb_st fb_half[(RLC_DIG / 8 + 1) * RLC_FB_DIGS][16]; +#endif /* FB_SLV == QUICK */ +#if FB_SRT == QUICK || !defined(STRIP) + /** Square root of z. */ + fb_st fb_srz; +#ifdef FB_PRECO + /** Multiplication table for the z^(1/2). */ + fb_st fb_tab_srz[256]; +#endif /* FB_PRECO */ +#endif /* FB_SRT == QUICK */ +#if FB_INV == ITOHT || !defined(STRIP) + /** Stores an addition chain for (RLC_FB_BITS - 1). */ + int chain[RLC_TERMS + 1]; + /** Stores the length of the addition chain. */ + 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 */ + +#ifdef WITH_EB + /** Identifier of the currently configured binary elliptic curve. */ + int eb_id; + /** The 'a' coefficient of the elliptic curve. */ + fb_st eb_a; + /** The 'b' coefficient of the elliptic curve. */ + fb_st eb_b; + /** Optimization identifier for the 'a' coefficient. */ + int eb_opt_a; + /** Optimization identifier for the 'b' coefficient. */ + int eb_opt_b; + /** The generator of the elliptic curve. */ + eb_st eb_g; + /** The order of the group of points in the elliptic curve. */ + bn_st eb_r; + /** The cofactor of the group order in the elliptic curve. */ + bn_st eb_h; + /** Flag that stores if the binary curve has efficient endomorphisms. */ + int eb_is_kbltz; +#ifdef EB_PRECO + /** Precomputation table for generator multiplication. */ + eb_st eb_pre[RLC_EB_TABLE]; + /** Array of pointers to the precomputation table. */ + eb_st *eb_ptr[RLC_EB_TABLE]; +#endif /* EB_PRECO */ +#endif /* WITH_EB */ + +#ifdef WITH_FP + /** Identifier of the currently configured prime field. */ + int fp_id; + /** Prime modulus. */ + bn_st prime; + /** Parameter for generating prime. */ + bn_st par; + /** Parameter in sparse form. */ + int par_sps[RLC_TERMS + 1]; + /** Length of sparse prime representation. */ + int par_len; +#if FP_RDC == MONTY || !defined(STRIP) + /** Value (R^2 mod p) for converting small integers to Montgomery form. */ + bn_st conv; + /** Value of constant one in Montgomery form. */ + bn_st one; +#endif /* FP_RDC == MONTY */ + /** Prime modulus modulo 8. */ + dig_t mod8; + /** Value derived from the prime used for modular reduction. */ + dig_t u; + /** Quadratic non-residue. */ + int qnr; + /** Cubic non-residue. */ + int cnr; + /** 2-adicity. */ + int ad2; +#if FP_RDC == QUICK || !defined(STRIP) + /** Sparse representation of prime modulus. */ + int sps[RLC_TERMS + 1]; + /** Length of sparse prime representation. */ + int sps_len; +#endif /* FP_RDC == QUICK */ +#endif /* WITH_FP */ + +#ifdef WITH_EP + /** Identifier of the currently configured prime elliptic curve. */ + int ep_id; + /** The 'a' coefficient of the elliptic curve. */ + fp_st ep_a; + /** The 'b' coefficient of the elliptic curve. */ + fp_st ep_b; + /** The generator of the elliptic curve. */ + ep_st ep_g; + /** The order of the group of points in the elliptic curve. */ + bn_st ep_r; + /** The cofactor of the group order in the elliptic curve. */ + bn_st ep_h; + /** The distinguished non-square used by the mapping function */ + fp_st ep_map_u; + /** Precomputed constants for hashing. */ + fp_st ep_map_c[4]; +#ifdef EP_ENDOM +#if EP_MUL == LWNAF || EP_FIX == COMBS || EP_FIX == LWNAF || EP_SIM == INTER || !defined(STRIP) + /** Parameters required by the GLV method. @{ */ + fp_st beta; + bn_st ep_v1[3]; + bn_st ep_v2[3]; + /** @} */ +#endif /* EP_MUL */ +#endif /* EP_ENDOM */ + /** Optimization identifier for the a-coefficient. */ + int ep_opt_a; + /** Optimization identifier for the b-coefficient. */ + int ep_opt_b; + /** Flag that stores if the prime curve has efficient endomorphisms. */ + int ep_is_endom; + /** Flag that stores if the prime curve is supersingular. */ + int ep_is_super; + /** Flag that stores if the prime curve is pairing-friendly. */ + int ep_is_pairf; + /** Flag that indicates whether this curve uses an isogeny for the SSWU mapping. */ + int ep_is_ctmap; +#ifdef EP_PRECO + /** Precomputation table for generator multiplication. */ + ep_st ep_pre[RLC_EP_TABLE]; + /** Array of pointers to the precomputation table. */ + ep_st *ep_ptr[RLC_EP_TABLE]; +#endif /* EP_PRECO */ +#ifdef EP_CTMAP + /** The isogeny map coefficients for the SSWU mapping. */ + iso_st ep_iso; +#endif /* EP_CTMAP */ +#endif /* WITH_EP */ + +#ifdef WITH_EPX + /** The generator of the elliptic curve. */ + ep2_t ep2_g; + /** The 'a' coefficient of the curve. */ + fp2_t ep2_a; + /** The 'b' coefficient of the curve. */ + fp2_t ep2_b; + /** The order of the group of points in the elliptic curve. */ + bn_st ep2_r; + /** The cofactor of the group order in the elliptic curve. */ + bn_st ep2_h; + /** sqrt(-3) in the field for this curve */ + bn_st ep2_s3; + /** (sqrt(-3) - 1) / 2 in the field for this curve */ + bn_st ep2_s32; + /** The distinguished non-square used by the mapping function */ + fp2_t ep2_map_u; + /** The constants needed for hashing. */ + fp2_t ep2_map_c[4]; + /** Optimization identifier for the a-coefficient. */ + int ep2_opt_a; + /** Optimization identifier for the b-coefficient. */ + int ep2_opt_b; + /** Flag that stores if the prime curve is a twist. */ + int ep2_is_twist; + /** Flag that indicates whether this curve uses an isogeny for the SSWU mapping. */ + int ep2_is_ctmap; +#ifdef EP_PRECO + /** Precomputation table for generator multiplication.*/ + ep2_st ep2_pre[RLC_EP_TABLE]; + /** Array of pointers to the precomputation table. */ + ep2_st *ep2_ptr[RLC_EP_TABLE]; +#endif /* EP_PRECO */ +#if ALLOC == STACK + /** In case of stack allocation, we need to get global memory for the table. */ + fp2_st _ep2_pre[3 * RLC_EP_TABLE]; + /** In case of stack allocation, storage for the EPX constants. */ + ep2_st _ep2_g; + /* 3 for ep2_g, plus ep2_a, ep2_b, ep2_map_u, and ep2_map_c[4] */ + fp2_st _ep2_storage[10]; +#endif /* ALLOC == STACK */ +#ifdef EP_CTMAP + /** The isogeny map coefficients for the SSWU mapping. */ + iso2_st ep2_iso; +#endif /* EP_CTMAP */ +#endif /* WITH_EPX */ + +#ifdef WITH_ED + /** Identifier of the currently configured Edwards elliptic curve. */ + int ed_id; + /** The 'a' coefficient of the Edwards elliptic curve. */ + fp_st ed_a; + /** The 'd' coefficient of the Edwards elliptic curve. */ + fp_st ed_d; + /** The square root of -1 needed for hashing. */ + fp_st srm1; + /** The generator of the Edwards elliptic curve. */ + ed_st ed_g; + /** The order of the group of points in the Edwards elliptic curve. */ + bn_st ed_r; + /** The cofactor of the Edwards elliptic curve. */ + bn_st ed_h; + +#ifdef ED_PRECO + /** Precomputation table for generator multiplication. */ + ed_st ed_pre[RLC_ED_TABLE]; + /** Array of pointers to the precomputation table. */ + ed_st *ed_ptr[RLC_ED_TABLE]; +#endif /* ED_PRECO */ +#endif + +#if defined(WITH_FPX) || defined(WITH_PP) + /** Integer part of the quadratic non-residue. */ + int qnr2; + /** Constants for computing Frobenius maps in higher extensions. @{ */ + fp2_st fp2_p1[5]; + fp2_st fp2_p2[3]; + /** @} */ + /** Constants for computing Frobenius maps in higher extensions. @{ */ + int frb3[3]; + fp_st fp3_p0[2]; + fp_st fp3_p1[5]; + fp_st fp3_p2[2]; + /** @} */ +#endif /* WITH_PP */ + +#if BENCH > 0 + /** Stores the time measured before the execution of the benchmark. */ + bench_t before; + /** Stores the time measured after the execution of the benchmark. */ + bench_t after; + /** Stores the sum of timings for the current benchmark. */ + long long total; +#ifdef OVERH + /** Benchmarking overhead to be measured and subtracted from benchmarks. */ + long long over; +#endif +#endif + +#if RAND != CALL + /** Internal state of the PRNG. */ + uint8_t rand[RAND_SIZE]; +#else + void (*rand_call)(uint8_t *, int, void *); + void *rand_args; +#endif + /** Flag to indicate if PRNG is seed. */ + int seeded; + /** Counter to keep track of number of calls since last seeding. */ + int counter; +} ctx_t; + +/*============================================================================*/ +/* Function prototypes */ +/*============================================================================*/ + +/** + * Initializes the library. + * + * @return RLC_OK if no error occurs, RLC_ERR otherwise. + */ +int core_init(void); + +/** + * Finalizes the library. + * + * @return RLC_OK if no error occurs, RLC_ERR otherwise. + */ +int core_clean(void); + +/** + * Returns a pointer to the current library context. + * + * @return a pointer to the library context. + */ +ctx_t *core_get(void); + +/** + * Switched the library context to a new context. + * + * @param[in] ctx - the new library context. + */ +void core_set(ctx_t *ctx); + +#if MULTI != RELIC_NONE +/** + * Set an initializer function which is called when the context + * is uninitialized. This function is called for every thread. + * + * @param[in] init function to call when the current context is not initialized + * @param[in] init_ptr a pointer which is passed to the initialized + */ +void core_set_thread_initializer(void(*init)(void *init_ptr), void* init_ptr); +#endif + +#endif /* !RLC_CORE_H */ diff --git a/bls/contrib/relic/include/relic_cp.h b/bls/contrib/relic/include/relic_cp.h new file mode 100644 index 00000000..5cb3aad3 --- /dev/null +++ b/bls/contrib/relic/include/relic_cp.h @@ -0,0 +1,1751 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 . + */ + +/** + * @defgroup cp Cryptographic protocols + */ + +/** + * @file + * + * Interface of cryptographic protocols. + * + * @ingroup bn + */ + +#ifndef RLC_CP_H +#define RLC_CP_H + +#include "relic_conf.h" +#include "relic_types.h" +#include "relic_bn.h" +#include "relic_ec.h" +#include "relic_pc.h" + +/*============================================================================*/ +/* Type definitions. */ +/*============================================================================*/ + +/** + * Represents an RSA key pair. + */ +typedef struct _rsa_t { + /** The modulus n = pq. */ + bn_t n; + /** The public exponent. */ + bn_t e; + /** The private exponent. */ + bn_t d; + /** The first prime p. */ + bn_t p; + /** The second prime q. */ + bn_t q; + /** The inverse of e modulo (p-1). */ + bn_t dp; + /** The inverse of e modulo (q-1). */ + bn_t dq; + /** The inverse of q modulo p. */ + bn_t qi; +} relic_rsa_st; + +/** + * Pointer to an RSA key pair. + */ +#if ALLOC == AUTO +typedef relic_rsa_st rsa_t[1]; +#else +typedef relic_rsa_st *rsa_t; +#endif + +/** + * Represents a Rabin key pair. + */ +typedef struct _rabin_t { + /** The modulus n = pq. */ + bn_t n; + /** The first prime p. */ + bn_t p; + /** The second prime q. */ + bn_t q; + /** The cofactor of the first prime. */ + bn_t dp; + /** The cofactor of the second prime. */ + bn_t dq; +} rabin_st; + +/** + * Pointer to a Rabin key pair. + */ +#if ALLOC == AUTO +typedef rabin_st rabin_t[1]; +#else +typedef rabin_st *rabin_t; +#endif + +/** + * Represents a Benaloh's Dense Probabilistic Encryption key pair. + */ +typedef struct _bdpe_t { + /** The modulus n = pq. */ + bn_t n; + /** The first prime p. */ + bn_t p; + /** The second prime q. */ + bn_t q; + /** The random element in {0, ..., n - 1}. */ + bn_t y; + /** The divisor of (p-1) such that gcd(t, (p-1)/t) = gcd(t, q-1) = 1. */ + dig_t t; +} bdpe_st; + +/** + * Pointer to a Benaloh's Dense Probabilistic Encryption key pair. + */ +#if ALLOC == AUTO +typedef bdpe_st bdpe_t[1]; +#else +typedef bdpe_st *bdpe_t; +#endif + +/** + * Represents a SOKAKA key pair. + */ +typedef struct _sokaka { + /** The private key in G_1. */ + g1_t s1; + /** The private key in G_2. */ + g2_t s2; +} sokaka_st; + +/** + * Pointer to SOKAKA key pair. + */ +#if ALLOC == AUTO +typedef sokaka_st sokaka_t[1]; +#else +typedef sokaka_st *sokaka_t; +#endif + +/** + * Represents a Boneh-Goh-Nissim cryptosystem key pair. + */ +typedef struct _bgn_t { + /** The first exponent. */ + bn_t x; + /** The second exponent. */ + bn_t y; + /** The third exponent. */ + bn_t z; + /* The first element from the first group. */ + g1_t gx; + /* The second element from the first group. */ + g1_t gy; + /* The thirs element from the first group. */ + g1_t gz; + /* The first element from the second group. */ + g2_t hx; + /* The second element from the second group. */ + g2_t hy; + /* The third element from the second group. */ + g2_t hz; +} bgn_st; + +/** + * Pointer to a a Boneh-Goh-Nissim cryptosystem key pair. + */ +#if ALLOC == AUTO +typedef bgn_st bgn_t[1]; +#else +typedef bgn_st *bgn_t; +#endif + +/*============================================================================*/ +/* Macro definitions */ +/*============================================================================*/ + +/** + * Initializes an RSA key pair with a null value. + * + * @param[out] A - the key pair to initialize. + */ +#if ALLOC == AUTO +#define rsa_null(A) /* empty */ +#else +#define rsa_null(A) A = NULL; +#endif + +/** + * Calls a function to allocate and initialize an RSA key pair. + * + * @param[out] A - the new key pair. + */ +#if ALLOC == DYNAMIC +#define rsa_new(A) \ + A = (rsa_t)calloc(1, sizeof(relic_rsa_st)); \ + if (A == NULL) { \ + THROW(ERR_NO_MEMORY); \ + } \ + bn_null((A)->e); \ + bn_null((A)->n); \ + bn_null((A)->d); \ + bn_null((A)->dp); \ + bn_null((A)->dq); \ + bn_null((A)->p); \ + bn_null((A)->q); \ + bn_null((A)->qi); \ + bn_new((A)->e); \ + bn_new((A)->n); \ + bn_new((A)->d); \ + bn_new((A)->dp); \ + bn_new((A)->dq); \ + bn_new((A)->p); \ + bn_new((A)->q); \ + bn_new((A)->qi); \ + +#elif ALLOC == AUTO +#define rsa_new(A) \ + bn_new((A)->e); \ + bn_new((A)->n); \ + bn_new((A)->d); \ + bn_new((A)->dp); \ + bn_new((A)->dq); \ + bn_new((A)->p); \ + bn_new((A)->q); \ + bn_new((A)->qi); \ + +#elif ALLOC == STACK +#define rsa_new(A) \ + A = (rsa_t)alloca(sizeof(relic_rsa_st)); \ + bn_new((A)->e); \ + bn_new((A)->n); \ + bn_new((A)->d); \ + bn_new((A)->dp); \ + bn_new((A)->dq); \ + bn_new((A)->p); \ + bn_new((A)->q); \ + bn_new((A)->qi); \ + +#endif + +/** + * Calls a function to clean and free an RSA key pair. + * + * @param[out] A - the key pair to clean and free. + */ +#if ALLOC == DYNAMIC +#define rsa_free(A) \ + if (A != NULL) { \ + bn_free((A)->e); \ + bn_free((A)->n); \ + bn_free((A)->d); \ + bn_free((A)->dp); \ + bn_free((A)->dq); \ + bn_free((A)->p); \ + bn_free((A)->q); \ + bn_free((A)->qi); \ + free(A); \ + A = NULL; \ + } + +#elif ALLOC == AUTO +#define rsa_free(A) /* empty */ + +#elif ALLOC == STACK +#define rsa_free(A) \ + bn_free((A)->e); \ + bn_free((A)->n); \ + bn_free((A)->d); \ + bn_free((A)->dp); \ + bn_free((A)->dq); \ + bn_free((A)->p); \ + bn_free((A)->q); \ + bn_free((A)->qi); \ + A = NULL; \ + +#endif + +/** + * Initializes a Rabin key pair with a null value. + * + * @param[out] A - the key pair to initialize. + */ +#if ALLOC == AUTO +#define rabin_null(A) /* empty */ +#else +#define rabin_null(A) A = NULL; +#endif + +/** + * Calls a function to allocate and initialize a Rabin key pair. + * + * @param[out] A - the new key pair. + */ +#if ALLOC == DYNAMIC +#define rabin_new(A) \ + A = (rabin_t)calloc(1, sizeof(rabin_st)); \ + if (A == NULL) { \ + THROW(ERR_NO_MEMORY); \ + } \ + bn_new((A)->n); \ + bn_new((A)->dp); \ + bn_new((A)->dq); \ + bn_new((A)->p); \ + bn_new((A)->q); \ + +#elif ALLOC == AUTO +#define rabin_new(A) \ + bn_new((A)->n); \ + bn_new((A)->dp); \ + bn_new((A)->dq); \ + bn_new((A)->p); \ + bn_new((A)->q); \ + +#elif ALLOC == STACK +#define rabin_new(A) \ + A = (rabin_t)alloca(sizeof(rabin_st)); \ + bn_new((A)->n); \ + bn_new((A)->dp); \ + bn_new((A)->dq); \ + bn_new((A)->p); \ + bn_new((A)->q); \ + +#endif + +/** + * Calls a function to clean and free a Rabin key pair. + * + * @param[out] A - the key pair to clean and free. + */ +#if ALLOC == DYNAMIC +#define rabin_free(A) \ + if (A != NULL) { \ + bn_free((A)->n); \ + bn_free((A)->dp); \ + bn_free((A)->dq); \ + bn_free((A)->p); \ + bn_free((A)->q); \ + free(A); \ + A = NULL; \ + } + +#elif ALLOC == AUTO +#define rabin_free(A) /* empty */ + +#elif ALLOC == STACK +#define rabin_free(A) \ + bn_free((A)->n); \ + bn_free((A)->dp); \ + bn_free((A)->dq); \ + bn_free((A)->p); \ + bn_free((A)->q); \ + A = NULL; \ + +#endif + +/** + * 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 + +/** + * Calls a function to allocate and initialize a Benaloh's key pair. + * + * @param[out] A - the new key pair. + */ +#if ALLOC == DYNAMIC +#define bdpe_new(A) \ + A = (bdpe_t)calloc(1, sizeof(bdpe_st)); \ + if (A == NULL) { \ + THROW(ERR_NO_MEMORY); \ + } \ + bn_new((A)->n); \ + bn_new((A)->y); \ + bn_new((A)->p); \ + bn_new((A)->q); \ + (A)->t = 0; \ + +#elif ALLOC == AUTO +#define bdpe_new(A) \ + bn_new((A)->n); \ + bn_new((A)->y); \ + bn_new((A)->p); \ + bn_new((A)->q); \ + (A)->t = 0; \ + +#elif ALLOC == STACK +#define bdpe_new(A) \ + A = (bdpe_t)alloca(sizeof(bdpe_st)); \ + bn_new((A)->n); \ + bn_new((A)->y); \ + bn_new((A)->p); \ + bn_new((A)->q); \ + +#endif + +/** + * Calls a function to clean and free a Benaloh's key pair. + * + * @param[out] A - the key pair to clean and free. + */ +#if ALLOC == DYNAMIC +#define bdpe_free(A) \ + if (A != NULL) { \ + bn_free((A)->n); \ + bn_free((A)->y); \ + bn_free((A)->p); \ + bn_free((A)->q); \ + (A)->t = 0; \ + free(A); \ + A = NULL; \ + } + +#elif ALLOC == AUTO +#define bdpe_free(A) /* empty */ + +#elif ALLOC == STACK +#define bdpe_free(A) \ + bn_free((A)->n); \ + bn_free((A)->y); \ + bn_free((A)->p); \ + bn_free((A)->q); \ + (A)->t = 0; \ + A = NULL; \ + +#endif + +/** + * Initializes a SOKAKA key pair with a null value. + * + * @param[out] A - the key pair to initialize. + */ +#if ALLOC == AUTO +#define sokaka_null(A) /* empty */ +#else +#define sokaka_null(A) A = NULL; +#endif + +/** + * Calls a function to allocate and initialize a SOKAKA key pair. + * + * @param[out] A - the new key pair. + */ +#if ALLOC == DYNAMIC +#define sokaka_new(A) \ + A = (sokaka_t)calloc(1, sizeof(sokaka_st)); \ + if (A == NULL) { \ + THROW(ERR_NO_MEMORY); \ + } \ + g1_new((A)->s1); \ + g2_new((A)->s2); \ + +#elif ALLOC == AUTO +#define sokaka_new(A) /* empty */ + +#elif ALLOC == STACK +#define sokaka_new(A) \ + A = (sokaka_t)alloca(sizeof(sokaka_st)); \ + g1_new((A)->s1); \ + g2_new((A)->s2); \ + +#endif + +/** + * Calls a function to clean and free a SOKAKA key pair. + * + * @param[out] A - the key pair to clean and free. + */ +#if ALLOC == DYNAMIC +#define sokaka_free(A) \ + if (A != NULL) { \ + g1_free((A)->s1); \ + g2_free((A)->s2); \ + free(A); \ + A = NULL; \ + } + +#elif ALLOC == AUTO +#define sokaka_free(A) /* empty */ + +#elif ALLOC == STACK +#define sokaka_free(A) \ + g1_free((A)->s1); \ + g2_free((A)->s2); \ + A = NULL; \ + +#endif + +/** + * Initializes a BGN key pair with a null value. + * + * @param[out] A - the key pair to initialize. + */ +#if ALLOC == AUTO +#define bgn_null(A) /* empty */ +#else +#define bgn_null(A) A = NULL; +#endif + +/** + * Calls a function to allocate and initialize a BGN key pair. + * + * @param[out] A - the new key pair. + */ +#if ALLOC == DYNAMIC +#define bgn_new(A) \ + A = (bgn_t)calloc(1, sizeof(bgn_st)); \ + if (A == NULL) { \ + THROW(ERR_NO_MEMORY); \ + } \ + bn_new((A)->x); \ + bn_new((A)->y); \ + bn_new((A)->z); \ + g1_new((A)->gx); \ + g1_new((A)->gy); \ + g1_new((A)->gz); \ + g2_new((A)->hx); \ + g2_new((A)->hy); \ + g2_new((A)->hz); \ + +#elif ALLOC == AUTO +#define bgn_new(A) /* empty */ + +#elif ALLOC == STACK +#define bgn_new(A) \ + A = (bgn_t)alloca(sizeof(bgn_st)); \ + bn_new((A)->x); \ + bn_new((A)->y); \ + bn_new((A)->z); \ + g1_new((A)->gx); \ + g1_new((A)->gy); \ + g1_new((A)->gz); \ + g2_new((A)->hx); \ + g2_new((A)->hy); \ + g2_new((A)->hz); \ + +#endif + +/** + * Calls a function to clean and free a BGN key pair. + * + * @param[out] A - the key pair to clean and free. + */ +#if ALLOC == DYNAMIC +#define bgn_free(A) \ + if (A != NULL) { \ + bn_free((A)->x); \ + bn_free((A)->y); \ + bn_free((A)->z); \ + g1_free((A)->gx); \ + g1_free((A)->gy); \ + g1_free((A)->gz); \ + g2_free((A)->hx); \ + g2_free((A)->hy); \ + g2_free((A)->hz); \ + free(A); \ + A = NULL; \ + } + +#elif ALLOC == AUTO +#define bgn_free(A) /* empty */ + +#elif ALLOC == STACK +#define bgn_free(A) \ + bn_free((A)->x); \ + bn_free((A)->y); \ + bn_free((A)->z); \ + g1_free((A)->gx); \ + g1_free((A)->gy); \ + g1_free((A)->gz); \ + g2_free((A)->hx); \ + g2_free((A)->hy); \ + g2_free((A)->hz); \ + A = NULL; \ + +#endif + +/** + * Generates a new RSA key pair. + * + * @param[out] PB - the public key. + * @param[out] PV - the private key. + * @param[in] B - the key length in bits. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +#if CP_RSA == BASIC +#define cp_rsa_gen(PB, PV, B) cp_rsa_gen_basic(PB, PV, B) +#elif CP_RSA == QUICK +#define cp_rsa_gen(PB, PV, B) cp_rsa_gen_quick(PB, PV, B) +#endif + +/** + * Decrypts using RSA. + * + * @param[out] O - the output buffer. + * @param[out] OL - the number of bytes written in the output buffer. + * @param[in] I - the input buffer. + * @param[in] IL - the number of bytes to encrypt. + * @param[in] K - the private key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +#if CP_RSA == BASIC +#define cp_rsa_dec(O, OL, I, IL, K) cp_rsa_dec_basic(O, OL, I, IL, K) +#elif CP_RSA == QUICK +#define cp_rsa_dec(O, OL, I, IL, K) cp_rsa_dec_quick(O, OL, I, IL, K) +#endif + +/** + * Signs a message using the RSA cryptosystem. + * + * @param[out] O - the output buffer. + * @param[out] OL - the number of bytes written in the output buffer. + * @param[in] I - the input buffer. + * @param[in] IL - the number of bytes to sign. + * @param[in] H - the flag to indicate the message format. + * @param[in] K - the private key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +#if CP_RSA == BASIC +#define cp_rsa_sig(O, OL, I, IL, H, K) cp_rsa_sig_basic(O, OL, I, IL, H, K) +#elif CP_RSA == QUICK +#define cp_rsa_sig(O, OL, I, IL, H, K) cp_rsa_sig_quick(O, OL, I, IL, H, K) +#endif + +/*============================================================================*/ +/* Function prototypes */ +/*============================================================================*/ + +/** + * Generates a key pair for the basic RSA algorithm. + * + * @param[out] pub - the public key. + * @param[out] prv - the private key. + * @param[in] bits - the key length in bits. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_rsa_gen_basic(rsa_t pub, rsa_t prv, int bits); + +/** + * Generates a key pair for fast RSA operations with the CRT optimization. + * + * @param[out] pub - the public key. + * @param[out] prv - the private key. + * @param[in] bits - the key length in bits. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_rsa_gen_quick(rsa_t pub, rsa_t prv, int bits); + +/** + * Encrypts using the RSA cryptosystem. + * + * @param[out] out - the output buffer. + * @param[in, out] out_len - the buffer capacity and number of bytes written. + * @param[in] in - the input buffer. + * @param[in] in_len - the number of bytes to encrypt. + * @param[in] pub - the public key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_rsa_enc(uint8_t *out, int *out_len, uint8_t *in, int in_len, rsa_t pub); + +/** + * Decrypts using the basic RSA decryption method. + * + * @param[out] out - the output buffer. + * @param[in, out] out_len - the buffer capacity and number of bytes written. + * @param[in] in - the input buffer. + * @param[in] in_len - the number of bytes to decrypt. + * @param[in] prv - the private key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_rsa_dec_basic(uint8_t *out, int *out_len, uint8_t *in, int in_len, + rsa_t prv); + +/** + * Decrypts using the fast RSA decryption with CRT optimization. + * + * @param[out] out - the output buffer. + * @param[in, out] out_len - the buffer capacity and number of bytes written. + * @param[in] in - the input buffer. + * @param[in] in_len - the number of bytes to decrypt. + * @param[in] prv - the private key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_rsa_dec_quick(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 + * the message being signed is already a hash value. + * + * @param[out] sig - the signature + * @param[out] sig_len - the number of bytes written in the signature. + * @param[in] msg - the message to sign. + * @param[in] msg_len - the number of bytes to sign. + * @param[in] hash - the flag to indicate the message format. + * @param[in] prv - the private key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_rsa_sig_basic(uint8_t *sig, int *sig_len, uint8_t *msg, int msg_len, + int hash, rsa_t prv); + +/** + * Signs using the fast RSA signature algorithm with CRT optimization. The flag + * must be non-zero if the message being signed is already a hash value. + * + * @param[out] sig - the signature + * @param[out] sig_len - the number of bytes written in the signature. + * @param[in] msg - the message to sign. + * @param[in] msg_len - the number of bytes to sign. + * @param[in] hash - the flag to indicate the message format. + * @param[in] prv - the private key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_rsa_sig_quick(uint8_t *sig, int *sig_len, uint8_t *msg, int msg_len, + int hash, rsa_t prv); + +/** + * Verifies an RSA signature. The flag must be non-zero if the message being + * signed is already a hash value. + * + * @param[in] sig - the signature to verify. + * @param[in] sig_len - the signature length in bytes. + * @param[in] msg - the signed message. + * @param[in] msg_len - the message length in bytes. + * @param[in] hash - the flag to indicate the message format. + * @param[in] pub - the public key. + * @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); + +/** + * Generates a key pair for the Rabin cryptosystem. + * + * @param[out] pub - the public key. + * @param[out] prv - the private key, + * @param[in] bits - the key length in bits. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_rabin_gen(rabin_t pub, rabin_t prv, int bits); + +/** + * Encrypts using the Rabin cryptosystem. + * + * @param[out] out - the output buffer. + * @param[in, out] out_len - the buffer capacity and number of bytes written. + * @param[in] in - the input buffer. + * @param[in] in_len - the number of bytes to encrypt. + * @param[in] pub - the public key. + * @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); + +/** + * Decrypts using the Rabin cryptosystem. + * + * @param[out] out - the output buffer. + * @param[in, out] out_len - the buffer capacity and number of bytes written. + * @param[in] in - the input buffer. + * @param[in] in_len - the number of bytes to decrypt. + * @param[in] prv - the private key. + * @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); + +/** + * Generates a key pair for Benaloh's Dense Probabilistic Encryption. + * + * @param[out] pub - the public key. + * @param[out] prv - the private key. + * @param[in] block - the block size. + * @param[in] bits - the key length in bits. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_bdpe_gen(bdpe_t pub, bdpe_t prv, dig_t block, int bits); + +/** + * Encrypts using Benaloh's cryptosystem. + * + * @param[out] out - the output buffer. + * @param[in, out] out_len - the buffer capacity and number of bytes written. + * @param[in] in - the plaintext as a small integer. + * @param[in] pub - the public key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_bdpe_enc(uint8_t *out, int *out_len, dig_t in, bdpe_t pub); + +/** + * Decrypts using Benaloh's cryptosystem. + * + * @param[out] out - the decrypted small integer. + * @param[in] in - the input buffer. + * @param[in] in_len - the number of bytes to encrypt. + * @param[in] prv - the private key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_bdpe_dec(dig_t *out, uint8_t *in, int in_len, bdpe_t prv); + +/** + * Generates a key pair for Paillier's Homomorphic Probabilistic Encryption. + * + * @param[out] n - the public key. + * @param[out] l - the private key. + * @param[in] bits - the key length in bits. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_phpe_gen(bn_t n, bn_t l, int bits); + +/** + * Encrypts using the Paillier cryptosystem. + * + * @param[out] out - the output buffer. + * @param[in, out] out_len - the buffer capacity and number of bytes written. + * @param[in] in - the input buffer. + * @param[in] in_len - the number of bytes to encrypt. + * @param[in] n - the public key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_phpe_enc(uint8_t *out, int *out_len, uint8_t *in, int in_len, bn_t n); + +/** + * Decrypts using the Paillier cryptosystem. Since this system is homomorphic, + * no padding can be applied and the user is responsible for specifying the + * resulting plaintext size. + * + * @param[out] out - the output buffer. + * @param[out] out_len - the number of bytes to write in the output buffer. + * @param[in] in_len - the number of bytes to decrypt. + * @param[in] n - the public key. + * @param[in] l - the private key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_phpe_dec(uint8_t *out, int out_len, uint8_t *in, int in_len, bn_t n, + bn_t l); + +/** + * Generates an ECDH key pair. + * + * @param[out] d - the private key. + * @param[in] q - the public key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_ecdh_gen(bn_t d, ec_t q); + +/** + * Derives a shared secret using ECDH. + * + * @param[out] key - the shared key. + * @param[int] key_len - the intended shared key length in bytes. + * @param[in] d - the private key. + * @param[in] q - the point received from the other party. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_ecdh_key(uint8_t *key, int key_len, bn_t d, ec_t q); + +/** + * Generate an ECMQV key pair. + * + * Should also be used to generate the ephemeral key pair. + * + * @param[out] d - the private key. + * @param[out] q - the public key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_ecmqv_gen(bn_t d, ec_t q); + +/** + * Derives a shared secret using ECMQV. + * + * @param[out] key - the shared key. + * @param[int] key_len - the intended shared key length in bytes. + * @param[in] d1 - the private key. + * @param[in] d2 - the ephemeral private key. + * @param[in] q2u - the ephemeral public key. + * @param[in] q1v - the point received from the other party. + * @param[in] q2v - the ephemeral point received from the party. + * @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); + +/** + * Generates an ECIES key pair. + * + * @param[out] d - the private key. + * @param[in] q - the public key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_ecies_gen(bn_t d, ec_t q); + +/** + * Encrypts using the ECIES cryptosystem. + * + * @param[out] r - the resulting elliptic curve point. + * @param[out] out - the output buffer. + * @param[in, out] out_len - the buffer capacity and number of bytes written. + * @param[in] in - the input buffer. + * @param[in] in_len - the number of bytes to encrypt. + * @param[in] iv - the block cipher initialization vector. + * @param[in] q - the public key. + * @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); + +/** + * Decrypts using the ECIES cryptosystem. + * + * @param[out] out - the output buffer. + * @param[in, out] out_len - the buffer capacity and number of bytes written. + * @param[in] in - the input buffer. + * @param[in] in_len - the number of bytes to encrypt. + * @param[in] iv - the block cipher initialization vector. + * @param[in] d - the private key. + * @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); + +/** + * Generates an ECDSA key pair. + * + * @param[out] d - the private key. + * @param[in] q - the public key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_ecdsa_gen(bn_t d, ec_t q); + +/** + * Signs a message using ECDSA. + * + * @param[out] r - the first component of the signature. + * @param[out] s - the second component of the signature. + * @param[in] msg - the message to sign. + * @param[in] len - the message length in bytes. + * @param[in] hash - the flag to indicate the message format. + * @param[in] d - the private key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_ecdsa_sig(bn_t r, bn_t s, uint8_t *msg, int len, int hash, bn_t d); + +/** + * Verifies a message signed with ECDSA using the basic method. + * + * @param[out] r - the first component of the signature. + * @param[out] s - the second component of the signature. + * @param[in] msg - the message to sign. + * @param[in] len - the message length in bytes. + * @param[in] hash - the flag to indicate the message format. + * @param[in] q - the public key. + * @return a boolean value indicating if the signature is valid. + */ +int cp_ecdsa_ver(bn_t r, bn_t s, uint8_t *msg, int len, int hash, ec_t q); + +/** + * Generates an Elliptic Curve Schnorr Signature key pair. + * + * @param[out] d - the private key. + * @param[in] q - the public key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_ecss_gen(bn_t d, ec_t q); + +/** + * Signs a message using the Elliptic Curve Schnorr Signature. + * + * @param[out] r - the first component of the signature. + * @param[out] s - the second component of the signature. + * @param[in] msg - the message to sign. + * @param[in] len - the message length in bytes. + * @param[in] d - the private key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_ecss_sig(bn_t e, bn_t s, uint8_t *msg, int len, bn_t d); + +/** + * Verifies a message signed with the Elliptic Curve Schnorr Signature using the + * basic method. + * + * @param[out] r - the first component of the signature. + * @param[out] s - the second component of the signature. + * @param[in] msg - the message to sign. + * @param[in] len - the message length in bytes. + * @param[in] q - the public key. + * @return a boolean value indicating if the signature is valid. + */ +int cp_ecss_ver(bn_t e, bn_t s, uint8_t *msg, int len, ec_t q); + +/** + * Generates a master key for the SOKAKA identity-based non-interactive + * authenticated key agreement protocol. + * + * @param[out] master - the master key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_sokaka_gen(bn_t master); + +/** + * Generates a private key for the SOKAKA protocol. + * + * @param[out] k - the private key. + * @param[in] id - the identity. + * @param[in] len - the length of identity in bytes. + * @param[in] master - the master key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_sokaka_gen_prv(sokaka_t k, char *id, int len, bn_t master); + +/** + * Computes a shared key between two entities. + * + * @param[out] key - the shared key. + * @param[int] key_len - the intended shared key length in bytes. + * @param[in] id1 - the first identity. + * @param[in] len1 - the length of the first identity in bytes. + * @param[in] k - the private key of the first identity. + * @param[in] id2 - the second identity. + * @param[in] len2 - the length of the second identity in bytes. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_sokaka_key(uint8_t *key, unsigned int key_len, char *id1, int len1, + sokaka_t k, char *id2, int len2); + +/** + * Generates a key pair for the Boneh-Go-Nissim (BGN) cryptosystem. + * + * @param[out] pub - the public key. + * @param[out] prv - the private key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_bgn_gen(bgn_t pub, bgn_t prv); + +/** + * Encrypts in G_1 using the BGN cryptosystem. + * + * @param[out] out - the ciphertext. + * @param[in] in - the plaintext as a small integer. + * @param[in] pub - the public key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_bgn_enc1(g1_t out[2], dig_t in, bgn_t pub); + +/** + * Decrypts in G_1 using the BGN cryptosystem. + * + * @param[out] out - the decrypted small integer. + * @param[in] in - the ciphertext. + * @param[in] prv - the private key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_bgn_dec1(dig_t *out, g1_t in[2], bgn_t prv); + +/** + * Encrypts in G_2 using the BGN cryptosystem. + * + * @param[out] c - the ciphertext. + * @param[in] m - the plaintext as a small integer. + * @param[in] pub - the public key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_bgn_enc2(g2_t out[2], dig_t in, bgn_t pub); + +/** + * Decrypts in G_2 using the BGN cryptosystem. + * + * @param[out] out - the decrypted small integer. + * @param[in] c - the ciphertext. + * @param[in] prv - the private key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_bgn_dec2(dig_t *out, g2_t in[2], bgn_t prv); + +/** + * Adds homomorphically two BGN ciphertexts in G_T. + * + * @param[out] e - the resulting ciphertext. + * @param[in] c - the first ciphertext to add. + * @param[in] d - the second ciphertext to add. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_bgn_add(gt_t e[4], gt_t c[4], gt_t d[4]); + +/** + * Multiplies homomorphically two BGN ciphertexts in G_T. + * + * @param[out] e - the resulting ciphertext. + * @param[in] c - the first ciphertext to add. + * @param[in] d - the second ciphertext to add. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_bgn_mul(gt_t e[4], g1_t c[2], g2_t d[2]); + +/** + * Decrypts in G_T using the BGN cryptosystem. + * + * @param[out] out - the decrypted small integer. + * @param[in] c - the ciphertext. + * @param[in] prv - the private key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_bgn_dec(dig_t *out, gt_t in[4], bgn_t prv); + +/** + * Generates a master key for a Private Key Generator (PKG) in the + * Boneh-Franklin Identity-Based Encryption (BF-IBE). + * + * @param[out] master - the master key. + * @param[out] pub - the public key of the private key generator. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_ibe_gen(bn_t master, g1_t pub); + +/** + * Generates a private key for a user in the BF-IBE protocol. + * + * @param[out] prv - the private key. + * @param[in] id - the identity. + * @param[in] len - the length of identity in bytes. + * @param[in] s - the master key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_ibe_gen_prv(g2_t prv, char *id, int len, bn_t master); + +/** + * Encrypts a message using the BF-IBE protocol. + * + * @param[out] out - the output buffer. + * @param[in, out] out_len - the buffer capacity and number of bytes written. + * @param[in] in - the input buffer. + * @param[in] in_len - the number of bytes to encrypt. + * @param[in] pub - the public key of the PKG. + * @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, int len, g1_t pub); + +/** + * Decrypts a message using the BF-IBE protocol. + * + * @param[out] out - the output buffer. + * @param[in, out] out_len - the buffer capacity and number of bytes written. + * @param[in] in - the input buffer. + * @param[in] in_len - the number of bytes to decrypt. + * @param[in] pub - the private key of the user. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_ibe_dec(uint8_t *out, int *out_len, uint8_t *in, int in_len, g2_t prv); + +/** + * Generates a key pair for the Boneh-Lynn-Schacham (BLS) signature protocol. + * + * @param[out] d - the private key. + * @param[out] q - the public key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_bls_gen(bn_t d, g2_t q); + +/** + * Signs a message using the BLS protocol. + * + * @param[out] s - the signature. + * @param[in] msg - the message to sign. + * @param[in] len - the message length in bytes. + * @param[in] d - the private key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_bls_sig(g1_t s, uint8_t *msg, int len, bn_t d); + +/** + * Verifies a message signed with BLS protocol. + * + * @param[out] s - the signature. + * @param[in] msg - the message to sign. + * @param[in] len - the message length in bytes. + * @param[in] q - the public key. + * @return a boolean value indicating if the signature is valid. + */ +int cp_bls_ver(g1_t s, uint8_t *msg, int len, g2_t q); + +/** + * Generates a key pair for the Boneh-Boyen (BB) signature protocol. + * + * @param[out] d - the private key. + * @param[out] q - the first component of the public key. + * @param[out] z - the second component of the public key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_bbs_gen(bn_t d, g2_t q, gt_t z); + +/** + * Signs a message using the BB protocol. + * + * @param[out] s - the signature. + * @param[in] msg - the message to sign. + * @param[in] len - the message length in bytes. + * @param[in] hash - the flag to indicate the message format. + * @param[in] d - the private key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_bbs_sig(g1_t s, uint8_t *msg, int len, int hash, bn_t d); + +/** + * Verifies a message signed with the BB protocol. + * + * @param[in] s - the signature. + * @param[in] msg - the message to sign. + * @param[in] len - the message length in bytes. + * @param[in] hash - the flag to indicate the message format. + * @param[out] q - the first component of the public key. + * @param[out] z - the second component of the public key. + * @return a boolean value indicating the verification result. + */ +int cp_bbs_ver(g1_t s, uint8_t *msg, int len, int hash, g2_t q, gt_t z); + +/** + * Generates a key pair for the Camenisch-Lysyanskaya simple signature (CLS) + * protocol. + * + * @param[out] u - the first part of the private key. + * @param[out] v - the second part of the private key. + * @param[out] x - the first part of the public key. + * @param[out] y - the second part of the public key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_cls_gen(bn_t u, bn_t v, g2_t x, g2_t y); + +/** + * Signs a message using the CLS protocol. + * + * @param[out] a - the first part of the signature. + * @param[out] b - the second part of the signature. + * @param[out] c - the third part of the signature. + * @param[in] msg - the message to sign. + * @param[in] len - the message length in bytes. + * @param[in] u - the first part of the private key. + * @param[in] v - the second part of the private key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_cls_sig(g1_t a, g1_t b, g1_t c, uint8_t *msg, int len, bn_t u, bn_t v); + +/** + ** Verifies a signature using the CLS protocol. + * + * @param[in] a - the first part of the signature. + * @param[in] b - the second part of the signature. + * @param[in] c - the third part of the signature. + * @param[in] msg - the message to sign. + * @param[in] len - the message length in bytes. + * @param[in] u - the first part of the public key. + * @param[in] v - the second part of the public key. + * @return a boolean value indicating the verification result. + */ +int cp_cls_ver(g1_t a, g1_t b, g1_t c, uint8_t *msg, int len, g2_t x, g2_t y); + +/** + * Generates a key pair for the Camenisch-Lysyanskaya message-independent (CLI) + * signature protocol. + * + * @param[out] t - the first part of the private key. + * @param[out] u - the second part of the private key. + * @param[out] v - the third part of the private key. + * @param[out] x - the first part of the public key. + * @param[out] y - the second part of the public key. + * @param[out] z - the third part of the public key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_cli_gen(bn_t t, bn_t u, bn_t v, g2_t x, g2_t y, g2_t z); + +/** + * Signs a message using the CLI protocol. + * + * @param[out] a - one of the components of the signature. + * @param[out] A - one of the components of the signature. + * @param[out] b - one of the components of the signature. + * @param[out] B - one of the components of the signature. + * @param[out] c - one of the components of the signature. + * @param[in] msg - the message to sign. + * @param[in] len - the message length in bytes. + * @param[in] r - the per-message randomness. + * @param[in] t - the first part of the private key. + * @param[in] u - the second part of the private key. + * @param[in] v - the third part of the private key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_cli_sig(g1_t a, g1_t A, g1_t b, g1_t B, g1_t c, uint8_t *msg, int len, + bn_t r, bn_t t, bn_t u, bn_t v); + +/** + * Verifies a message signed using the CLI protocol. + * + * @param[in] a - one of the components of the signature. + * @param[in] A - one of the components of the signature. + * @param[in] b - one of the components of the signature. + * @param[in] B - one of the components of the signature. + * @param[in] c - one of the components of the signature. + * @param[in] msg - the message to sign. + * @param[in] len - the message length in bytes. + * @param[in] r - the per-message randomness. + * @param[in] x - the first part of the public key. + * @param[in] y - the second part of the public key. + * @param[in] z - the third part of the public key. + * @return a boolean value indicating the verification result. + */ +int cp_cli_ver(g1_t a, g1_t A, g1_t b, g1_t B, g1_t c, uint8_t *msg, int len, + bn_t r, g2_t x, g2_t y, g2_t z); + +/** + * Generates a key pair for the Camenisch-Lysyanskaya message-block (CLB) + * signature protocol. + * + * @param[out] t - the first part of the private key. + * @param[out] u - the second part of the private key. + * @param[out] v - the remaining (l - 1) parts of the private key. + * @param[out] x - the first part of the public key. + * @param[out] y - the second part of the public key. + * @param[out] z - the remaining (l - 1) parts of the public key. + * @param[in] l - the number of messages to sign. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_clb_gen(bn_t t, bn_t u, bn_t v[], g2_t x, g2_t y, g2_t z[], int l); + +/** + * Signs a block of messages using the CLB protocol. + * + * @param[out] a - the first component of the signature. + * @param[out] A - the (l - 1) next components of the signature. + * @param[out] b - the next component of the signature. + * @param[out] B - the (l - 1) next components of the signature. + * @param[out] c - the last component of the signature. + * @param[in] msgs - the l messages to sign. + * @param[in] lens - the l message lengths in bytes. + * @param[in] t - the first part of the private key. + * @param[in] u - the second part of the private key. + * @param[in] v - the remaining (l - 1) parts of the private key. + * @param[in] l - the number of messages to sign. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_clb_sig(g1_t a, g1_t A[], g1_t b, g1_t B[], g1_t c, uint8_t *msgs[], + int lens[], bn_t t, bn_t u, bn_t v[], int l); + +/** + * Verifies a block of messages signed using the CLB protocol. + * + * @param[out] a - the first component of the signature. + * @param[out] A - the (l - 1) next components of the signature. + * @param[out] b - the next component of the signature. + * @param[out] B - the (l - 1) next components of the signature. + * @param[out] c - the last component of the signature. + * @param[in] msgs - the l messages to sign. + * @param[in] lens - the l message lengths in bytes. + * @param[in] x - the first part of the public key. + * @param[in] y - the second part of the public key. + * @param[in] z - the remaining (l - 1) parts of the public key. + * @param[in] l - the number of messages to sign. + * @return a boolean value indicating the verification result. + */ +int cp_clb_ver(g1_t a, g1_t A[], g1_t b, g1_t B[], g1_t c, uint8_t *msgs[], + int lens[], g2_t x, g2_t y, g2_t z[], int l); + +/** + * Generates a key pair for the Pointcheval-Sanders simple signature (PSS) + * protocol. + * + * @param[out] u - the first part of the private key. + * @param[out] v - the second part of the private key. + * @param[out] g - the first part of the public key. + * @param[out] x - the secpmd part of the public key. + * @param[out] y - the third part of the public key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_pss_gen(bn_t u, bn_t v, g2_t g, g2_t x, g2_t y); + +/** + * Signs a message using the PSS protocol. + * + * @param[out] a - the first part of the signature. + * @param[out] b - the second part of the signature. + * @param[in] msg - the message to sign. + * @param[in] len - the message length in bytes. + * @param[in] u - the first part of the private key. + * @param[in] v - the second part of the private key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_pss_sig(g1_t a, g1_t b, uint8_t *msg, int len, bn_t u, bn_t v); + +/** + ** Verifies a signature using the PSS protocol. + * + * @param[in] a - the first part of the signature. + * @param[in] b - the second part of the signature. + * @param[in] msg - the message to sign. + * @param[in] len - the message length in bytes. + * @param[in] g - the first part of the public key. + * @param[in] u - the second part of the public key. + * @param[in] v - the third part of the public key. + * @return a boolean value indicating the verification result. + */ +int cp_pss_ver(g1_t a, g1_t b, uint8_t *msg, int len, g2_t g, g2_t x, g2_t y); + +/** + * Generates a key pair for the Pointcheval-Sanders block signature (PSB) + * protocol. + * + * @param[out] r - the first part of the private key. + * @param[out] s - the second part of the private key. + * @param[out] g - the first part of the public key. + * @param[out] x - the secpmd part of the public key. + * @param[out] y - the third part of the public key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_psb_gen(bn_t r, bn_t s[], g2_t g, g2_t x, g2_t y[], int l); + +/** + * Signs a block of messages using the PSB protocol. + * + * @param[out] a - the first component of the signature. + * @param[out] b - the second component of the signature. + * @param[in] msgs - the l messages to sign. + * @param[in] lens - the l message lengths in bytes. + * @param[in] r - the first part of the private key. + * @param[in] s - the remaining l part of the private key. + * @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, uint8_t *msgs[], int lens[], bn_t r, bn_t s[], + int l); + +/** + * Verifies a block of messages signed using the PSB protocol. + * + * @param[out] a - the first component of the signature. + * @param[out] b - the seconed component of the signature. + * @param[in] msgs - the l messages to sign. + * @param[in] lens - the l message lengths in bytes. + * @param[in] g - the first part of the public key. + * @param[in] x - the second part of the public key. + * @param[in] y - the remaining l parts of the public key. + * @param[in] l - the number of messages to sign. + * @return a boolean value indicating the verification result. + */ +int cp_psb_ver(g1_t a, g1_t b, uint8_t *msgs[], int lens[], g2_t g, g2_t x, + g2_t y[], int l); + +/** + * Generates a Zhang-Safavi-Naini-Susilo (ZSS) key pair. + * + * @param[out] d - the private key. + * @param[out] q - the first component of the public key. + * @param[out] z - the second component of the public key. + */ +int cp_zss_gen(bn_t d, g1_t q, gt_t z); + +/** + * Signs a message using ZSS scheme. + * + * @param[out] s - the signature. + * @param[in] msg - the message to sign. + * @param[in] len - the message length in bytes. + * @param[in] hash - the flag to indicate the message format. + * @param[in] d - the private key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_zss_sig(g2_t s, uint8_t *msg, int len, int hash, bn_t d); + +/** + * Verifies a message signed with ZSS scheme. + * + * @param[in] s - the signature. + * @param[in] msg - the message to sign. + * @param[in] len - the message length in bytes. + * @param[in] hash - the flag to indicate the message format. + * @param[out] q - the first component of the public key. + * @param[out] z - the second component of the public key. + * @return a boolean value indicating the verification result. + */ +int cp_zss_ver(g2_t s, uint8_t *msg, int len, int hash, g1_t q, gt_t z); + +/** + * Generates a vBNN-IBS key generation center (KGC). + * + * @param[out] msk - the KGC master key. + * @param[out] mpk - the KGC public key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_vbnn_gen(bn_t msk, ec_t mpk); + +/** + * Extract a user key from an identity and a vBNN-IBS key generation center. + * + * @param[out] sk - the extracted vBNN-IBS user private key. + * @param[out] pk - the extracted vBNN-IBS user public key. + * @param[in] msk - the KGC master key. + * @param[in] id - the identity used for extraction. + * @param[in] id_len - the identity length in bytes. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_vbnn_gen_prv(bn_t sk, ec_t pk, bn_t msk, uint8_t *id, int id_len); + +/** + * Signs a message using the vBNN-IBS scheme. + * + * @param[out] r - the R value of the signature. + * @param[out] z - the z value of the signature. + * @param[out] h - the h value of the signature. + * @param[in] id - the identity buffer. + * @param[in] id_len - the size of identity buffer. + * @param[in] msg - the message buffer to sign. + * @param[in] msg_len - the size of message buffer. + * @param[in] sk - the signer private key. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_vbnn_sig(ec_t r, bn_t z, bn_t h, uint8_t *id, int id_len, uint8_t *msg, + int msg_len, bn_t sk, ec_t pk); + +/** + * Verifies a signature and message using the vBNN-IBS scheme. + * + * @param[in] r - the R value of the signature. + * @param[in] z - the z value of the signature. + * @param[in] h - the h value of the signature. + * @param[in] id - the identity buffer. + * @param[in] id_len - the size of identity buffer. + * @param[in] msg - the message buffer to sign. + * @param[in] msg_len - the size of message buffer. + * @param[in] mpk - the master public key of the generation center. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +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); + +/** + * Initialize the Context-hiding Multi-key Homomorphic Signature scheme (CMLHS). + * The scheme due to Schabhuser et al. signs a vector of messages. + * + * @param[out] h - the random element (message as one component). + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_cmlhs_init(g1_t h); + +/** + * Generates a key pair for the CMLHS scheme using BLS as underlying signature. + * + * @param[out] x - the exponent values, one per label. + * @param[out] hs - the hash values, one per label. + * @param[in] len - the number of possible labels. + * @param[out] prf - the key for the pseudo-random function (PRF). + * @param[out] plen - the PRF key length. + * @param[out] sk - the private key for the BLS signature scheme. + * @param[out] pk - the public key for the BLS signature scheme. + * @param[out] d - the secret exponent. + * @param[out] y - the corresponding public element. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_cmlhs_gen(bn_t x[], gt_t hs[], int len, uint8_t prf[], int plen, + bn_t sk, g2_t pk, bn_t d, g2_t y); + +/** + * Signs a message vector using the CMLHS. + * + * @param[out] sig - the resulting BLS signature. + * @param[out] z - the power of the output of the PRF. + * @param[out] a - the first component of the signature. + * @param[out] c - the second component of the signature. + * @param[out] r - the third component of the signature. + * @param[out] s - the fourth component of the signature. + * @param[in] msg - the message vector to sign (one component). + * @param[in] data - the dataset identifier. + * @param[in] dlen - the length of the dataset identifier. + * @param[in] label - the integer label. + * @param[in] x - the exponent value for the label. + * @param[in] h - the random value (message has one component). + * @param[in] prf - the key for the pseudo-random function (PRF). + * @param[in] plen - the PRF key length. + * @param[in] sk - the private key for the BLS signature scheme. + * @param[out] d - the secret exponent. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +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, + char *data, int dlen, int label, bn_t x, g1_t h, + uint8_t prf[], int plen, bn_t sk, bn_t d); + +/** + * Applies a function over a set of CMLHS signatures from the same user. + * + * @param[out] a - the resulting first component of the signature. + * @param[out] c - the resulting second component of the signature. + * @param[in] as - the vector of first components of the signatures. + * @param[in] cs - the vector of second components of the signatures. + * @param[in] f - the linear coefficients in the function. + * @param[in] len - the number of coefficients. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_cmlhs_fun(g1_t a, g1_t c, g1_t as[], g1_t cs[], dig_t f[], int len); + +/** + * Evaluates a function over a set of CMLHS signatures. + * + * @param[out] r - the resulting third component of the signature. + * @param[out] s - the resulting fourth component of the signature. + * @param[in] rs - the vector of third components of the signatures. + * @param[in] ss - the vector of fourth components of the signatures. + * @param[in] f - the linear coefficients in the function. + * @param[in] len - the number of coefficients. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_cmlhs_evl(g1_t r, g2_t s, g1_t rs[], g2_t ss[], dig_t f[], int len); + +/** + * Verifies a CMLHS signature over a set of messages. + * + * @param[in] r - the first component of the homomorphic signature. + * @param[in] s - the second component of the homomorphic signature. + * @param[in] sig - the BLS signatures. + * @param[in] z - the powers of the outputs of the PRF. + * @param[in] a - the vector of first components of the signatures. + * @param[in] c - the vector of second components of the signatures. + * @param[in] msg - the combined message. + * @param[in] data - the dataset identifier. + * @param[in] dlen - the length of the dataset identifier. + * @param[in] label - the integer labels. + * @param[in] h - the random element (message has one component). + * @param[in] hs - the hash values, one per label. + * @param[in] f - the linear coefficients in the function. + * @param[in] flen - the number of coefficients. + * @param[in] y - the public elements of the users. + * @param[in] pk - the public keys of the users. + * @param[in] slen - the number of signatures. + * @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, int dlen, int label[], g1_t h, + gt_t hs[][RLC_TERMS], dig_t f[][RLC_TERMS], int flen[], g2_t y[], + g2_t pk[], int slen); + +/** + * Generates a key pair for the Multi-Key Homomorphic Signature (MKLHS) scheme. + * + * @param[out] sk - the private key for the signature scheme. + * @param[out] pk - the public key for the signature scheme. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_mklhs_gen(bn_t sk, g2_t pk); + +/** + * Signs a message using the MKLHS. + * + * @param[out] s - the resulting signature. + * @param[in] m - the message to sign. + * @param[in] data - the dataset identifier. + * @param[in] dlen - the length of the dataset identifier. + * @param[in] label - the label. + * @param[in] llen - the length of the label. + * @param[in] sk - the private key for the signature scheme. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_mklhs_sig(g1_t s, bn_t m, char *data, int dlen, char *label, int llen, + bn_t sk); + +/** + * Applies a function over a set of messages from the same user. + * + * @param[out] mu - the combined message. + * @param[in] m - the vector of individual messages. + * @param[in] f - the linear coefficients in the function. + * @param[in] len - the number of coefficients. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_mklhs_fun(bn_t mu, bn_t m[], dig_t f[], int len); + +/** + * Evaluates a function over a set of MKLHS signatures. + * + * @param[out] sig - the resulting signature + * @param[in] s - the set of signatures. + * @param[in] f - the linear coefficients in the function. + * @param[in] len - the number of coefficients. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_mklhs_evl(g1_t sig, g1_t s[], dig_t f[], int len); + +/** + * Verifies a MKLHS signature over a set of messages. + * + * @param[in] sig - the homomorphic signature to verify. + * @param[in] m - the signed message. + * @param[in] mu - the vector of signed messages per user. + * @param[in] data - the dataset identifier. + * @param[in] dlen - the length of the dataset identifier. + * @param[in] label - the vector of labels. + * @param[in] llen - the vector of label lengths. + * @param[in] f - the linear coefficients in the function. + * @param[in] flen - the number of coefficients. + * @param[in] pk - the public keys of the users. + * @param[in] slen - the number of signatures. + * @return a boolean value indicating the verification result. + */ +int cp_mklhs_ver(g1_t sig, bn_t m, bn_t mu[], char *data, int dlen, + char *label[], int llen[], dig_t f[][RLC_TERMS], int flen[], g2_t pk[], + int slen); + +/** + * Computes the offline part of veryfying a MKLHS signature over a set of + * messages. + * + * @param[out] h - the hashes of labels + * @param[out] ft - the precomputed linear coefficients. + * @param[in] label - the vector of labels. + * @param[in] llen - the vector of label lengths. + * @param[in] f - the linear coefficients in the function. + * @param[in] flen - the number of coefficients. + * @param[in] slen - the number of signatures. + * @return RLC_OK if no errors occurred, RLC_ERR otherwise. + */ +int cp_mklhs_off(g1_t h[], dig_t ft[], char *label[], int llen[], + dig_t f[][RLC_TERMS], int flen[], int slen); + +/** + * Computes the online part of veryfying a MKLHS signature over a set of + * messages. + * + * @param[in] sig - the homomorphic signature to verify. + * @param[in] m - the signed message. + * @param[in] mu - the vector of signed messages per user. + * @param[in] data - the dataset identifier. + * @param[in] dlen - the length of the dataset identifier. + * @param[in] d - the hashes of labels. + * @param[in] ft - the precomputed linear coefficients. + * @param[in] pk - the public keys of the users. + * @param[in] slen - the number of signatures. + * @return a boolean value indicating the verification result. + */ +int cp_mklhs_onv(g1_t sig, bn_t m, bn_t mu[], char *data, int dlen, + g1_t h[], dig_t ft[], g2_t pk[], int slen); + +#endif /* !RLC_CP_H */ diff --git a/bls/contrib/relic/include/relic_dv.h b/bls/contrib/relic/include/relic_dv.h new file mode 100644 index 00000000..dc71b463 --- /dev/null +++ b/bls/contrib/relic/include/relic_dv.h @@ -0,0 +1,262 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 . + */ + +/** + * @defgroup dv Digit vector handling + */ + +/** + * @file + * + * Interface of the module for manipulating temporary double-precision digit + * vectors. + * + * @ingroup dv + */ + +#ifndef RLC_DV_H +#define RLC_DV_H + +#include "relic_bn.h" +#include "relic_conf.h" +#include "relic_types.h" +#include "relic_util.h" +#include "relic_label.h" + +/*============================================================================*/ +/* Constant definitions */ +/*============================================================================*/ + +/** + * Size in bits of the largest field element. + */ +#ifdef WITH_FP + +#ifdef WITH_FB +#define RLC_DV_MAX (RLC_MAX(FP_PRIME, FB_POLYN)) +#else /* !WITH_FB */ +#define RLC_DV_MAX (FP_PRIME) +#endif + +#else /* !WITH_FP */ + +#ifdef WITH_FB +#define RLC_DV_MAX (FB_POLYN) +#else /* !WITH_FB */ +#define RLC_DV_MAX (0) +#endif + +#endif /* WITH_FP */ + +/** + * Size in digits of a temporary vector. + * + * A temporary vector has enough size to store a multiplication/squaring result + * produced by any module. + */ +#define RLC_DV_DIGS (RLC_MAX(RLC_CEIL(RLC_DV_MAX, RLC_DIG), RLC_BN_SIZE)) + +/** + * Size in bytes of a temporary vector. + */ +#define RLC_DV_BYTES (RLC_DV_DIGS * (RLC_DIG / 8)) + +/*============================================================================*/ +/* Macro definitions */ +/*============================================================================*/ + +/** + * Size of padding to be added so that digit vectors are aligned. + */ +#if ALIGN > 1 +#define RLC_PAD(A) ((A) % ALIGN == 0 ? 0 : ALIGN - ((A) % ALIGN)) +#else +#define RLC_PAD(A) (0) +#endif + +/** + * Align digit vector pointer to specified byte-boundary. + * + * @param[in,out] A - the pointer to align. + */ +#if ALIGN > 1 +#if ARCH == AVR || ARCH == MSP || ARCH == X86 || ARCH == ARM +#define ALIGNED(A) ((unsigned int)(A) + RLC_PAD((unsigned int)(A))); + +#elif ARCH == X64 +#define ALIGNED(A) ((unsigned long)(A) + RLC_PAD((unsigned long)(A))); + +#endif +#else +#define ALIGNED(A) (A) +#endif + +/*============================================================================*/ +/* Type definitions */ +/*============================================================================*/ + +/** + * Represents a temporary double-precision digit vector. + */ +#if ALLOC == AUTO +typedef rlc_align dig_t dv_t[RLC_DV_DIGS + RLC_PAD(RLC_DV_BYTES)/(RLC_DIG / 8)]; +#else +typedef dig_t *dv_t; +#endif + +/*============================================================================*/ +/* Macro definitions */ +/*============================================================================*/ + +/** + * Initializes a digit vector with a null value. + * + * @param[out] A - the digit vector to initialize. + */ +#if ALLOC == AUTO +#define dv_null(A) /* empty */ +#else +#define dv_null(A) A = NULL; +#endif + +/** + * Calls a function to allocate a temporary double-precision digit vector. + * + * @param[out] A - the double-precision result. + */ +#if ALLOC == DYNAMIC +#define dv_new(A) dv_new_dynam(&(A), RLC_DV_DIGS) +#elif ALLOC == AUTO +#define dv_new(A) /* empty */ +#elif ALLOC == STACK +#define dv_new(A) \ + A = (dig_t *)alloca(RLC_DV_BYTES + RLC_PAD(RLC_DV_BYTES)); \ + A = (dig_t *)RLC_ALIGN(A); \ + +#endif + +/** + * Calls a function to clean and free a temporary double-precision digit vector. + * + * @param[out] A - the temporary digit vector to clean and free. + */ +#if ALLOC == DYNAMIC +#define dv_free(A) dv_free_dynam(&(A)) +#elif ALLOC == AUTO +#define dv_free(A) (void)A +#elif ALLOC == STACK +#define dv_free(A) (void)A +#endif + +/*============================================================================*/ +/* Function prototypes */ +/*============================================================================*/ + +/** + * Prints a temporary digit vector. + * + * @param[in] a - the temporary digit vector to print. + * @param[in] digits - the number of digits to print. + */ +void dv_print(dig_t *a, int digits); + +/** + * Assigns zero to a temporary double-precision digit vector. + * + * @param[out] a - the temporary digit vector to assign. + * @param[in] digits - the number of words to initialize with zero. + */ +void dv_zero(dig_t *a, int digits); + +/** + * Copies some digits from a digit vector to another digit vector. + * + * @param[out] c - the destination. + * @param[in] a - the source. + * @param[in] digits - the number of digits to copy. + */ +void dv_copy(dig_t *c, const dig_t *a, int digits); + +/** + * Conditionally copies some digits from a digit vector to another digit vector. + * + * @param[out] c - the destination. + * @paraim[in] a - the source. + * @param[in] digits - the number of digits to copy. + * @param[in] cond - the condition to evaluate. + */ +void dv_copy_cond(dig_t *c, const dig_t *a, int digits, dig_t cond); + +/** + * Conditionally swap two digit vectors. + * + * @param[in,out] c - the destination. + * @paraim[in,out] a - the source. + * @param[in] digits - the number of digits to copy. + * @param[in] cond - the condition to evaluate. + */ +void dv_swap_cond(dig_t *c, dig_t *a, int digits, dig_t cond); + +/** + * Returns the result of a comparison between two digit vectors. + * + * @param[in] a - the first digit vector. + * @param[in] b - the second digit vector. + * @param[in] size - the length in digits of the vectors. + * @return RLC_LT if a < b, RLC_EQ if a == b and RLC_GT if a > b. + */ +int dv_cmp(const dig_t *a, const dig_t *b, int size); + +/** + * Compares two digit vectors in constant time. + * + * @param[in] a - the first digit vector. + * @param[in] b - the second digit vector. + * @param[in] size - the length in digits of the vectors. + * @return RLC_EQ if they are equal and RLC_NE otherwise. + */ +int dv_cmp_const(const dig_t *a, const dig_t *b, int size); + +/** + * Allocates and initializes a temporary double-precision digit vector. + * + * @param[out] a - the new temporary digit vector. + * @param[in] digits - the required precision in digits. + * @throw ERR_NO_MEMORY - if there is no available memory. + * @throw ERR_PRECISION - if the required precision cannot be represented + * by the library. + */ +#if ALLOC == DYNAMIC +void dv_new_dynam(dv_t *a, int digits); +#endif + +/** + * Cleans and frees a temporary double-precision digit vector. + * + * @param[out] a - the temporary digit vector to clean and free. + */ +#if ALLOC == DYNAMIC +void dv_free_dynam(dv_t *a); +#endif + +#endif /* !RLC_DV_H */ diff --git a/bls/contrib/relic/include/relic_eb.h b/bls/contrib/relic/include/relic_eb.h new file mode 100644 index 00000000..35000a95 --- /dev/null +++ b/bls/contrib/relic/include/relic_eb.h @@ -0,0 +1,967 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 . + */ + +/** + * @defgroup eb Elliptic curves over binary fields + */ + +/** + * @file + * + * Interface of the module for arithmetic on binary elliptic curves. + * + * @ingroup eb + */ + +#ifndef RLC_EB_H +#define RLC_EB_H + +#include "relic_fb.h" +#include "relic_bn.h" +#include "relic_conf.h" +#include "relic_types.h" +#include "relic_label.h" + +/*============================================================================*/ +/* Constant definitions */ +/*============================================================================*/ + +/** + * Binary elliptic curve identifiers. + */ +enum { + /** NIST B-163 binary curve. */ + NIST_B163 = 1, + /** NIST K-163 Koblitz curve. */ + NIST_K163, + /** NIST B-133 binary curve. */ + NIST_B233, + /** NIST K-233 Koblitz curve. */ + NIST_K233, + /** Curve over 2^{251} used in eBATs. */ + EBACS_B251, + /** Curve over 2^{257} good for halving. */ + HALVE_B257, + /** SECG K-239 binary curve. */ + SECG_K239, + /** NIST B-283 binary curve. */ + NIST_B283, + /** NIST K-283 Koblitz curve. */ + NIST_K283, + /** NIST B-409 binary curve. */ + NIST_B409, + /** NIST K-409 Koblitz curve. */ + NIST_K409, + /** NIST B-571 binary curve. */ + NIST_B571, + /** NIST K-571 Koblitz curve. */ + NIST_K571, +}; + +/** + * Size of a precomputation table using the binary method. + */ +#define RLC_EB_TABLE_BASIC (RLC_FB_BITS) + +/** + * Size of a precomputation table using the single-table comb method. + */ +#define RLC_EB_TABLE_COMBS (1 << EB_DEPTH) + +/** + * Size of a precomputation table using the double-table comb method. + */ +#define RLC_EB_TABLE_COMBD (1 << (EB_DEPTH + 1)) + +/** + * Size of a precomputation table using the w-(T)NAF method. + */ +#define RLC_EB_TABLE_LWNAF (1 << (EB_DEPTH - 2)) + +/** + * Size of a precomputation table using the chosen algorithm. + */ +#if EB_FIX == BASIC +#define RLC_EB_TABLE RLC_EB_TABLE_BASIC +#elif EB_FIX == COMBS +#define RLC_EB_TABLE RLC_EB_TABLE_COMBS +#elif EB_FIX == COMBD +#define RLC_EB_TABLE RLC_EB_TABLE_COMBD +#elif EB_FIX == LWNAF +#define RLC_EB_TABLE RLC_EB_TABLE_LWNAF +#endif + +/** + * Maximum size of a precomputation table. + */ +#ifdef STRIP +#define RLC_EB_TABLE_MAX RLC_EB_TABLE +#else +#define RLC_EB_TABLE_MAX RLC_MAX(RLC_EB_TABLE_BASIC, RLC_EB_TABLE_COMBD) +#endif + +/*============================================================================*/ +/* Type definitions */ +/*============================================================================*/ + +/** + * Represents an elliptic curve point over a binary field. + */ +typedef struct { + /** The first coordinate. */ + fb_st x; + /** The second coordinate. */ + fb_st y; + /** The third coordinate (projective representation). */ + fb_st z; + /** Flag to indicate that this point is normalized. */ + int norm; +} eb_st; + +/** + * Pointer to an elliptic curve point. + */ +#if ALLOC == AUTO +typedef eb_st eb_t[1]; +#else +typedef eb_st *eb_t; +#endif + +/*============================================================================*/ +/* Macro definitions */ +/*============================================================================*/ + +/** + * Initializes a point on a binary elliptic curve with a null value. + * + * @param[out] A - the point to initialize. + */ +#if ALLOC == AUTO +#define eb_null(A) /* empty */ +#else +#define eb_null(A) A = NULL; +#endif + +/** + * Calls a function to allocate a point on a binary elliptic curve. + * + * @param[out] A - the new point. + * @throw ERR_NO_MEMORY - if there is no available memory. + */ +#if ALLOC == DYNAMIC +#define eb_new(A) \ + A = (eb_t)calloc(1, sizeof(eb_st)); \ + if (A == NULL) { \ + THROW(ERR_NO_MEMORY); \ + } \ + +#elif ALLOC == AUTO +#define eb_new(A) /* empty */ + +#elif ALLOC == STACK +#define eb_new(A) \ + A = (eb_t)alloca(sizeof(eb_st)); \ + +#endif + +/** + * Calls a function to clean and free a point on a binary elliptic curve. + * + * @param[out] A - the point to clean and free. + */ +#if ALLOC == DYNAMIC +#define eb_free(A) \ + if (A != NULL) { \ + free(A); \ + A = NULL; \ + } \ + +#elif ALLOC == AUTO +#define eb_free(A) /* empty */ + +#elif ALLOC == STACK +#define eb_free(A) \ + A = NULL; \ + +#endif + +/** + * Negates a binary elliptic curve point. Computes R = -P. + * + * @param[out] R - the result. + * @param[in] P - the point to negate. + */ +#if EB_ADD == BASIC +#define eb_neg(R, P) eb_neg_basic(R, P) +#elif EB_ADD == PROJC +#define eb_neg(R, P) eb_neg_projc(R, P) +#endif + +/** + * Adds two binary elliptic curve points. 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 EB_ADD == BASIC +#define eb_add(R, P, Q) eb_add_basic(R, P, Q); +#elif EB_ADD == PROJC +#define eb_add(R, P, Q) eb_add_projc(R, P, Q); +#endif + +/** + * Subtracts a binary elliptic curve point from another. Computes R = P - Q. + * + * @param[out] R - the result. + * @param[in] P - the first point. + * @param[in] Q - the second point. + */ +#if EB_ADD == BASIC +#define eb_sub(R, P, Q) eb_sub_basic(R, P, Q) +#elif EB_ADD == PROJC +#define eb_sub(R, P, Q) eb_sub_projc(R, P, Q) +#endif + +/** + * Doubles a binary elliptic curve point. Computes R = 2P. + * + * @param[out] R - the result. + * @param[in] P - the point to double. + */ +#if EB_ADD == BASIC +#define eb_dbl(R, P) eb_dbl_basic(R, P); +#elif EB_ADD == PROJC +#define eb_dbl(R, P) eb_dbl_projc(R, P); +#endif + +/** + * Computes the Frobenius map of a binary elliptic curve point on a Koblitz + * curve. Computes R = t(P). + * + * @param[out] R - the result. + * @param[in] P - the point. + */ +#if EB_ADD == BASIC +#define eb_frb(R, P) eb_frb_basic(R, P) +#elif EB_ADD == PROJC +#define eb_frb(R, P) eb_frb_projc(R, P) +#endif + +/** + * Multiplies a binary elliptic curve point by an integer. Computes R = kP. + * + * @param[out] R - the result. + * @param[in] P - the point to multiply. + * @param[in] K - the integer. + */ +#if EB_MUL == BASIC +#define eb_mul(R, P, K) eb_mul_basic(R, P, K) +#elif EB_MUL == LODAH +#define eb_mul(R, P, K) eb_mul_lodah(R, P, K) +#elif EB_MUL == HALVE +#define eb_mul(R, P, K) eb_mul_halve(R, P, K) +#elif EB_MUL == LWNAF +#define eb_mul(R, P, K) eb_mul_lwnaf(R, P, K) +#elif EB_MUL == RWNAF +#define eb_mul(R, P, K) eb_mul_rwnaf(R, P, K) +#endif + +/** + * Builds a precomputation table for multiplying a fixed binary elliptic point + * point. + * + * @param[out] T - the precomputation table. + * @param[in] P - the point to multiply. + */ +#if EB_FIX == BASIC +#define eb_mul_pre(T, P) eb_mul_pre_basic(T, P) +#elif EB_FIX == COMBS +#define eb_mul_pre(T, P) eb_mul_pre_combs(T, P) +#elif EB_FIX == COMBD +#define eb_mul_pre(T, P) eb_mul_pre_combd(T, P) +#elif EB_FIX == LWNAF +#define eb_mul_pre(T, P) eb_mul_pre_lwnaf(T, P) +#endif + +/** + * Multiplies a fixed binary elliptic point using a precomputation table. + * Computes R = kP. + * + * @param[out] R - the result. + * @param[in] T - the precomputation table. + * @param[in] K - the integer. + */ +#if EB_FIX == BASIC +#define eb_mul_fix(R, T, K) eb_mul_fix_basic(R, T, K) +#elif EB_FIX == COMBS +#define eb_mul_fix(R, T, K) eb_mul_fix_combs(R, T, K) +#elif EB_FIX == COMBD +#define eb_mul_fix(R, T, K) eb_mul_fix_combd(R, T, K) +#elif EB_FIX == LWNAF +#define eb_mul_fix(R, T, K) eb_mul_fix_lwnaf(R, T, K) +#endif + +/** + * Multiplies and adds two binary elliptic curve points simultaneously. Computes + * R = kP + mQ. + * + * @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 EB_SIM == BASIC +#define eb_mul_sim(R, P, K, Q, M) eb_mul_sim_basic(R, P, K, Q, M) +#elif EB_SIM == TRICK +#define eb_mul_sim(R, P, K, Q, M) eb_mul_sim_trick(R, P, K, Q, M) +#elif EB_SIM == INTER +#define eb_mul_sim(R, P, K, Q, M) eb_mul_sim_inter(R, P, K, Q, M) +#elif EB_SIM == JOINT +#define eb_mul_sim(R, P, K, Q, M) eb_mul_sim_joint(R, P, K, Q, M) +#endif + +/*============================================================================*/ +/* Function prototypes */ +/*============================================================================*/ + +/** + * Initializes the binary elliptic curve arithmetic module. + */ +void eb_curve_init(void); + +/** + * Finalizes the binary elliptic curve arithmetic module. + */ +void eb_curve_clean(void); + +/** + * Returns the 'a' coefficient of the currently configured binary elliptic + * curve. + * + * @return the 'a' coefficient of the elliptic curve. + */ +dig_t *eb_curve_get_a(void); + +/** + * Returns the 'b' coefficient of the currently configured binary elliptic + * curve. + * + * @return the 'b' coefficient of the elliptic curve. + */ +dig_t *eb_curve_get_b(void); + +/** + * Returns a optimization identifier based on the 'a' coefficient of the curve. + * + * @return the optimization identifier. + */ +int eb_curve_opt_a(void); + +/** + * Returns a optimization identifier based on the 'b' coefficient of the curve. + * + * @return the optimization identifier. + */ +int eb_curve_opt_b(void); + +/** + * Tests if the configured binary elliptic curve is a Koblitz curve. + * + * @return 1 if the binary elliptic curve is a Koblitz curve, 0 otherwise. + */ +int eb_curve_is_kbltz(void); + +/** + * Returns the generator of the group of points in the binary elliptic curve. + * + * @param[out] g - the returned generator. + */ +void eb_curve_get_gen(eb_t g); + +/** + * Returns the precomputation table for the generator. + * + * @return the table. + */ +const eb_t *eb_curve_get_tab(void); + +/** + * Returns the order of the group of points in the binary elliptic curve. + * + * @param[out] n - the returned order. + */ +void eb_curve_get_ord(bn_t n); + +/** + * Returns the cofactor of the binary elliptic curve. + * + * @param[out] n - the returned cofactor. + */ +void eb_curve_get_cof(bn_t h); + +/** + * Configures an ordinary binary elliptic curve by its coefficients and + * generator. + * + * @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] n - the order of the generator. + * @param[in] h - the cofactor of the group order. + */ +void eb_curve_set(const fb_t a, const fb_t b, const eb_t g, const bn_t n, + const bn_t h); + +/** + * Configures a new binary elliptic curve by its parameter identifier. + * + * @param[in] param - the parameters identifier. + */ +void eb_param_set(int param); + +/** + * Configures some set of curve parameters for the current security level. + */ +int eb_param_set_any(void); + +/** + * Configures a set of curve parameters without endormorphisms for the current + * security level. + * + * @return RLC_OK if there is a curve at this security level, RLC_ERR otherwise. + */ +int eb_param_set_any_plain(void); + +/** + * Configures a set of Koblitz curve parameters for the current security level. + * + * @return RLC_OK if there is a curve at this security level, RLC_ERR otherwise. + */ +int eb_param_set_any_kbltz(void); + +/** + * Returns the parameter identifier of the currently configured binary elliptic + * curve. + * + * @return the parameter identifier. + */ +int eb_param_get(void); + +/** + * Prints the current configured binary elliptic curve. + */ +void eb_param_print(void); + +/** + * Returns the current security level. + */ +int eb_param_level(void); + +/** + * Tests if a point on a binary elliptic curve is at the infinity. + * + * @param[in] p - the point to test. + * @return 1 if the point is at infinity, 0 otherise. + */ +int eb_is_infty(const eb_t p); + +/** + * Assigns a binary elliptic curve point to a point at the infinity. + * + * @param[out] p - the point to assign. + */ +void eb_set_infty(eb_t p); + +/** + * Copies the second argument to the first argument. + * + * @param[out] r - the result. + * @param[in] p - the binary elliptic curve point to copy. + */ +void eb_copy(eb_t r, const eb_t p); + +/** + * Compares two binary elliptic curve points. + * + * @param[in] p - the first binary elliptic curve point. + * @param[in] q - the second binary elliptic curve point. + * @return RLC_EQ if p == q and RLC_NE if p != q. + */ +int eb_cmp(const eb_t p, const eb_t q); + +/** + * Assigns a random value to a binary elliptic curve point. + * + * @param[out] p - the binary elliptic curve point to assign. + */ +void eb_rand(eb_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 eb_rhs(fb_t rhs, const eb_t p); + +/** Tests if a point is in the curve. + * + * @param[in] p - the point to test. + */ +int eb_is_valid(const eb_t p); + +/** + * Builds a precomputation table for multiplying a random binary elliptic point. + * + * @param[out] t - the precomputation table. + * @param[in] p - the point to multiply. + * @param[in] w - the window width. + */ +void eb_tab(eb_t *t, const eb_t p, int w); + +/** + * Prints a binary elliptic curve point. + * + * @param[in] p - the binary elliptic curve point to print. + */ +void eb_print(const eb_t p); + +/** + * Returns the number of bytes necessary to store a binary elliptic curve point + * with optional point compression. + * + * @param[in] a - the binary field element. + * @param[in] pack - the flag to indicate compression. + * @return the number of bytes. + */ +int eb_size_bin(const eb_t a, int pack); + +/** + * Reads a binary elliptic curve point 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 eb_read_bin(eb_t a, const uint8_t *bin, int len); + +/** + * Writes a binary field element 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 binary elliptic curve point to write. + * @param[in] pack - the flag to indicate point compression. + * @throw ERR_NO_BUFFER - if the buffer capacity is invalid. + */ +void eb_write_bin(uint8_t *bin, int len, const eb_t a, int pack); + +/** + * Negates a binary elliptic curve point represented by affine coordinates. + * + * @param[out] r - the result. + * @param[in] p - the point to negate. + */ +void eb_neg_basic(eb_t r, const eb_t p); + +/** + * Negates a binary elliptic curve point represented by projective coordinates. + * + * @param[out] r - the result. + * @param[in] p - the point to negate. + */ +void eb_neg_projc(eb_t r, const eb_t p); + +/** + * Adds two binary elliptic curve points represented in affine coordinates. + * + * @param[out] r - the result. + * @param[in] p - the first point to add. + * @param[in] q - the second point to add. + */ +void eb_add_basic(eb_t r, const eb_t p, const eb_t q); + +/** + * Adds two binary elliptic curve points represented in projective coordinates. + * 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. + */ +void eb_add_projc(eb_t r, const eb_t p, const eb_t q); + +/** + * Subtracts a binary elliptic curve point from another, both points represented + * by affine coordinates. + * + * @param[out] r - the result. + * @param[in] p - the first point. + * @param[in] q - the second point. + */ +void eb_sub_basic(eb_t r, const eb_t p, const eb_t q); + +/** + * Subtracts a binary elliptic curve point from another, both points represented + * by projective coordinates. + * + * @param[out] r - the result. + * @param[in] p - the first point. + * @param[in] q - the second point. + */ +void eb_sub_projc(eb_t r, const eb_t p, const eb_t q); + +/** + * Doubles a binary elliptic curve point represented in affine coordinates. + * + * @param[out] r - the result. + * @param[in] p - the point to double. + */ +void eb_dbl_basic(eb_t r, const eb_t p); + +/** + * Doubles a binary elliptic curve point represented in projective coordinates. + * + * @param[out] r - the result. + * @param[in] p - the point to double. + */ +void eb_dbl_projc(eb_t r, const eb_t p); + +/** + * Halves a point represented in affine coordinates. + * + * @param[out] r - the result. + * @param[in] p - the point to halve. + */ +void eb_hlv(eb_t r, const eb_t p); + +/** + * Computes the Frobenius map of a binary elliptic curve point represented + * by affine coordinates. + * + * @param[out] r - the result. + * @param[in] p - the point. + */ +void eb_frb_basic(eb_t r, const eb_t p); + +/** + * Computes the Frobenius map of a binary elliptic curve point represented + * by projective coordinates. + * + * @param[out] r - the result. + * @param[in] p - the point. + */ +void eb_frb_projc(eb_t r, const eb_t p); + +/** + * Multiplies a binary 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 eb_mul_basic(eb_t r, const eb_t p, const bn_t k); + +/** + * Multiplies a binary elliptic point by an integer using the constant-time + * López-Dahab point multiplication method. + * + * @param[out] r - the result. + * @param[in] p - the point to multiply. + * @param[in] k - the integer. + */ +void eb_mul_lodah(eb_t r, const eb_t p, const bn_t k); + +/** + * Multiplies a binary elliptic point by an integer using the left-to-right + * w-NAF method. If the binary curve is a Koblitz curve, w-TNAF is used. + * + * @param[out] r - the result. + * @param[in] p - the point to multiply. + * @param[in] k - the integer. + */ +void eb_mul_lwnaf(eb_t r, const eb_t p, const bn_t k); + +/** + * Multiplies a binary elliptic point by an integer using the right-to-left + * w-NAF method. If the binary curve is a Koblitz curve, w-TNAF is used. + * + * @param[out] r - the result. + * @param[in] p - the point to multiply. + * @param[in] k - the integer. + */ +void eb_mul_rwnaf(eb_t r, const eb_t p, const bn_t k); + +/** + * Multiplies a binary elliptic point by an integer using the halving method. + * + * @param[out] r - the result. + * @param[in] p - the point to multiply. + * @param[in] k - the integer. + */ +void eb_mul_halve(eb_t r, const eb_t p, const bn_t k); + +/** + * Multiplies the generator of a binary elliptic curve by an integer. + * + * @param[out] r - the result. + * @param[in] k - the integer. + */ +void eb_mul_gen(eb_t r, const bn_t k); + +/** + * Multiplies a binary elliptic point by a small positive integer. + * + * @param[out] r - the result. + * @param[in] p - the point to multiply. + * @param[in] k - the integer. + */ +void eb_mul_dig(eb_t r, const eb_t p, const dig_t k); + +/** + * Builds a precomputation table for multiplying a fixed binary elliptic point + * using the binary method. + * + * @param[out] t - the precomputation table. + * @param[in] p - the point to multiply. + */ +void eb_mul_pre_basic(eb_t *t, const eb_t p); + +/** + * Builds a precomputation table for multiplying a fixed binary elliptic point + * using Yao's windowing method. + * + * @param[out] t - the precomputation table. + * @param[in] p - the point to multiply. + */ +void eb_mul_pre_yaowi(eb_t *t, const eb_t p); + +/** + * Builds a precomputation table for multiplying a fixed binary elliptic point + * using the NAF windowing method. + * + * @param[out] t - the precomputation table. + * @param[in] p - the point to multiply. + */ +void eb_mul_pre_nafwi(eb_t *t, const eb_t p); + +/** + * Builds a precomputation table for multiplying a fixed binary elliptic point + * using the single-table comb method. + * + * @param[out] t - the precomputation table. + * @param[in] p - the point to multiply. + */ +void eb_mul_pre_combs(eb_t *t, const eb_t p); + +/** + * Builds a precomputation table for multiplying a fixed binary elliptic point + * using the double-table comb method. + * + * @param[out] t - the precomputation table. + * @param[in] p - the point to multiply. + */ +void eb_mul_pre_combd(eb_t *t, const eb_t p); + +/** + * Builds a precomputation table for multiplying a fixed binary elliptic point + * using the w-(T)NAF method. + * + * @param[out] t - the precomputation table. + * @param[in] p - the point to multiply. + */ +void eb_mul_pre_lwnaf(eb_t *t, const eb_t p); + +/** + * Multiplies a fixed binary 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 eb_mul_fix_basic(eb_t r, const eb_t *t, const bn_t k); + +/** + * Multiplies a fixed binary 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 eb_mul_fix_yaowi(eb_t r, const eb_t *t, const bn_t k); + +/** + * Multiplies a fixed binary 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 eb_mul_fix_nafwi(eb_t r, const eb_t *t, const bn_t k); + +/** + * Multiplies a fixed binary 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 eb_mul_fix_combs(eb_t r, const eb_t *t, const bn_t k); + +/** + * Multiplies a fixed binary 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 eb_mul_fix_combd(eb_t r, const eb_t *t, const bn_t k); + +/** + * Multiplies a fixed binary 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 eb_mul_fix_lwnaf(eb_t r, const eb_t *t, const bn_t k); + +/** + * Multiplies and adds two binary 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 eb_mul_sim_basic(eb_t r, const eb_t p, const bn_t k, const eb_t q, + const bn_t m); + +/** + * Multiplies and adds two binary 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 eb_mul_sim_trick(eb_t r, const eb_t p, const bn_t k, const eb_t q, + const bn_t m); + +/** + * Multiplies and adds two binary 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 eb_mul_sim_inter(eb_t r, const eb_t p, const bn_t k, const eb_t q, + const bn_t m); + +/** + * Multiplies and adds two binary 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 eb_mul_sim_joint(eb_t r, const eb_t p, const bn_t k, const eb_t q, + const bn_t m); + +/** + * Multiplies and adds the generator and a binary elliptic curve point + * simultaneously. Computes R = kG + mQ. + * + * @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 eb_mul_sim_gen(eb_t r, const bn_t k, const eb_t q, const bn_t m); + +/** + * Converts a point to affine coordinates. + * + * @param[out] r - the result. + * @param[in] p - the point to convert. + */ +void eb_norm(eb_t r, const eb_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 eb_norm_sim(eb_t *r, const eb_t *t, int n); + +/** + * Maps a byte array to a point in a binary elliptic curve. + * + * @param[out] p - the result. + * @param[in] msg - the byte array to map. + * @param[in] len - the array length in bytes. + */ +void eb_map(eb_t p, const uint8_t *msg, int len); + +/** + * Compresses a point. + * + * @param[out] r - the result. + * @param[in] p - the point to compress. + */ +void eb_pck(eb_t r, const eb_t p); + +/** + * Decompresses a point. + * + * @param[out] r - the result. + * @param[in] p - the point to decompress. + * @return if the decompression was successful + */ +int eb_upk(eb_t r, const eb_t p); + +#endif /* !RLC_EB_H */ diff --git a/bls/contrib/relic/include/relic_ec.h b/bls/contrib/relic/include/relic_ec.h new file mode 100644 index 00000000..7ab33680 --- /dev/null +++ b/bls/contrib/relic/include/relic_ec.h @@ -0,0 +1,455 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 . + */ + +/** + * @defgroup ec Elliptic curve cryptography + */ + +/** + * @file + * + * Abstractions of elliptic curve arithmetic useful to protocol implementors. + * + * @ingroup ec + */ + +#ifndef RLC_EC_H +#define RLC_EC_H + +#include "relic_ep.h" +#include "relic_eb.h" +#include "relic_ed.h" +#include "relic_bn.h" +#include "relic_util.h" +#include "relic_conf.h" +#include "relic_types.h" + +/*============================================================================*/ +/* Constant definitions */ +/*============================================================================*/ + +/** + * Prefix for mappings of functions. + */ +#if EC_CUR == PRIME +#define EC_LOWER ep_ +#elif EC_CUR == CHAR2 +#define EC_LOWER eb_ +#elif EC_CUR == EDDIE +#define EC_LOWER ed_ +#endif + +/** + * Prefix for mappings of constant definitions. + */ +#if EC_CUR == PRIME +#define EC_UPPER EP_ +#elif EC_CUR == CHAR2 +#define EC_UPPER EB_ +#elif EC_CUR == EDDIE +#define EC_UPPER ED_ +#endif + +/** + * Size of a precomputation table using the chosen algorithm. + */ +#if EC_CUR == PRIME +#define RLC_EC_TABLE RLC_EP_TABLE +#elif EC_CUR == CHAR2 +#define RLC_EC_TABLE RLC_EB_TABLE +#elif EC_CUR == EDDIE +#define RLC_EC_TABLE RLC_ED_TABLE +#endif + +/** + * Size of a field element in words. + */ +#if EC_CUR == PRIME +#define RLC_FC_DIGS RLC_FP_DIGS +#elif EC_CUR == CHAR2 +#define RLC_FC_DIGS RLC_FB_DIGS +#elif EC_CUR == EDDIE +#define RLC_FC_DIGS RLC_FP_DIGS +#endif + +/** + * Size of a field element in bits. + */ +#if EC_CUR == PRIME +#define RLC_FC_BITS RLC_FP_BITS +#elif EC_CUR == CHAR2 +#define RLC_FC_BITS RLC_FB_BITS +#elif EC_CUR == EDDIE +#define RLC_FC_BITS RLC_FP_BITS +#endif + +/** + * Size of a field element in bytes. + */ +#if EC_CUR == PRIME +#define RLC_FC_BYTES RLC_FP_BYTES +#elif EC_CUR == CHAR2 +#define RLC_FC_BYTES RLC_FB_BYTES +#elif EC_CUR == EDDIE +#define RLC_FC_BYTES RLC_FP_BYTES +#endif + +/*============================================================================*/ +/* Type definitions */ +/*============================================================================*/ + +/** + * Represents an elliptic curve point. + */ +typedef RLC_CAT(EC_LOWER, t) ec_t; + +/*============================================================================*/ +/* Macro definitions */ +/*============================================================================*/ + +/** + * Initializes a point on an elliptic curve with a null value. + * + * @param[out] A - the point to initialize. + */ +#define ec_null(A) RLC_CAT(EC_LOWER, 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. + */ +#define ec_new(A) RLC_CAT(EC_LOWER, new)(A) + +/** + * Calls a function to clean and free a point on an elliptic curve. + * + * @param[out] A - the point to clean and free. + */ +#define ec_free(A) RLC_CAT(EC_LOWER, free)(A) + +/** + * Returns the generator of the group of points in the elliptic curve. + * + * @param[out] G - the returned generator. + */ +#define ec_curve_get_gen(G) RLC_CAT(EC_LOWER, curve_get_gen)(G) + +/** + * Returns the precomputation table for the generator. + * + * @return the table. + */ +#define ec_curve_get_tab() RLC_CAT(EC_LOWER, curve_get_tab)() + +/** + * Returns the order of the group of points in the elliptic curve. + * + * @param[out] N - the returned order. + */ +#define ec_curve_get_ord(N) RLC_CAT(EC_LOWER, curve_get_ord)(N) + +/** + * Returns the cofactor of the group of points in the elliptic curve. + * + * @param[out] H - the returned order. + */ +#define ec_curve_get_cof(H) RLC_CAT(EC_LOWER, curve_get_cof)(H) + +/** + * Configures some set of curve parameters for the current security level. + */ +#if EC_CUR == PRIME +#if defined(EC_ENDOM) +#define ec_param_set_any() ep_param_set_any_endom() +#else +#define ec_param_set_any() ep_param_set_any() +#endif +#elif EC_CUR == CHAR2 +#if defined(EC_ENDOM) +#define ec_param_set_any() eb_param_set_any_kbltz() +#else +#define ec_param_set_any() eb_param_set_any() +#endif +#elif EC_CUR == EDDIE +#define ec_param_set_any() ed_param_set_any() +#endif + +/** + * Prints the current configured elliptic curve. + */ +#define ec_param_print() RLC_CAT(EC_LOWER, param_print)() + + /** + * Returns the current configured elliptic curve. + */ +#define ec_param_get() RLC_CAT(EC_LOWER, param_get)() + +/** + * Returns the current security level. + */ +#define ec_param_level() RLC_CAT(EC_LOWER, param_level)() + +/** + * Tests if a point on a elliptic curve is at the infinity. + * + * @param[in] P - the point to test. + * @return 1 if the point is at infinity, 0 otherwise. + */ +#define ec_is_infty(P) RLC_CAT(EC_LOWER, is_infty)(P) + +/** + * Assigns a elliptic curve point to a point at the infinity. + * + * @param[out] P - the point to assign. + */ +#define ec_set_infty(P) RLC_CAT(EC_LOWER, set_infty)(P) + +/** + * Copies the second argument to the first argument. + * + * @param[out] R - the result. + * @param[in] P - the elliptic curve point to copy. + */ +#define ec_copy(R, P) RLC_CAT(EC_LOWER, copy)(R, 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. + */ +#define ec_cmp(P, Q) RLC_CAT(EC_LOWER, cmp)(P, Q) + +/** + * Assigns a random value to a elliptic curve point. + * + * @param[out] P - the elliptic curve point to assign. + */ +#define ec_rand(P) RLC_CAT(EC_LOWER, rand)(P) + +/** Tests if a point is in the curve. + * + * @param[in] P - the point to test. + */ +#define ec_is_valid(P) RLC_CAT(EC_LOWER, is_valid)(P) + +/** + * Returns the number of bytes necessary to store an elliptic curve point with + * optional point compression. + * + * @param[in] A - the elliptic curve point. + * @param[in] P - the flag to indicate compression. + */ +#define ec_size_bin(A, P) RLC_CAT(EC_LOWER, size_bin)(A, P) + +/** + * Reads an elliptic curve point from a byte vector in big-endian format. + * + * @param[out] A - the result. + * @param[in] B - the byte vector. + * @param[in] L - the buffer capacity. + */ +#define ec_read_bin(A, B, L) RLC_CAT(EC_LOWER, read_bin)(A, B, L) + +/** + * Writes an elliptic curve point to a byte vector in big-endian format with + * optional point compression. + * + * @param[out] B - the byte vector. + * @param[in] L - the buffer capacity. + * @param[in] A - the prime elliptic curve point to write. + * @param[in] P - the flag to indicate point compression. + */ +#define ec_write_bin(B, L, A, P) RLC_CAT(EC_LOWER, write_bin)(B, L, A, P) + +/** + * Prints a elliptic curve point. + * + * @param[in] P - the elliptic curve point to print. + */ +#define ec_print(P) RLC_CAT(EC_LOWER, print)(P) + +/** + * Negates an elliptic curve point. Computes R = -P. + * + * @param[out] R - the result. + * @param[in] P - the point to negate. + */ +#define ec_neg(R, P) RLC_CAT(EC_LOWER, neg)(R, P) + +/** + * Adds two elliptic curve points. 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. + */ +#define ec_add(R, P, Q) RLC_CAT(EC_LOWER, add)(R, P, Q) + +/** + * Subtracts an elliptic curve point from another. Computes R = P - Q. + * + * @param[out] R - the result. + * @param[in] P - the first point. + * @param[in] Q - the second point. + */ +#define ec_sub(R, P, Q) RLC_CAT(EC_LOWER, sub)(R, P, Q) + +/** + * Doubles an elliptic curve point. Computes R = 2P. + * + * @param[out] R - the result. + * @param[in] P - the point to double. + */ +#define ec_dbl(R, P) RLC_CAT(EC_LOWER, dbl)(R, P) + +/** + * Multiplies an elliptic curve point by an integer. Computes R = kP. + * + * @param[out] R - the result. + * @param[in] P - the point to multiply. + * @param[in] K - the integer. + */ +#define ec_mul(R, P, K) RLC_CAT(EC_LOWER, mul)(R, P, K) + +/** + * Multiplies the generator of a prime elliptic curve by an integer. + * + * @param[out] R - the result. + * @param[in] K - the integer. + */ +#define ec_mul_gen(R, K) RLC_CAT(EC_LOWER, mul_gen)(R, K) + +/** + * Multiplies an elliptic curve point by a small integer. Computes R = kP. + * + * @param[out] R - the result. + * @param[in] P - the point to multiply. + * @param[in] K - the integer. + */ +#define ec_mul_dig(R, P, K) RLC_CAT(EC_LOWER, mul_dig)(R, P, K) + +/** + * Builds a precomputation table for multiplying a fixed elliptic curve + * point. + * + * @param[out] T - the precomputation table. + * @param[in] P - the point to multiply. + */ +#define ec_mul_pre(T, P) RLC_CAT(EC_LOWER, mul_pre)(T, P) +/** + * Multiplies a elliptic point using a precomputation table. + * Computes R = kP. + * + * @param[out] R - the result. + * @param[in] T - the precomputation table. + * @param[in] K - the integer. + */ +#define ec_mul_fix(R, T, K) RLC_CAT(EC_LOWER, mul_fix)(R, T, K) + +/** + * Multiplies and adds two elliptic curve points simultaneously. Computes + * R = kP + lQ. + * + * @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] L - the second integer, + */ +#define ec_mul_sim(R, P, K, Q, L) RLC_CAT(EC_LOWER, mul_sim)(R, P, K, Q, L) + +/** + * Multiplies and adds two elliptic curve points simultaneously. Computes + * R = kG + lQ. + * + * @param[out] R - the result. + * @param[in] K - the first integer. + * @param[in] Q - the second point to multiply. + * @param[in] L - the second integer, + */ +#define ec_mul_sim_gen(R, K, Q, L) RLC_CAT(EC_LOWER, mul_sim_gen)(R, K, Q, L) + +/** + * Converts a point to affine coordinates. + * + * @param[out] R - the result. + * @param[in] P - the point to convert. + */ +#define ec_norm(R, P) RLC_CAT(EC_LOWER, norm)(R, P) + +/** + * Maps a byte array to a point in an elliptic curve. + * + * @param[out] P - the result. + * @param[in] M - the byte array to map. + * @param[in] L - the array length in bytes. + */ +#define ec_map(P, M, L) RLC_CAT(EC_LOWER, map)(P, M, L) + +/** + * Compresses a point. + * + * @param[out] R - the result. + * @param[in] P - the point to compress. + */ +#define ec_pck(R, P) RLC_CAT(EC_LOWER, pck)(R, P) + +/** + * Decompresses a point. + * + * @param[out] R - the result. + * @param[in] P - the point to decompress. + */ +#define ec_upk(R, P) RLC_CAT(EC_LOWER, upk)(R, P) + +/** + * Returns the x-coordinate of an elliptic curve point represented as a + * multiple precision integer. + * + * @param[out] X - the x-coordinate. + * @param[in] P - the point to read. + */ +#if EC_CUR == PRIME || EC_CUR == EDDIE +#define ec_get_x(X, P) fp_prime_back(X, P->x) +#else +#define ec_get_x(X, P) bn_read_raw(X, P->x, RLC_FC_DIGS) +#endif + +/** +* Returns the y-coordinate of an elliptic curve point represented as a +* multiple precision integer. +* +* @param[out] Y - the y-coordinate. +* @param[in] P - the point to read. +*/ +#if EC_CUR == PRIME || EC_CUR == EDDIE +#define ec_get_y(Y, P) fp_prime_back(Y, (P)->y) +#else +#define ec_get_y(Y, P) bn_read_raw(Y, (P)->y, RLC_FC_DIGS) +#endif + +#endif /* !RLC_EC_H */ diff --git a/bls/contrib/relic/include/relic_ed.h b/bls/contrib/relic/include/relic_ed.h new file mode 100644 index 00000000..97bf0f36 --- /dev/null +++ b/bls/contrib/relic/include/relic_ed.h @@ -0,0 +1,894 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 . + */ + +/** + * @defgroup ed Edwards curves over prime fields. + */ + +/** + * @file + * + * Interface of the module for arithmetic on elliptic curves. + * + * @ingroup ed + */ + + #ifndef RLC_ED_H + #define RLC_ED_H + +#include "relic_fp.h" +#include "relic_bn.h" +#include "relic_types.h" +#include "relic_label.h" + +/*============================================================================*/ +/* Constant definitions */ +/*============================================================================*/ + +/** + * Prime elliptic curve identifiers. + */ +enum { + /** ED25519 Edwards curve. */ + CURVE_ED25519 = 1 +}; + +/*============================================================================*/ +/* Precomputaion table */ +/*============================================================================*/ +/** + * Size of a precomputation table using the binary method. + */ +#define RLC_ED_TABLE_BASIC (RLC_FP_BITS + 1) + +/** + * Size of a precomputation table using the single-table comb method. + */ +#define RLC_ED_TABLE_COMBS (1 << ED_DEPTH) + +/** + * Size of a precomputation table using the double-table comb method. + */ +#define RLC_ED_TABLE_COMBD (1 << (ED_DEPTH + 1)) + +/** + * Size of a precomputation table using the w-(T)NAF method. + */ +#define RLC_ED_TABLE_LWNAF (1 << (ED_DEPTH - 2)) + +/** + * Size of a precomputation table using the chosen algorithm. + */ +#if ED_FIX == 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 +#define RLC_ED_TABLE RLC_ED_TABLE_COMBD +#elif ED_FIX == LWNAF +#define RLC_ED_TABLE RLC_ED_TABLE_LWNAF +#endif + +/** + * Maximum size of a precomputation table. + */ +#ifdef STRIP +#define RLC_ED_TABLE_MAX RLC_ED_TABLE +#else +#define RLC_ED_TABLE_MAX RLC_MAX(RLC_ED_TABLE_BASIC, RLC_ED_TABLE_COMBD) +#endif + +/*============================================================================*/ +/* Type definitions */ +/*============================================================================*/ + +/** + * Represents an elliptic curve point over an Edwards field. + */ +typedef struct { + /** The first coordinate. */ + fp_st x; + /** The second coordinate. */ + fp_st y; + /** The third coordinate (projective representation). */ + fp_st z; +#if ED_ADD == EXTND || !defined(STRIP) + /** The forth coordinate (extended coordinates) */ + fp_st t; +#endif + /** Flag to indicate that this point is normalized. */ + int norm; +} ed_st; + +/** + * Pointer to an elliptic curve point. + */ +#if ALLOC == AUTO +typedef ed_st ed_t[1]; +#else +typedef ed_st *ed_t; +#endif + +/*============================================================================*/ +/* Macro definitions */ +/*============================================================================*/ + +/** + * Initializes a point on an Edwards curve with a null value. + * + * @param[out] A - the point to initialize. + */ +#if ALLOC == AUTO +#define ed_null(A) /* empty */ +#else +#define ed_null(A) A = NULL; +#endif + +/** + * Calls a function to allocate a point on an Edwards curve. + * + * @param[out] A - the new point. + * @throw ERR_NO_MEMORY - if there is no available memory. + */ +#if ALLOC == DYNAMIC +#define ed_new(A) \ + A = (ed_t)calloc(1, sizeof(ed_st)); \ + if (A == NULL) { \ + THROW(ERR_NO_MEMORY); \ + } + +#elif ALLOC == AUTO +#define ed_new(A) /* empty */ + +#elif ALLOC == STACK +#define ed_new(A) \ + A = (ed_t)alloca(sizeof(ed_st)); \ + +#endif + +/** + * Calls a function to clean and free a point on an Edwards curve. + * + * @param[out] A - the point to free. + */ +#if ALLOC == DYNAMIC +#define ed_free(A) \ + if (A != NULL) { \ + free(A); \ + A = NULL; \ + } + +#elif ALLOC == AUTO +#define ed_free(A) /* empty */ + +#elif ALLOC == STACK +#define ed_free(A) \ + A = NULL; \ + +#endif + +/** + * Negates an Edwards elliptic curve point. Computes R = -P. + * + * @param[out] R - the result. + * @param[in] P - the point to negate. + */ +#if ED_ADD == BASIC +#define ed_neg(R, P) ed_neg_basic(R, P) +#elif ED_ADD == PROJC || ED_ADD == EXTND +#define ed_neg(R, P) ed_neg_projc(R, P) +#endif + +/** + * Adds two Edwards elliptic curve points. 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 ED_ADD == BASIC +#define ed_add(R, P, Q) ed_add_basic(R, P, Q) +#elif ED_ADD == PROJC +#define ed_add(R, P, Q) ed_add_projc(R, P, Q) +#elif ED_ADD == EXTND +#define ed_add(R, P, Q) ed_add_extnd(R, P, Q) +#endif + +/** + * Subtracts an Edwards elliptic curve point from another. Computes R = P - Q. + * + * @param[out] R - the result. + * @param[in] P - the first point. + * @param[in] Q - the second point. + */ +#if ED_ADD == BASIC +#define ed_sub(R, P, Q) ed_sub_basic(R, P, Q) +#elif ED_ADD == PROJC +#define ed_sub(R, P, Q) ed_sub_projc(R, P, Q) +#elif ED_ADD == EXTND +#define ed_sub(R, P, Q) ed_sub_extnd(R, P, Q) +#endif + +/** + * Doubles an Edwards elliptic curve point. Computes R = 2P. + * + * @param[out] R - the result. + * @param[in] P - the point to double. + */ +#if ED_ADD == BASIC +#define ed_dbl(R, P) ed_dbl_basic(R, P) +#elif ED_ADD == PROJC +#define ed_dbl(R, P) ed_dbl_projc(R, P) +#elif ED_ADD == EXTND +#define ed_dbl(R, P) ed_dbl_extnd(R, P) +#endif + + +/** + * Configures an Edwards curve by its parameter identifier. + * + * @param - the parameter identifier. + */ +void ed_param_set(int param); + +/** + * Configures some set of curve parameters for the current security level. + */ +int ed_param_set_any(void); + +/** + * Returns the parameter identifier of the currently configured Edwards elliptic + * curve. + * + * @return the parameter identifier. + */ +int ed_param_get(void); + +/** + * Returns the order of the group of points in the Edwards curve. + * + * @param[out] r - the returned order. + */ +void ed_curve_get_ord(bn_t r); + +/** + * Returns the generator of the group of points in the curve. + * + * @param[out] g - the returned generator. + */ +void ed_curve_get_gen(ed_t g); + +/** + * Returns the precomputation table for the generator. + * + * @return the table. + */ +const ed_t *ed_curve_get_tab(void); + +/** + * Returns the cofactor of the Edwards elliptic curve. + * + * @param[out] n - the returned cofactor. + */ +void ed_curve_get_cof(bn_t h); + +/** + * Prints the current configured Edwards elliptic curve. + */ +void ed_param_print(void); + +/** + * Returns the current security level. + */ +int ed_param_level(void); + +#if ED_ADD == EXTND +/** + * Converts projective point into extended point. + */ +void ed_projc_to_extnd(ed_t r, const fp_t x, const fp_t y, const fp_t z); +#endif + +/** + * Assigns a random value to an Edwards elliptic curve point. + * + * @param[out] p - the Edwards elliptic curve point to assign. + */ +void ed_rand(ed_t p); + +/** + * Computes the right-hand side of the elliptic curve equation at a certain + * Edwards elliptic curve point. + * + * @param[out] rhs - the result. + * @param[in] p - the point. + */ +void ed_rhs(fp_t rhs, const ed_t p); + +/** + * Copies the second argument to the first argument. + * + * @param[out] q - the result. + * @param[in] p - the Edwards elliptic curve point to copy. + */ +void ed_copy(ed_t r, const ed_t p); + +/** + * Compares two Edwards elliptic curve points. + * + * @param[in] p - the first Edwards elliptic curve point. + * @param[in] q - the second Edwards elliptic curve point. + * @return RLC_EQ if p == q and RLC_NE if p != q. + */ +int ed_cmp(const ed_t p, const ed_t q); + +/** + * Assigns an Edwards elliptic curve point to a point at the infinity. + * + * @param[out] p - the point to assign. + */ +void ed_set_infty(ed_t p); + +/** + * Tests if a point on an Edwards elliptic curve is at the infinity. + * + * @param[in] p - the point to test. + * @return 1 if the point is at infinity, 0 otherise. + */ +int ed_is_infty(const ed_t p); + +/** + * Negates an Edwards elliptic curve point represented by affine coordinates. + * + * @param[out] r - the result. + * @param[in] p - the point to negate. + */ +void ed_neg_basic(ed_t r, const ed_t p); + +/** + * Negates an Edwards elliptic curve point represented by projective coordinates. + * + * @param[out] r - the result. + * @param[in] p - the point to negate. + */ +void ed_neg_projc(ed_t r, const ed_t p); + +/** + * Adds two Edwards elliptic curve points represented in affine coordinates. + * + * @param[out] r - the result. + * @param[in] p - the first point to add. + * @param[in] q - the second point to add. + */ +void ed_add_basic(ed_t r, const ed_t p, const ed_t q); + +/** + * Adds two Edwards elliptic curve points represented in projective coordinates. + * + * @param[out] r - the result. + * @param[in] p - the first point to add. + * @param[in] q - the second point to add. + */ +void ed_add_projc(ed_t r, const ed_t p, const ed_t q); + +/** + * Adds two Edwards elliptic curve points represented in exteded coordinates. + * + * @param[out] r - the result. + * @param[in] p - the first point to add. + * @param[in] q - the second point to add. + */ +void ed_add_extnd(ed_t r, const ed_t p, const ed_t q); + +/** + * Subtracts an Edwards elliptic curve point from another, both points represented + * by affine coordinates.. + * + * @param[out] r - the result. + * @param[in] p - the first point. + * @param[in] q - the second point. + */ +void ed_sub_basic(ed_t r, const ed_t p, const ed_t q); + +/** + * Subtracts an Edwards elliptic curve point from another, both represented + * by projective coordinates. + * + * @param[out] r - the result. + * @param[in] p - the first point. + * @param[in] q - the second point. + */ +void ed_sub_projc(ed_t r, const ed_t p, const ed_t q); + +/** + * Subtracts an Edwards elliptic curve point from another, both represented + * by extended coordinates. + * + * @param[out] r - the result. + * @param[in] p - the first point. + * @param[in] q - the second point. + */ +void ed_sub_extnd(ed_t r, const ed_t p, const ed_t q); + +/** + * Doubles an Edwards elliptic curve point represented in affine coordinates. + * + * @param[out] r - the result. + * @param[in] p - the point to double. + */ +void ed_dbl_basic(ed_t r, const ed_t p); + +/** + * Doubles an Edwards elliptic curve point represented in projective coordinates. + * + * @param[out] r - the result. + * @param[in] p - the point to double. + */ +void ed_dbl_projc(ed_t r, const ed_t p); + +/** + * Doubles an Edwards elliptic curve point represented in extended coordinates. + * + * @param[out] r - the result. + * @param[in] p - the point to double. + */ +void ed_dbl_extnd(ed_t r, const ed_t p); + +/** + * Converts a point to affine coordinates. + * + * @param[out] r - the result. + * @param[in] p - the point to convert. + */ +void ed_norm(ed_t r, const ed_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 ed_norm_sim(ed_t *r, const ed_t *t, int n); + +/** + * Maps a byte array to a point in an Edwards elliptic curve. + * + * @param[out] p - the result. + * @param[in] msg - the byte array to map. + * @param[in] len - the array length in bytes. + */ +void ed_map(ed_t p, const uint8_t *msg, int len); + +/** + * Multiplies an Edwards elliptic curve point by an integer. Computes R = kP. + * + * @param[out] R - the result. + * @param[in] P - the point to multiply. + * @param[in] K - the integer. + */ +#if ED_MUL == BASIC +#define ed_mul(R, P, K) ed_mul_basic(R, P, K) +#elif ED_MUL == SLIDE +#define ed_mul(R, P, K) ed_mul_slide(R, P, K) +#elif ED_MUL == MONTY +#define ed_mul(R, P, K) ed_mul_monty(R, P, K) +#elif ED_MUL == LWNAF +#define ed_mul(R, P, K) ed_mul_lwnaf(R, P, K) +#elif ED_MUL == LWREG +#define ed_mul(R, P, K) ed_mul_lwreg(R, P, K) +#endif + +/** + * Builds a precomputation table for multiplying a fixed Edwards elliptic point. + * + * @param[out] T - the precomputation table. + * @param[in] P - the point to multiply. + */ +#if ED_FIX == BASIC +#define ed_mul_pre(T, P) ed_mul_pre_basic(T, P) +#elif ED_FIX == COMBS +#define ed_mul_pre(T, P) ed_mul_pre_combs(T, P) +#elif ED_FIX == COMBD +#define ed_mul_pre(T, P) ed_mul_pre_combd(T, P) +#elif ED_FIX == LWNAF +#define ed_mul_pre(T, P) ed_mul_pre_lwnaf(T, P) +#endif + +/** + * Multiplies a fixed Edwards elliptic point using a precomputation table. + * Computes R = kP. + * + * @param[out] R - the result. + * @param[in] T - the precomputation table. + * @param[in] K - the integer. + */ +#if ED_FIX == BASIC +#define ed_mul_fix(R, T, K) ed_mul_fix_basic(R, T, K) +#elif ED_FIX == COMBS +#define ed_mul_fix(R, T, K) ed_mul_fix_combs(R, T, K) +#elif ED_FIX == COMBD +#define ed_mul_fix(R, T, K) ed_mul_fix_combd(R, T, K) +#elif ED_FIX == LWNAF +#define ed_mul_fix(R, T, K) ed_mul_fix_lwnaf(R, T, K) +#endif + + /** + * Multiplies and adds two Edwards elliptic curve points simultaneously. Computes + * R = kP + mQ. + * + * @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 ED_SIM == BASIC +#define ed_mul_sim(R, P, K, Q, M) ed_mul_sim_basic(R, P, K, Q, M) +#elif ED_SIM == TRICK +#define ed_mul_sim(R, P, K, Q, M) ed_mul_sim_trick(R, P, K, Q, M) +#elif ED_SIM == INTER +#define ed_mul_sim(R, P, K, Q, M) ed_mul_sim_inter(R, P, K, Q, M) +#elif ED_SIM == JOINT +#define ed_mul_sim(R, P, K, Q, M) ed_mul_sim_joint(R, P, K, Q, M) +#endif + +/*============================================================================*/ +/* Function prototypes */ +/*============================================================================*/ + +/** + * Initializes the Edwards elliptic curve arithmetic module. + */ +void ed_curve_init(void); + +/** + * Finalizes the Edwards elliptic curve arithmetic module. + */ +void ed_curve_clean(void); + +/** + * Builds a precomputation table for multiplying a fixed Edwards elliptic point + * using the binary method. + * + * @param[out] t - the precomputation table. + * @param[in] p - the point to multiply. + */ +void ed_mul_pre_basic(ed_t *t, const ed_t p); + +/** + * Builds a precomputation table for multiplying a fixed Edwards elliptic point + * using Yao's windowing method. + * + * @param[out] t - the precomputation table. + * @param[in] p - the point to multiply. + */ +void ed_mul_pre_yaowi(ed_t *t, const ed_t p); + +/** + * Builds a precomputation table for multiplying a fixed Edwards elliptic point + * using the NAF windowing method. + * + * @param[out] t - the precomputation table. + * @param[in] p - the point to multiply. + */ +void ed_mul_pre_nafwi(ed_t *t, const ed_t p); + +/** + * Builds a precomputation table for multiplying a fixed Edwards elliptic point + * using the single-table comb method. + * + * @param[out] t - the precomputation table. + * @param[in] p - the point to multiply. + */ +void ed_mul_pre_combs(ed_t *t, const ed_t p); + +/** + * Builds a precomputation table for multiplying a fixed Edwards elliptic point + * using the double-table comb method. + * + * @param[out] t - the precomputation table. + * @param[in] p - the point to multiply. + */ +void ed_mul_pre_combd(ed_t *t, const ed_t p); + +/** + * Builds a precomputation table for multiplying a fixed Edwards elliptic point + * using the w-(T)NAF method. + * + * @param[out] t - the precomputation table. + * @param[in] p - the point to multiply. + */ +void ed_mul_pre_lwnaf(ed_t *t, const ed_t p); + +/** + * Multiplies a fixed Edwards 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 ed_mul_fix_basic(ed_t r, const ed_t *t, const bn_t k); + +/** + * Multiplies a fixed Edwards 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 ed_mul_fix_yaowi(ed_t r, const ed_t *t, const bn_t k); + +/** + * Multiplies a fixed Edwards 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 ed_mul_fix_nafwi(ed_t r, const ed_t *t, const bn_t k); + +/** + * Multiplies a fixed Edwards 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 ed_mul_fix_combs(ed_t r, const ed_t *t, const bn_t k); + +/** + * Multiplies a fixed Edwards 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 ed_mul_fix_combd(ed_t r, const ed_t *t, const bn_t k); + +/** + * Multiplies a fixed Edwards 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 ed_mul_fix_lwnaf(ed_t r, const ed_t *t, const bn_t k); + +/** + * Multiplies a fixed Edwards elliptic point using a precomputation table and + * the w-(T)NAF mixed coordinate method. + * + * @param[out] r - the result. + * @param[in] t - the precomputation table. + * @param[in] k - the integer. + */ +void ed_mul_fix_lwnaf_mixed(ed_t r, const ed_t *t, const bn_t k); + +/** + * Multiplies the generator of an Edwards elliptic curve by an integer. + * + * @param[out] r - the result. + * @param[in] k - the integer. + */ +void ed_mul_gen(ed_t r, const bn_t k); + +/** + * Multiplies an Edwards elliptic curve point by a small positive integer. + * + * @param[out] r - the result. + * @param[in] p - the point to multiply. + * @param[in] k - the integer. + */ +void ed_mul_dig(ed_t r, const ed_t p, dig_t k); + +/** + * Multiplies and adds two Edwards 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 ed_mul_sim_basic(ed_t r, const ed_t p, const bn_t k, const ed_t q, + const bn_t m); + +/** + * Multiplies and adds two Edwards 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 ed_mul_sim_trick(ed_t r, const ed_t p, const bn_t k, const ed_t q, + const bn_t m); + +/** + * Multiplies and adds two Edwards 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 ed_mul_sim_inter(ed_t r, const ed_t p, const bn_t k, const ed_t q, + const bn_t m); + +/** + * Multiplies and adds two Edwards 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 ed_mul_sim_joint(ed_t r, const ed_t p, const bn_t k, const ed_t q, + const bn_t m); + +/** + * Multiplies and adds the generator and an Edwards elliptic curve point + * simultaneously. Computes R = kG + mQ. + * + * @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 ed_mul_sim_gen(ed_t r, const bn_t k, const ed_t q, const bn_t m); + +/** + * Builds a precomputation table for multiplying a random Edwards elliptic point. + * + * @param[out] t - the precomputation table. + * @param[in] p - the point to multiply. + * @param[in] w - the window width. + */ +void ed_tab(ed_t *t, const ed_t p, int w); + +/** + * Prints an Edwards elliptic curve point. + * + * @param[in] p - the Edwards elliptic curve point to print. + */ +void ed_print(const ed_t p); + +/** + * Tests if a point is in the curve. + * + * @param[in] p - the point to test. + */ +int ed_is_valid(const ed_t p); + +/** + * Returns the number of bytes necessary to store an Edwards elliptic curve point + * with optional point compression. + * + * @param[in] a - the Edwards field element. + * @param[in] pack - the flag to indicate compression. + * @return the number of bytes. + */ +int ed_size_bin(const ed_t a, int pack); + +/** + * Reads an Edwards elliptic curve point 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 ed_read_bin(ed_t a, const uint8_t *bin, int len); + +/** + * Writes an Edwards elliptic curve point 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 Edwards elliptic curve point to write. + * @param[in] pack - the flag to indicate point compression. + * @throw ERR_NO_BUFFER - if the buffer capacity is invalid. + */ +void ed_write_bin(uint8_t *bin, int len, const ed_t a, int pack); + +/** + * Multiplies an Edwards 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 ed_mul_basic(ed_t r, const ed_t p, const bn_t k); + +/** + * Multiplies an Edwards 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 ed_mul_slide(ed_t r, const ed_t p, const bn_t k); + +/** + * Multiplies an Edwards elliptic point by an integer using the constant-time + * Montgomery laddering point multiplication method. + * + * @param[out] r - the result. + * @param[in] p - the point to multiply. + * @param[in] k - the integer. + */ +void ed_mul_monty(ed_t r, const ed_t p, const bn_t k); + +/** + * Multiplies an Edwards 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 ed_mul_lwnaf(ed_t r, const ed_t p, const bn_t k); + +/** + * Multiplies an Edwards 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 ed_mul_lwreg(ed_t r, const ed_t p, const bn_t k); + +/** + * Compresses a point. + * + * @param[out] r - the result. + * @param[in] p - the point to compress. + */ +void ed_pck(ed_t r, const ed_t p); + +/** + * Decompresses a point. + * + * @param[out] r - the result. + * @param[in] p - the point to decompress. + * @return if the decompression was successful + */ +int ed_upk(ed_t r, const ed_t p); + +#endif diff --git a/bls/contrib/relic/include/relic_ep.h b/bls/contrib/relic/include/relic_ep.h new file mode 100644 index 00000000..4ff6ad27 --- /dev/null +++ b/bls/contrib/relic/include/relic_ep.h @@ -0,0 +1,1185 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 . + */ + +/** + * @defgroup ep Elliptic curves over prime fields + */ + +/** + * @file + * + * Interface of the module for arithmetic on prime elliptic curves. + * + * @ingroup ep + */ + +#ifndef RLC_EP_H +#define RLC_EP_H + +#include "relic_fp.h" +#include "relic_bn.h" +#include "relic_types.h" +#include "relic_label.h" + +/*============================================================================*/ +/* Constant definitions */ +/*============================================================================*/ + +/** + * Prime elliptic curve identifiers. + */ +enum { + /** SECG P-160 prime curve. */ + SECG_P160 = 1, + /** SECG K-160 prime curve. */ + SECG_K160, + /** NIST P-192 prime curve. */ + NIST_P192, + /** SECG K-192 prime curve. */ + SECG_K192, + /** Curve22103 prime curve. */ + CURVE_22103, + /** NIST P-224 prime curve. */ + NIST_P224, + /** SECG K-224 prime curve. */ + SECG_K224, + /** Curve4417 prime curve. */ + CURVE_4417, + /** Curve1147 prime curve. */ + CURVE_1174, + /** Curve25519 prime curve. */ + CURVE_25519, + /** NIST P-256 prime curve. */ + NIST_P256, + /** Brainpool P256r1 curve. */ + BSI_P256, + /** SECG K-256 prime curve. */ + SECG_K256, + /** Curve67254 prime curve. */ + CURVE_67254, + /** Curve383187 prime curve. */ + CURVE_383187, + /** NIST P-384 prime curve. */ + NIST_P384, + /** Curve 511187 prime curve. */ + CURVE_511187, + /** NIST P-521 prime curve. */ + NIST_P521, + /** Barreto-Naehrig curve with positive x */ + BN_P158, + /** Barreto-Naehrig curve with negative x (found by Nogami et al.). */ + BN_P254, + /** Barreto-Naehrig curve with negative x. */ + BN_P256, + /** Barreto-Lynn-Scott curve with embedding degree 12 (ZCash curve). */ + B12_P381, + /** Barreto-Naehrig curve with negative x. */ + BN_P382, + /** 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, + /** Optimal TNFS-secure curve with embedding degree 8. */ + OT8_P511, + /** Cocks-pinch curve with embedding degree 8. */ + CP8_P544, + /** Kachisa-Scott-Schaefer curve with embedding degree 54. */ + K54_P569, + /** Barreto-Lynn-Scott curve with embedding degree 48. */ + B48_P575, + /** Barreto-Naehrig curve with positive x. */ + BN_P638, + /** Barreto-Lynn-Scott curve with embedding degree 12. */ + B12_P638, + /** 1536-bit supersingular curve. */ + SS_P1536, +}; + +/** + * Pairing-friendly elliptic curve identifiers. + */ +enum { + /** Supersingular curves with embedding degree 2. */ + EP_SS2 = 1, + /** Barreto-Naehrig. */ + EP_BN, + /* Optimal TNFS-secure. */ + EP_OT8, + /* Cocks-Pinch curve. */ + EP_CP8, + /* Barreto-Lynn-Scott with embedding degree 12. */ + EP_B12, + /* Kachisa-Schafer-Scott with embedding degree 16. */ + EP_K16, + /* Barreto-Lynn-Scott with embedding degree 24. */ + EP_B24, + /* Barreto-Lynn-Scott with embedding degree 48. */ + EP_B48, + /** Kachisa-Scott-Schaefer curve with embedding degree 54. */ + EP_K54, +}; + +/*============================================================================*/ +/* Constant definitions */ +/*============================================================================*/ + +/** + * Denotes a divisive twist. + */ +#define EP_DTYPE 1 + +/** + * Denotes a multiplicative twist. + */ +#define EP_MTYPE 2 + +/** + * Size of a precomputation table using the binary method. + */ +#define RLC_EP_TABLE_BASIC (RLC_FP_BITS + 1) + +/** + * Size of a precomputation table using the single-table comb method. + */ +#define RLC_EP_TABLE_COMBS (1 << EP_DEPTH) + +/** + * Size of a precomputation table using the double-table comb method. + */ +#define RLC_EP_TABLE_COMBD (1 << (EP_DEPTH + 1)) + +/** + * Size of a precomputation table using the w-(T)NAF method. + */ +#define RLC_EP_TABLE_LWNAF (1 << (EP_DEPTH - 2)) + +/** + * Size of a precomputation table using the chosen algorithm. + */ +#if EP_FIX == BASIC +#define RLC_EP_TABLE RLC_EP_TABLE_BASIC +#elif EP_FIX == COMBS +#define RLC_EP_TABLE RLC_EP_TABLE_COMBS +#elif EP_FIX == COMBD +#define RLC_EP_TABLE RLC_EP_TABLE_COMBD +#elif EP_FIX == LWNAF +#define RLC_EP_TABLE RLC_EP_TABLE_LWNAF +#endif + +/** + * Maximum size of a precomputation table. + */ +#ifdef STRIP +#define RLC_EP_TABLE_MAX RLC_EP_TABLE +#else +#define RLC_EP_TABLE_MAX RLC_MAX(RLC_EP_TABLE_BASIC, RLC_EP_TABLE_COMBD) +#endif + +/** + * Maximum number of coefficients of an isogeny map polynomial. + * RLC_TERMS of value 16 is sufficient for a degree-11 isogeny polynomial. + */ +#define RLC_EP_CTMAP_MAX 16 + +/*============================================================================*/ +/* Type definitions */ +/*============================================================================*/ + +/** + * Represents an elliptic curve point over a prime field. + */ +typedef struct { + /** The first coordinate. */ + fp_st x; + /** The second coordinate. */ + fp_st y; + /** The third coordinate (projective representation). */ + fp_st z; + /** Flag to indicate that this point is normalized. */ + int norm; +} ep_st; + + +/** + * Pointer to an elliptic curve point. + */ +#if ALLOC == AUTO +typedef ep_st ep_t[1]; +#else +typedef ep_st *ep_t; +#endif + +/** + * Data structure representing an isogeny map. + */ +typedef struct { + /** The a-coefficient of the isogenous curve used for SSWU mapping. */ + fp_st a; + /** The b-coefficient of the isogenous curve used for SSWU mapping. */ + fp_st b; + /** Degree of x numerator */ + int deg_xn; + /** Degree of x denominator */ + int deg_xd; + /** Degree of y numerator */ + int deg_yn; + /** Degree of y denominator */ + int deg_yd; + /** x numerator coefficients */ + fp_st xn[RLC_EP_CTMAP_MAX]; + /** x denominator coefficients */ + fp_st xd[RLC_EP_CTMAP_MAX]; + /** y numerator coefficients */ + fp_st yn[RLC_EP_CTMAP_MAX]; + /** y denominator coefficients */ + fp_st yd[RLC_EP_CTMAP_MAX]; +} iso_st; + +/** + * Pointer to isogeny map coefficients. + */ +typedef iso_st *iso_t; + +/*============================================================================*/ +/* Macro definitions */ +/*============================================================================*/ + +/** + * Initializes a point on a prime elliptic curve with a null value. + * + * @param[out] A - the point to initialize. + */ +#if ALLOC == AUTO +#define ep_null(A) /* empty */ +#else +#define ep_null(A) A = NULL; +#endif + +/** + * Calls a function to allocate a point on a prime elliptic curve. + * + * @param[out] A - the new point. + * @throw ERR_NO_MEMORY - if there is no available memory. + */ +#if ALLOC == DYNAMIC +#define ep_new(A) \ + A = (ep_t)calloc(1, sizeof(ep_st)); \ + if (A == NULL) { \ + THROW(ERR_NO_MEMORY); \ + } \ + +#elif ALLOC == AUTO +#define ep_new(A) /* empty */ + +#elif ALLOC == STACK +#define ep_new(A) \ + A = (ep_t)alloca(sizeof(ep_st)); \ + +#endif + +/** + * Calls a function to clean and free a point on a prime elliptic curve. + * + * @param[out] A - the point to free. + */ +#if ALLOC == DYNAMIC +#define ep_free(A) \ + if (A != NULL) { \ + free(A); \ + A = NULL; \ + } + +#elif ALLOC == AUTO +#define ep_free(A) /* empty */ + +#elif ALLOC == STACK +#define ep_free(A) \ + A = NULL; \ + +#endif + +/** + * Negates a prime elliptic curve point. Computes R = -P. + * + * @param[out] R - the result. + * @param[in] P - the point to negate. + */ +#if EP_ADD == BASIC +#define ep_neg(R, P) ep_neg_basic(R, P) +#elif EP_ADD == PROJC +#define ep_neg(R, P) ep_neg_projc(R, P) +#endif + +/** + * Adds two prime elliptic curve points. 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 ep_add(R, P, Q) ep_add_basic(R, P, Q) +#elif EP_ADD == PROJC +#define ep_add(R, P, Q) ep_add_projc(R, P, Q) +#endif + +/** + * Subtracts a prime elliptic curve point from another. Computes R = P - Q. + * + * @param[out] R - the result. + * @param[in] P - the first point. + * @param[in] Q - the second point. + */ +#if EP_ADD == BASIC +#define ep_sub(R, P, Q) ep_sub_basic(R, P, Q) +#elif EP_ADD == PROJC +#define ep_sub(R, P, Q) ep_sub_projc(R, P, Q) +#endif + +/** + * Doubles a prime elliptic curve point. Computes R = 2P. + * + * @param[out] R - the result. + * @param[in] P - the point to double. + */ +#if EP_ADD == BASIC +#define ep_dbl(R, P) ep_dbl_basic(R, P) +#elif EP_ADD == PROJC +#define ep_dbl(R, P) ep_dbl_projc(R, P) +#endif + +/** + * Multiplies a prime elliptic curve point by an integer. Computes R = kP. + * + * @param[out] R - the result. + * @param[in] P - the point to multiply. + * @param[in] K - the integer. + */ +#if EP_MUL == BASIC +#define ep_mul(R, P, K) ep_mul_basic(R, P, K) +#elif EP_MUL == SLIDE +#define ep_mul(R, P, K) ep_mul_slide(R, P, K) +#elif EP_MUL == MONTY +#define ep_mul(R, P, K) ep_mul_monty(R, P, K) +#elif EP_MUL == LWNAF +#define ep_mul(R, P, K) ep_mul_lwnaf(R, P, K) +#elif EP_MUL == LWREG +#define ep_mul(R, P, K) ep_mul_lwreg(R, P, K) +#endif + +/** + * Builds a precomputation table for multiplying a fixed prime elliptic point. + * + * @param[out] T - the precomputation table. + * @param[in] P - the point to multiply. + */ +#if EP_FIX == BASIC +#define ep_mul_pre(T, P) ep_mul_pre_basic(T, P) +#elif EP_FIX == COMBS +#define ep_mul_pre(T, P) ep_mul_pre_combs(T, P) +#elif EP_FIX == COMBD +#define ep_mul_pre(T, P) ep_mul_pre_combd(T, P) +#elif EP_FIX == LWNAF +#define ep_mul_pre(T, P) ep_mul_pre_lwnaf(T, P) +#endif + +/** + * Multiplies a fixed prime elliptic point using a precomputation table. + * Computes R = kP. + * + * @param[out] R - the result. + * @param[in] T - the precomputation table. + * @param[in] K - the integer. + */ +#if EP_FIX == BASIC +#define ep_mul_fix(R, T, K) ep_mul_fix_basic(R, T, K) +#elif EP_FIX == COMBS +#define ep_mul_fix(R, T, K) ep_mul_fix_combs(R, T, K) +#elif EP_FIX == COMBD +#define ep_mul_fix(R, T, K) ep_mul_fix_combd(R, T, K) +#elif EP_FIX == LWNAF +#define ep_mul_fix(R, T, K) ep_mul_fix_lwnaf(R, T, K) +#endif + +/** + * Multiplies and adds two prime elliptic curve points simultaneously. Computes + * R = kP + mQ. + * + * @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 ep_mul_sim(R, P, K, Q, M) ep_mul_sim_basic(R, P, K, Q, M) +#elif EP_SIM == TRICK +#define ep_mul_sim(R, P, K, Q, M) ep_mul_sim_trick(R, P, K, Q, M) +#elif EP_SIM == INTER +#define ep_mul_sim(R, P, K, Q, M) ep_mul_sim_inter(R, P, K, Q, M) +#elif EP_SIM == JOINT +#define ep_mul_sim(R, P, K, Q, M) ep_mul_sim_joint(R, P, K, Q, M) +#endif + +/*============================================================================*/ +/* Function prototypes */ +/*============================================================================*/ + +/** + * Initializes the prime elliptic curve arithmetic module. + */ +void ep_curve_init(void); + +/** + * Finalizes the prime elliptic curve arithmetic module. + */ +void ep_curve_clean(void); + +/** + * Returns the 'a' coefficient of the currently configured prime elliptic curve. + * + * @return the 'a' coefficient of the elliptic curve. + */ +dig_t *ep_curve_get_a(void); + +/** + * Returns the 'b' coefficient of the currently configured prime elliptic curve. + * + * @return the 'b' coefficient of the elliptic curve. + */ +dig_t *ep_curve_get_b(void); + +/** + * Returns the efficient endormorphism associated with the prime curve. + */ +dig_t *ep_curve_get_beta(void); + +/** + * Returns the parameter V1 of the prime curve. + */ +void ep_curve_get_v1(bn_t v[]); + +/** + * Returns the parameter V2 of the prime curve. + */ +void ep_curve_get_v2(bn_t v[]); + +/** + * Returns a optimization identifier based on the 'a' coefficient of the curve. + * + * @return the optimization identifier. + */ +int ep_curve_opt_a(void); + +/** + * Returns a optimization identifier based on the 'b' coefficient of the curve. + * + * @return the optimization identifier. + */ +int ep_curve_opt_b(void); + +/** + * Tests if the configured prime elliptic curve is a Koblitz curve. + * + * @return 1 if the prime elliptic curve is a Koblitz curve, 0 otherwise. + */ +int ep_curve_is_endom(void); + +/** + * Tests if the configured prime elliptic curve is supersingular. + * + * @return 1 if the prime elliptic curve is supersingular, 0 otherwise. + */ +int ep_curve_is_super(void); + +/** + * Tests if the configured prime elliptic curve is pairing-friendly. + * + * @return 0 if the prime elliptic curve is not pairing-friendly, and the + * family identifier otherwise. + */ +int ep_curve_is_pairf(void); + +/** + * Tests if the current curve should use an isogeny map for the SSWU map. + * + * @return 1 if the curve uses an isogeny, and 0 otherwise. + */ +int ep_curve_is_ctmap(void); + +/** + * Returns the generator of the group of points in the prime elliptic curve. + * + * @param[out] g - the returned generator. + */ +void ep_curve_get_gen(ep_t g); + +/** + * Returns the precomputation table for the generator. + * + * @return the table. + */ +const ep_t *ep_curve_get_tab(void); + +/** + * Returns the order of the group of points in the prime elliptic curve. + * + * @param[out] r - the returned order. + */ +void ep_curve_get_ord(bn_t n); + +/** + * Returns the cofactor of the binary elliptic curve. + * + * @param[out] n - the returned cofactor. + */ +void ep_curve_get_cof(bn_t h); + +/** + * Returns the isogeny map coefficients for use with the SSWU map. + */ +iso_t ep_curve_get_iso(void); + +/** + * Configures a prime elliptic curve without endomorphisms by its coefficients + * and generator. + * + * @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. + * @param[in] u - the non-square used for hashing to this curve. + * @param[in] ctmap - true if this curve will use an isogeny for mapping. + */ +void ep_curve_set_plain(const fp_t a, const fp_t b, const ep_t g, const bn_t r, + const bn_t h, const fp_t u, int ctmap); + +/** + * Configures a supersingular prime elliptic curve by its coefficients and + * generator. + * + * @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. + * @param[in] u - the non-square used for hashing to this curve. + * @param[in] ctmap - true if this curve will use an isogeny for mapping. + */ +void ep_curve_set_super(const fp_t a, const fp_t b, const ep_t g, const bn_t r, + const bn_t h, const fp_t u, int ctmap); + +/** + * Configures a prime elliptic curve with endomorphisms by its coefficients and + * generator. + * + * @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] beta - the constant associated with the endomorphism. + * @param[in] l - the exponent corresponding to the endomorphism. + * @param[in] h - the cofactor of the group order. + * @param[in] u - the non-square used for hashing to this curve. + * @param[in] ctmap - true if this curve will use an isogeny for mapping. + */ +void ep_curve_set_endom(const fp_t a, const fp_t b, const ep_t g, const bn_t r, + const bn_t h, const fp_t beta, const bn_t l, const fp_t u, int ctmap); + +/** + * Configures a prime elliptic curve by its parameter identifier. + * + * @param - the parameter identifier. + */ +void ep_param_set(int param); + +/** + * Configures some set of curve parameters for the current security level. + */ +int ep_param_set_any(void); + +/** + * Configures some set of ordinary curve parameters for the current security + * level. + * + * @return RLC_OK if there is a curve at this security level, RLC_ERR otherwise. + */ +int ep_param_set_any_plain(void); + +/** + * Configures some set of Koblitz curve parameters for the current security + * level. + * + * @return RLC_OK if there is a curve at this security level, RLC_ERR otherwise. + */ +int ep_param_set_any_endom(void); + +/** + * Configures some set of supersingular curve parameters for the current + * security level. + * + * @return RLC_OK if there is a curve at this security level, RLC_ERR otherwise. + */ +int ep_param_set_any_super(void); + +/** + * Configures some set of pairing-friendly curve parameters for the current + * security level. + * + * @return RLC_OK if there is a curve at this security level, RLC_ERR otherwise. + */ +int ep_param_set_any_pairf(void); + +/** + * Returns the parameter identifier of the currently configured prime elliptic + * curve. + * + * @return the parameter identifier. + */ +int ep_param_get(void); + +/** + * Prints the current configured prime elliptic curve. + */ +void ep_param_print(void); + +/** + * Returns the current security level. + */ +int ep_param_level(void); + +/** + * Returns the embedding degree of the currently configured elliptic curve. + */ +int ep_param_embed(void); + +/** + * Tests if a point on a prime elliptic curve is at the infinity. + * + * @param[in] p - the point to test. + * @return 1 if the point is at infinity, 0 otherise. + */ +int ep_is_infty(const ep_t p); + +/** + * Assigns a prime elliptic curve point to a point at the infinity. + * + * @param[out] p - the point to assign. + */ +void ep_set_infty(ep_t p); + +/** + * Copies the second argument to the first argument. + * + * @param[out] q - the result. + * @param[in] p - the prime elliptic curve point to copy. + */ +void ep_copy(ep_t r, const ep_t p); + +/** + * Compares two prime elliptic curve points. + * + * @param[in] p - the first prime elliptic curve point. + * @param[in] q - the second prime elliptic curve point. + * @return RLC_EQ if p == q and RLC_NE if p != q. + */ +int ep_cmp(const ep_t p, const ep_t q); + +/** + * Assigns a random value to a prime elliptic curve point. + * + * @param[out] p - the prime elliptic curve point to assign. + */ +void ep_rand(ep_t p); + +/** + * Computes the right-hand side of the elliptic curve equation at a certain + * prime elliptic curve point. + * + * @param[out] rhs - the result. + * @param[in] p - the point. + */ +void ep_rhs(fp_t rhs, const ep_t p); + +/** + * Tests if a point is in the curve. + * + * @param[in] p - the point to test. + */ +int ep_is_valid(const ep_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 ep_tab(ep_t *t, const ep_t p, int w); + +/** + * Prints a prime elliptic curve point. + * + * @param[in] p - the prime elliptic curve point to print. + */ +void ep_print(const ep_t p); + +/** + * Returns the number of bytes necessary to store a prime elliptic curve point + * 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 ep_size_bin(const ep_t a, int pack); + +/** + * Reads a prime elliptic curve point 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 ep_read_bin(ep_t a, const uint8_t *bin, int len); + +/** + * Writes a prime elliptic curve point 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 point compression. + * @throw ERR_NO_BUFFER - if the buffer capacity is invalid. + */ +void ep_write_bin(uint8_t *bin, int len, const ep_t a, int pack); + +/** + * Negates a prime elliptic curve point represented by affine coordinates. + * + * @param[out] r - the result. + * @param[in] p - the point to negate. + */ +void ep_neg_basic(ep_t r, const ep_t p); + +/** + * Negates a prime elliptic curve point represented by projective coordinates. + * + * @param[out] r - the result. + * @param[in] p - the point to negate. + */ +void ep_neg_projc(ep_t r, const ep_t p); + +/** + * Adds two prime elliptic curve points represented in affine coordinates. + * + * @param[out] r - the result. + * @param[in] p - the first point to add. + * @param[in] q - the second point to add. + */ +void ep_add_basic(ep_t r, const ep_t p, const ep_t q); + +/** + * Adds two prime elliptic curve points represented in affine coordinates 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 ep_add_slp_basic(ep_t r, fp_t s, const ep_t p, const ep_t q); + +/** + * Adds two prime elliptic curve points represented in projective coordinates. + * + * @param[out] r - the result. + * @param[in] p - the first point to add. + * @param[in] q - the second point to add. + */ +void ep_add_projc(ep_t r, const ep_t p, const ep_t q); + +/** + * Subtracts a prime elliptic curve point from another, both points represented + * in affine coordinates. + * + * @param[out] r - the result. + * @param[in] p - the first point. + * @param[in] q - the second point. + */ +void ep_sub_basic(ep_t r, const ep_t p, const ep_t q); + +/** + * Subtracts a prime elliptic curve point from another, both points represented + * in projective coordinates. + * + * @param[out] r - the result. + * @param[in] p - the first point. + * @param[in] q - the second point. + */ +void ep_sub_projc(ep_t r, const ep_t p, const ep_t q); + +/** + * Doubles a prime elliptic curve point represented in affine coordinates. + * + * @param[out] r - the result. + * @param[in] p - the point to double. + */ +void ep_dbl_basic(ep_t r, const ep_t p); + +/** + * Doubles a prime elliptic curve point represented in affine coordinates and + * returns the computed slope. + * + * @param[out] r - the result. + * @param[out] s - the slope. + * @param[in] p - the point to double. + */ +void ep_dbl_slp_basic(ep_t r, fp_t s, const ep_t p); + +/** + * Doubles a prime elliptic curve point represented in projective coordinates. + * + * @param[out] r - the result. + * @param[in] p - the point to double. + */ +void ep_dbl_projc(ep_t r, const ep_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 ep_mul_basic(ep_t r, const ep_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 ep_mul_slide(ep_t r, const ep_t p, const bn_t k); + +/** + * Multiplies a prime elliptic point by an integer using the constant-time + * Montgomery laddering point multiplication method. + * + * @param[out] r - the result. + * @param[in] p - the point to multiply. + * @param[in] k - the integer. + */ +void ep_mul_monty(ep_t r, const ep_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 ep_mul_lwnaf(ep_t r, const ep_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 ep_mul_lwreg(ep_t r, const ep_t p, const bn_t k); + +/** + * Multiplies the generator of a prime elliptic curve by an integer. + * + * @param[out] r - the result. + * @param[in] k - the integer. + */ +void ep_mul_gen(ep_t r, const bn_t k); + +/** + * Multiplies a prime elliptic point by a small positive integer. + * + * @param[out] r - the result. + * @param[in] p - the point to multiply. + * @param[in] k - the integer. + */ +void ep_mul_dig(ep_t r, const ep_t p, dig_t k); + +/** + * 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 ep_mul_pre_basic(ep_t *t, const ep_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 ep_mul_pre_yaowi(ep_t *t, const ep_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 ep_mul_pre_nafwi(ep_t *t, const ep_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 ep_mul_pre_combs(ep_t *t, const ep_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 ep_mul_pre_combd(ep_t *t, const ep_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 ep_mul_pre_lwnaf(ep_t *t, const ep_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 ep_mul_fix_basic(ep_t r, const ep_t *t, const bn_t k); + +/** + * Multiplies a fixed prime elliptic point using a precomputation table and + * Yao's windowing method + * + * @param[out] r - the result. + * @param[in] t - the precomputation table. + * @param[in] k - the integer. + */ +void ep_mul_fix_yaowi(ep_t r, const ep_t *t, const bn_t k); + +/** + * Multiplies a fixed prime elliptic point using a precomputation table and + * the w-(T)NAF method. + * + * @param[out] r - the result. + * @param[in] t - the precomputation table. + * @param[in] k - the integer. + */ +void ep_mul_fix_nafwi(ep_t r, const ep_t *t, const bn_t k); + +/** + * Multiplies a fixed prime elliptic point using a precomputation table and + * the single-table comb method. + * + * @param[out] r - the result. + * @param[in] t - the precomputation table. + * @param[in] k - the integer. + */ +void ep_mul_fix_combs(ep_t r, const ep_t *t, const bn_t k); + +/** + * Multiplies a fixed prime elliptic point using a precomputation table and + * the double-table comb method. + * + * @param[out] r - the result. + * @param[in] t - the precomputation table. + * @param[in] k - the integer. + */ +void ep_mul_fix_combd(ep_t r, const ep_t *t, const bn_t k); + +/** + * Multiplies a fixed prime elliptic point using a precomputation table and + * the w-(T)NAF method. + * + * @param[out] r - the result. + * @param[in] t - the precomputation table. + * @param[in] k - the integer. + */ +void ep_mul_fix_lwnaf(ep_t r, const ep_t *t, const bn_t k); + +/** + * Multiplies and adds two prime elliptic curve points simultaneously using + * scalar multiplication and point addition. + * + * @param[out] r - the result. + * @param[in] p - the first point to multiply. + * @param[in] k - the first integer. + * @param[in] q - the second point to multiply. + * @param[in] m - the second integer, + */ +void ep_mul_sim_basic(ep_t r, const ep_t p, const bn_t k, const ep_t q, + const bn_t m); + +/** + * Multiplies and adds two prime elliptic curve points simultaneously using + * shamir's trick. + * + * @param[out] r - the result. + * @param[in] p - the first point to multiply. + * @param[in] k - the first integer. + * @param[in] q - the second point to multiply. + * @param[in] m - the second integer, + */ +void ep_mul_sim_trick(ep_t r, const ep_t p, const bn_t k, const ep_t q, + const bn_t m); + +/** + * Multiplies and adds two prime elliptic curve points simultaneously using + * interleaving of NAFs. + * + * @param[out] r - the result. + * @param[in] p - the first point to multiply. + * @param[in] k - the first integer. + * @param[in] q - the second point to multiply. + * @param[in] m - the second integer, + */ +void ep_mul_sim_inter(ep_t r, const ep_t p, const bn_t k, const ep_t q, + const bn_t m); + +/** + * Multiplies and adds two prime elliptic curve points simultaneously using + * Solinas' Joint Sparse Form. + * + * @param[out] r - the result. + * @param[in] p - the first point to multiply. + * @param[in] k - the first integer. + * @param[in] q - the second point to multiply. + * @param[in] m - the second integer, + */ +void ep_mul_sim_joint(ep_t r, const ep_t p, const bn_t k, const ep_t q, + const bn_t m); + +/** + * Multiplies and adds the generator and a prime elliptic curve point + * simultaneously. Computes R = kG + mQ. + * + * @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 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. + * + * @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 ep_mul_sim_dig(ep_t r, const ep_t p[], const dig_t k[], int len); + +/** + * Converts a point to affine coordinates. + * + * @param[out] r - the result. + * @param[in] p - the point to convert. + */ +void ep_norm(ep_t r, const ep_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 ep_norm_sim(ep_t *r, const ep_t *t, int n); + +/** + * 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. + */ +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 + * domain separation tag (aka personalization string). + * + * @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); + +/** + * Compresses a point. + * + * @param[out] r - the result. + * @param[in] p - the point to compress. + */ +void ep_pck(ep_t r, const ep_t p); + +/** + * Decompresses a point. + * + * @param[out] r - the result. + * @param[in] p - the point to decompress. + * @return a boolean value indicating if the decompression was successful. + */ +int ep_upk(ep_t r, const ep_t p); + +#endif /* !RLC_EP_H */ diff --git a/bls/contrib/relic/include/relic_epx.h b/bls/contrib/relic/include/relic_epx.h new file mode 100644 index 00000000..419a2a3a --- /dev/null +++ b/bls/contrib/relic/include/relic_epx.h @@ -0,0 +1,1022 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 . + */ + +/** + * @defgroup epx Elliptic curves defined over extensions of prime fields. + */ + +/** + * @file + * + * Interface of the module for arithmetic on prime elliptic curves defined over + * extension fields. + * + * @ingroup epx + */ + +#ifndef RLC_EPX_H +#define RLC_EPX_H + +#include "relic_fpx.h" +#include "relic_ep.h" +#include "relic_types.h" + +/*============================================================================*/ +/* Constant definitions */ +/*============================================================================*/ + +/** + * Size of a precomputation table using the binary method. + */ +#define RLC_EPX_TABLE_BASIC (2 * RLC_FP_BITS + 1) + +/** + * Size of a precomputation table using the single-table comb method. + */ +#define RLC_EPX_TABLE_COMBS (1 << EP_DEPTH) + +/** + * Size of a precomputation table using the double-table comb method. + */ +#define RLC_EPX_TABLE_COMBD (1 << (EP_DEPTH + 1)) + +/** + * Size of a precomputation table using the w-(T)NAF method. + */ +#define RLC_EPX_TABLE_LWNAF (1 << (EP_DEPTH - 2)) + +/** + * Size of a precomputation table using the chosen algorithm. + */ +#if EP_FIX == BASIC +#define RLC_EPX_TABLE RLC_EPX_TABLE_BASIC +#elif EP_FIX == COMBS +#define RLC_EPX_TABLE RLC_EPX_TABLE_COMBS +#elif EP_FIX == COMBD +#define RLC_EPX_TABLE RLC_EPX_TABLE_COMBD +#elif EP_FIX == LWNAF +#define RLC_EPX_TABLE RLC_EPX_TABLE_LWNAF +#endif + +/** + * Maximum size of a precomputation table. + */ +#ifdef STRIP +#define RLC_EPX_TABLE_MAX RLC_EPX_TABLE +#else +#define RLC_EPX_TABLE_MAX RLC_MAX(RLC_EPX_TABLE_BASIC, RLC_EPX_TABLE_COMBD) +#endif + +/** + * Maximum number of coefficients of an isogeny map polynomial. + * 4 is sufficient for a degree-3 isogeny polynomial. + */ +#define RLC_EPX_CTMAP_MAX 4 + +/*============================================================================*/ +/* Type definitions */ +/*============================================================================*/ + +/** + * Represents an elliptic curve point over a quadratic extension over a prime + * field. + */ +typedef struct { + /** The first coordinate. */ + fp2_t x; + /** The second coordinate. */ + fp2_t y; + /** The third coordinate (projective representation). */ + fp2_t z; + /** Flag to indicate that this point is normalized. */ + int norm; +} ep2_st; + +/** + * Pointer to an elliptic curve point. + */ +#if ALLOC == AUTO +typedef ep2_st ep2_t[1]; +#else +typedef ep2_st *ep2_t; +#endif + +/** + * Represents an elliptic curve point over a cubic extension over a prime + * field. + */ +typedef struct { + /** The first coordinate. */ + fp3_t x; + /** The second coordinate. */ + fp3_t y; + /** The third coordinate (projective representation). */ + fp3_t z; + /** Flag to indicate that this point is normalized. */ + int norm; +} ep3_st; + +/** + * Pointer to an elliptic curve point. + */ +#if ALLOC == AUTO +typedef ep3_st ep3_t[1]; +#else +typedef ep3_st *ep3_t; +#endif + +/** + * Coefficients of an isogeny map for a curve over a quadratic extension. + */ +typedef struct { + /** The a-coefficient of the isogenous curve used for SSWU mapping. */ + fp2_t a; + /** The b-coefficient of the isogenous curve used for SSWU mapping. */ + fp2_t b; + /** Degree of x numerator */ + int deg_xn; + /** Degree of x denominator */ + int deg_xd; + /** Degree of y numerator */ + int deg_yn; + /** Degree of y denominator */ + int deg_yd; + /** x numerator coefficients */ + fp2_t xn[RLC_EPX_CTMAP_MAX]; + /** x denominator coefficients */ + fp2_t xd[RLC_EPX_CTMAP_MAX]; + /** y numerator coefficients */ + fp2_t yn[RLC_EPX_CTMAP_MAX]; + /** y denominator coefficients */ + fp2_t yd[RLC_EPX_CTMAP_MAX]; +#if ALLOC == STACK + /** In case of stack allocation, storage for the values in this struct. */ + /* a, b, and the elms in xn, xd, yn, yd */ + fp2_st storage[2 + 4 * RLC_EPX_CTMAP_MAX]; +#endif /* ALLOC == DYNAMIC or STACK */ +} iso2_st; + +/** + * Pointer to isogeny map coefficients. + */ +typedef iso2_st *iso2_t; + +/*============================================================================*/ +/* Macro definitions */ +/*============================================================================*/ + +/** + * Initializes a point on a elliptic curve with a null value. + * + * @param[out] A - the point to initialize. + */ +#if ALLOC == AUTO +#define ep2_null(A) /* empty */ +#else +#define ep2_null(A) A = NULL +#endif + +/** + * Calls a function to allocate a point on a elliptic curve. + * + * @param[out] A - the new point. + * @throw ERR_NO_MEMORY - if there is no available memory. + */ +#if ALLOC == DYNAMIC +#define ep2_new(A) \ + A = (ep2_t)calloc(1, sizeof(ep2_st)); \ + if (A == NULL) { \ + THROW(ERR_NO_MEMORY); \ + } \ + fp2_null((A)->x); \ + fp2_null((A)->y); \ + fp2_null((A)->z); \ + fp2_new((A)->x); \ + fp2_new((A)->y); \ + fp2_new((A)->z); \ + +#elif ALLOC == AUTO +#define ep2_new(A) /* empty */ + +#elif ALLOC == STACK +#define ep2_new(A) \ + A = (ep2_t)alloca(sizeof(ep2_st)); \ + fp2_new((A)->x); \ + fp2_new((A)->y); \ + fp2_new((A)->z); \ + +#endif + +/** + * Calls a function to clean and free a point on a elliptic curve. + * + * @param[out] A - the point to free. + */ +#if ALLOC == DYNAMIC +#define ep2_free(A) \ + if (A != NULL) { \ + fp2_free((A)->x); \ + fp2_free((A)->y); \ + fp2_free((A)->z); \ + free(A); \ + A = NULL; \ + } \ + +#elif ALLOC == AUTO +#define ep2_free(A) /* empty */ +#elif ALLOC == STACK +#define ep2_free(A) A = NULL; +#endif + +/** + * Negates a point in an elliptic curve over a quadratic extension field. + * Computes R = -P. + * + * @param[out] R - the result. + * @param[in] P - the point to negate. + */ +#if EP_ADD == BASIC +#define ep2_neg(R, P) ep2_neg_basic(R, P) +#elif EP_ADD == PROJC +#define ep2_neg(R, P) ep2_neg_projc(R, P) +#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 ep2_add(R, P, Q) ep2_add_basic(R, P, Q); +#elif EP_ADD == PROJC +#define ep2_add(R, P, Q) ep2_add_projc(R, P, Q); +#endif + +/** + * Subtracts a point in an elliptic curve over a quadratic extension field from + * another point in this curve. Computes R = P - Q. + * + * @param[out] R - the result. + * @param[in] P - the first point. + * @param[in] Q - the second point. + */ +#if EP_ADD == BASIC +#define ep2_sub(R, P, Q) ep2_sub_basic(R, P, Q) +#elif EP_ADD == PROJC +#define ep2_sub(R, P, Q) ep2_sub_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 ep2_dbl(R, P) ep2_dbl_basic(R, P); +#elif EP_ADD == PROJC +#define ep2_dbl(R, P) ep2_dbl_projc(R, P); +#endif + +/** + * Multiplies a point in an elliptic curve over a quadratic extension field. + * Computes R = kP. + * + * @param[out] R - the result. + * @param[in] P - the point to multiply. + * @param[in] K - the integer. + */ +#if EP_MUL == BASIC +#define ep2_mul(R, P, K) ep2_mul_basic(R, P, K) +#elif EP_MUL == SLIDE +#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 +#define ep2_mul(R, P, K) ep2_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 ep2_mul_pre(T, P) ep2_mul_pre_basic(T, P) +#elif EP_FIX == COMBS +#define ep2_mul_pre(T, P) ep2_mul_pre_combs(T, P) +#elif EP_FIX == COMBD +#define ep2_mul_pre(T, P) ep2_mul_pre_combd(T, P) +#elif EP_FIX == LWNAF +#define ep2_mul_pre(T, P) ep2_mul_pre_lwnaf(T, P) +#elif EP_FIX == GLV +//TODO: implement ep2_mul_pre_glv +#define ep2_mul_pre(T, P) ep2_mul_pre_lwnaf(T, P) +#endif + +/** + * Multiplies a fixed prime elliptic point over a quadratic extension using a + * precomputation table. Computes R = kP. + * + * @param[out] R - the result. + * @param[in] T - the precomputation table. + * @param[in] K - the integer. + */ +#if EP_FIX == BASIC +#define ep2_mul_fix(R, T, K) ep2_mul_fix_basic(R, T, K) +#elif EP_FIX == COMBS +#define ep2_mul_fix(R, T, K) ep2_mul_fix_combs(R, T, K) +#elif EP_FIX == COMBD +#define ep2_mul_fix(R, T, K) ep2_mul_fix_combd(R, T, K) +#elif EP_FIX == LWNAF +#define ep2_mul_fix(R, T, K) ep2_mul_fix_lwnaf(R, T, K) +#elif EP_FIX == GLV +//TODO: implement ep2_mul_pre_glv +#define ep2_mul_fix(R, T, K) ep2_mul_fix_lwnaf(R, T, K) +#endif + +/** + * Multiplies and adds two prime elliptic curve points simultaneously. Computes + * R = kP + lQ. + * + * @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 ep2_mul_sim(R, P, K, Q, M) ep2_mul_sim_basic(R, P, K, Q, M) +#elif EP_SIM == TRICK +#define ep2_mul_sim(R, P, K, Q, M) ep2_mul_sim_trick(R, P, K, Q, M) +#elif EP_SIM == INTER +#define ep2_mul_sim(R, P, K, Q, M) ep2_mul_sim_inter(R, P, K, Q, M) +#elif EP_SIM == JOINT +#define ep2_mul_sim(R, P, K, Q, M) ep2_mul_sim_joint(R, P, K, Q, M) +#endif + +/*============================================================================*/ +/* Function prototypes */ +/*============================================================================*/ + +/** + * Initializes the elliptic curve over quadratic extension. + */ +void ep2_curve_init(void); + +/** + * Finalizes the elliptic curve over quadratic extension. + */ +void ep2_curve_clean(void); + +/** + * Returns the 'a' coefficient of the currently configured elliptic curve. + * + * @return the 'a' coefficient of the elliptic curve. + */ +fp_t *ep2_curve_get_a(void); + +/** + * Returns the 'b' coefficient of the currently configured elliptic curve. + * + * @param[out] b - the 'b' coefficient of the elliptic curve. + */ +fp_t *ep2_curve_get_b(void); + +/** + * Returns the vector of coefficients required to perform GLV method. + * + * @param[out] b - the vector of coefficients. + */ +void ep2_curve_get_vs(bn_t *v); + +/** + * Returns a optimization identifier based on the 'a' coefficient of the curve. + * + * @return the optimization identifier. + */ +int ep2_curve_opt_a(void); + +/** + * Returns b optimization identifier based on the 'b' coefficient of the curve. + * + * @return the optimization identifier. + */ +int ep2_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 ep2_curve_is_twist(void); + +/** + * Tests if the current curve should use an isogeny map for the SSWU map. + * + * @return 1 if the curve uses an isogeny, and 0 otherwise. + */ +int ep2_curve_is_ctmap(void); + +/** + * Returns the generator of the group of points in the elliptic curve. + * + * @param[out] g - the returned generator. + */ +void ep2_curve_get_gen(ep2_t g); + +/** + * Returns the precomputation table for the generator. + * + * @return the table. + */ +ep2_t *ep2_curve_get_tab(void); + +/** + * Returns the order of the group of points in the elliptic curve. + * + * @param[out] n - the returned order. + */ +void ep2_curve_get_ord(bn_t n); + +/** + * Returns the cofactor of the group order in the elliptic curve. + * + * @param[out] h - the returned cofactor. + */ +void ep2_curve_get_cof(bn_t h); + +/** + * Returns the sqrt(-3) mod q in the curve, where q is the prime. + * + * @param[out] h - the returned cofactor. + */ +void ep2_curve_get_s3(bn_t s3); + +/** + * Returns the (sqrt(-3) - 1) / 2 mod q in the curve, where q is the prime. + * + * @param[out] h - the returned cofactor. + */ +void ep2_curve_get_s32(bn_t s32); + +/** + * Returns the isogeny map coefficients for use with the SSWU map. + */ +iso2_t ep2_curve_get_iso(void); + +/** + * Configures an elliptic curve over a quadratic 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 ep2_curve_set(fp2_t a, fp2_t b, ep2_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 ep2_curve_set_twist(int type); + +/** + * Tests if a point on a elliptic curve is at the infinity. + * + * @param[in] p - the point to test. + * @return 1 if the point is at infinity, 0 otherise. + */ +int ep2_is_infty(ep2_t p); + +/** + * Assigns a elliptic curve point to a point at the infinity. + * + * @param[out] p - the point to assign. + */ +void ep2_set_infty(ep2_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 ep2_copy(ep2_t r, ep2_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 ep2_cmp(ep2_t p, ep2_t q); + +/** + * Assigns a random value to an elliptic curve point. + * + * @param[out] p - the elliptic curve point to assign. + */ +void ep2_rand(ep2_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 ep2_rhs(fp2_t rhs, ep2_t p); + +/** + * Tests if a point is in the curve. + * + * @param[in] p - the point to test. + */ +int ep2_is_valid(ep2_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 ep2_tab(ep2_t *t, ep2_t p, int w); + +/** + * Prints a elliptic curve point. + * + * @param[in] p - the elliptic curve point to print. + */ +void ep2_print(ep2_t p); + +/** + * Returns the number of bytes necessary to store a prime elliptic curve point + * over a quadratic 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 ep2_size_bin(ep2_t a, int pack); + +/** + * Reads a prime elliptic curve point over a quadratic 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 ep2_read_bin(ep2_t a, const uint8_t *bin, int len); + +/** + * Writes a prime elliptic curve pointer over a quadratic 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 point compression. + * @throw ERR_NO_BUFFER - if the buffer capacity is invalid. + */ +void ep2_write_bin(uint8_t *bin, int len, ep2_t a, int pack); + +/** + * Negates a point represented in affine coordinates in an elliptic curve over + * a quadratic extension. + * + * @param[out] r - the result. + * @param[out] p - the point to negate. + */ +void ep2_neg_basic(ep2_t r, ep2_t p); + +/** + * Negates a point represented in projective coordinates in an elliptic curve + * over a quadratic exyension. + * + * @param[out] r - the result. + * @param[out] p - the point to negate. + */ +void ep2_neg_projc(ep2_t r, ep2_t p); + +/** + * Adds to points represented in affine coordinates in an elliptic curve over a + * quadratic extension. + * + * @param[out] r - the result. + * @param[in] p - the first point to add. + * @param[in] q - the second point to add. + */ +void ep2_add_basic(ep2_t r, ep2_t p, ep2_t q); + +/** + * Adds to points represented in affine coordinates in an elliptic curve over a + * quadratic 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 ep2_add_slp_basic(ep2_t r, fp2_t s, ep2_t p, ep2_t q); + +/** + * Subtracts a points represented in affine coordinates in an elliptic curve + * over a quadratic extension from another point. + * + * @param[out] r - the result. + * @param[in] p - the first point. + * @param[in] q - the point to subtract. + */ +void ep2_sub_basic(ep2_t r, ep2_t p, ep2_t q); + +/** + * Adds two points represented in projective coordinates in an elliptic curve + * over a quadratic extension. + * + * @param[out] r - the result. + * @param[in] p - the first point to add. + * @param[in] q - the second point to add. + */ +void ep2_add_projc(ep2_t r, ep2_t p, ep2_t q); + +/** + * Subtracts a points represented in projective coordinates in an elliptic curve + * over a quadratic extension from another point. + * + * @param[out] r - the result. + * @param[in] p - the first point. + * @param[in] q - the point to subtract. + */ +void ep2_sub_projc(ep2_t r, ep2_t p, ep2_t q); + +/** + * Doubles a points represented in affine coordinates in an elliptic curve over + * a quadratic extension. + * + * @param[out] r - the result. + * @param[int] p - the point to double. + */ +void ep2_dbl_basic(ep2_t r, ep2_t p); + +/** + * Doubles a points represented in affine coordinates in an elliptic curve over + * a quadratic extension and returns the computed slope. + * + * @param[out] r - the result. + * @param[out] s - the slope. + * @param[in] p - the point to double. + */ +void ep2_dbl_slp_basic(ep2_t r, fp2_t s, ep2_t p); + +/** + * Doubles a points represented in projective coordinates in an elliptic curve + * over a quadratic extension. + * + * @param[out] r - the result. + * @param[in] p - the point to double. + */ +void ep2_dbl_projc(ep2_t r, ep2_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 ep2_mul_basic(ep2_t r, ep2_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 ep2_mul_slide(ep2_t r, ep2_t p, const bn_t k); + +/** + * Multiplies a prime elliptic point by an integer using the constant-time + * Montgomery laddering point multiplication method. + * + * @param[out] r - the result. + * @param[in] p - the point to multiply. + * @param[in] k - the integer. + */ +void ep2_mul_monty(ep2_t r, ep2_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 ep2_mul_lwnaf(ep2_t r, ep2_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 ep2_mul_lwreg(ep2_t r, ep2_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 ep2_mul_gen(ep2_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 ep2_mul_dig(ep2_t r, ep2_t p, dig_t k); + +/** + * 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 ep2_mul_pre_basic(ep2_t *t, ep2_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 ep2_mul_pre_yaowi(ep2_t *t, ep2_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 ep2_mul_pre_nafwi(ep2_t *t, ep2_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 ep2_mul_pre_combs(ep2_t *t, ep2_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 ep2_mul_pre_combd(ep2_t *t, ep2_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 ep2_mul_pre_lwnaf(ep2_t *t, ep2_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 ep2_mul_fix_basic(ep2_t r, ep2_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 ep2_mul_fix_yaowi(ep2_t r, ep2_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 ep2_mul_fix_nafwi(ep2_t r, ep2_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 ep2_mul_fix_combs(ep2_t r, ep2_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 ep2_mul_fix_combd(ep2_t r, ep2_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 ep2_mul_fix_lwnaf(ep2_t r, ep2_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 ep2_mul_sim_basic(ep2_t r, ep2_t p, bn_t k, ep2_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 ep2_mul_sim_trick(ep2_t r, ep2_t p, bn_t k, ep2_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 ep2_mul_sim_inter(ep2_t r, ep2_t p, bn_t k, ep2_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 ep2_mul_sim_joint(ep2_t r, ep2_t p, bn_t k, ep2_t q, bn_t m); + +/** + * Multiplies and adds the generator and a prime elliptic curve point + * simultaneously. Computes R = kG + lQ. + * + * @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 ep2_mul_sim_gen(ep2_t r, bn_t k, ep2_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 ep2_mul_sim_dig(ep2_t r, ep2_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 ep2_norm(ep2_t r, ep2_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 ep2_norm_sim(ep2_t *r, ep2_t *t, int n); + +/** + * Maps a byte array to a point in a prime elliptic curve. The + * algorithm implemented is the Fouque-Tibouchi algorithm from the + * paper "Indifferentiable Hashing to Barreto-Naehrig curves" for + * the BLS12-381 curve. + * + * @param[out] p - the result. + * @param[in] msg - the byte array to map. + * @param[in] len - the array length in bytes. + */ +void ep2_map(ep2_t p, const uint8_t *msg, int len, int performHash); + +/** + * Computes a power of the Gailbraith-Lin-Scott homomorphism of a point + * represented in affine coordinates on a twisted elliptic curve over a + * quadratic exension. That is, Psi^i(P) = Twist(P)(Frob^i(unTwist(P)). + * On the trace-zero group of a quadratic twist, consists of a power of the + * Frobenius map of a point represented in affine coordinates in an elliptic + * curve over a quadratic 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 ep2_frb(ep2_t r, ep2_t p, int i); + +/** + * Compresses a point in an elliptic curve over a quadratic extension. + * + * @param[out] r - the result. + * @param[in] p - the point to compress. + */ +void ep2_pck(ep2_t r, ep2_t p); + +/** + * Decompresses a point in an elliptic curve over a quadratic extension. + * + * @param[out] r - the result. + * @param[in] p - the point to decompress. + * @return if the decompression was successful + */ +int ep2_upk(ep2_t r, ep2_t p); + +#endif /* !RLC_EPX_H */ diff --git a/bls/contrib/relic/include/relic_err.h b/bls/contrib/relic/include/relic_err.h new file mode 100644 index 00000000..559afbbf --- /dev/null +++ b/bls/contrib/relic/include/relic_err.h @@ -0,0 +1,340 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 + * + * Interface of the error-handling functions. + * + * @ingroup relic + */ + +#ifndef RLC_ERR_H +#define RLC_ERR_H + +#include +#include +#include +#include +#include + +#include "relic_core.h" +#include "relic_conf.h" +#include "relic_util.h" +#include "relic_label.h" + +/*============================================================================*/ +/* Constant definitions */ +/*============================================================================*/ + +/** + * List of possible errors generated by the library. + */ +enum errors { + /** Constant to indicate the first an error already catched. */ + ERR_CAUGHT = 1, + /** Occurs when memory-allocating functions fail. */ + ERR_NO_MEMORY, + /** Occcurs when the library precision is not sufficient. */ + ERR_NO_PRECI, + /** Occurs when a file is not found. */ + ERR_NO_FILE, + /** Occurs when the specified number of bytes cannot be read from source. */ + ERR_NO_READ, + /** Occurs when an invalid value is passed as input. */ + ERR_NO_VALID, + /** Occurs when a buffer capacity is insufficient. */ + ERR_NO_BUFFER, + /** Occurs when there is not a supported field in the security level. */ + ERR_NO_FIELD, + /** Occurs when there is not a supported curve in the security level. */ + ERR_NO_CURVE, + /** Occurs when the library configuration is incorrect. */ + ERR_NO_CONFIG, + /** Constant to indicate the number of errors. */ + ERR_MAX +}; + +/** Truncate file name if verbosity is turned off. */ +#ifdef VERBS +#define ERR_FILE RLC_STR(__FILE__) +#else +#define ERR_FILE \ + ((strrchr(RLC_STR(__FILE__), '/') ? : RLC_STR(__FILE__) - 1) + 1) +#endif + +/*============================================================================*/ +/* Type definitions */ +/*============================================================================*/ + +/** + * Type that represents an error. + */ +typedef int err_t; + +/** + * Type that describes an error status, including the error code and the program + * location where the error occurred. + */ +typedef struct _sts_t { + /** Error occurred. */ + err_t *error; + /** Pointer to the program location where the error occurred. */ + jmp_buf addr; + /** Flag to tell if there is a surrounding try-catch block. */ + int block; +} sts_t; + +/*============================================================================*/ +/* Macro definitions */ +/*============================================================================*/ + +/** + * Implements the TRY clause of the error-handling routines. + * + * This macro copies the last error from the current library context to + * a temporary variable and handles the current error. The loop is used so + * the CATCH facility is called first to store the address of the error + * being caught. The setjmp() function is then called to store the current + * program location in the current error field. The program block can now be + * executed. If an error is thrown inside the program block, the setjmp() + * function is called again and the return value is non-zero. + */ +#define ERR_TRY \ + { \ + sts_t *_last, _this; \ + ctx_t *_ctx = core_get(); \ + _last = _ctx->last; \ + _this.block = 1; \ + _ctx->last = &_this; \ + for (int _z = 0; ; _z = 1) \ + if (_z) { \ + if (setjmp(_this.addr) == 0) { \ + if (1) \ + +/** + * Implements the CATCH clause of the error-handling routines. + * + * First, the address of the error is stored and the execution resumes + * on the ERR_TRY macro. If an error is thrown inside the program block, + * the caught flag is updated and the last error is restored. If some error + * was caught, the execution is resumed inside the CATCH block. + * + * @param[in] ADDR - the address of the exception being caught + */ +#define ERR_CATCH(ADDR) \ + else { } \ + _ctx->caught = 0; \ + } else { \ + _ctx->caught = 1; \ + } \ + _ctx->last = _last; \ + break; \ + } else { \ + _this.error = ADDR; \ + } \ + } \ + for (int _z = 0; _z < 2; _z++) \ + if (_z == 1 && core_get()->caught) \ + +/** + * 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. + * + * 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. + * + * If the error pointer is valid, the longjmp() function is called to return to + * the program location where setjmp() was last called. An error message + * respective to the error is then printed and the current error pointer is + * updated to store the error. + * + * @param[in] E - the exception being caught. + */ +#define ERR_THROW(E) \ + { \ + 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; \ + ERR_PRINT(E); \ + } else { \ + for (; ; longjmp(_ctx->last->addr, 1)) { \ + ERR_PRINT(E); \ + if (_ctx->last->error) { \ + if (E != ERR_CAUGHT) { \ + *(_ctx->last->error) = E; \ + } \ + } \ + } \ + } \ + } \ + +#ifdef CHECK +/** + * Implements a TRY clause. + */ +#define TRY ERR_TRY +#else +/** + * Stub for the TRY clause. + */ +#define TRY if (1) +#endif + +#ifdef CHECK +/** + * Implements a CATCH clause. + */ +#define CATCH(E) ERR_CATCH(&(E)) +#else +/** + * Stub for the CATCH clause. + */ +#define CATCH(E) else +#endif + +#ifdef CHECK +/** + * Implements a CATCH clause for any possible error. + * + * If this macro is used the error type is not available inside the CATCH + * block. + */ +#define CATCH_ANY ERR_CATCH(NULL) +#else +/** + * Stub for the CATCH_ANY clause. + */ +#define CATCH_ANY if (0) +#endif + +#ifdef CHECK +/** + * Implements a FINALLY clause. + */ +#define FINALLY else if (_z == 0) +#else +#define FINALLY if (1) +#endif + +#ifdef CHECK +/** + * Implements a THROW clause. + */ +#define THROW ERR_THROW +#else +/** + * Stub for the THROW clause. + */ +#ifdef QUIET +#define THROW(E) core_get()->code = RLC_ERR; +#else +#define THROW(E) \ + core_get()->code = RLC_ERR; \ + util_print("FATAL ERROR in %s:%d\n", ERR_FILE, __LINE__); \ + +#endif +#endif + +/** + * Treats an error jumping to the argument. + * + * @param[in] LABEL - the label to jump + */ +#define ERROR(LABEL) goto LABEL + +#ifdef VERBS + +/** + * Prints the current error message. + * + * @param[in] ERROR - the error code. + */ +#define ERR_PRINT(ERROR) \ + err_full_msg(__func__, ERR_FILE, __LINE__, ERROR) \ + +#else + +/** + * Prints the current error message. + * + * @param[in] ERROR - the error code. + */ +#define ERR_PRINT(ERROR) \ + err_simple_msg(ERROR) \ + +#endif + +/*============================================================================*/ +/* Function prototypes */ +/*============================================================================*/ + +#ifdef CHECK + +/** + * Prints the error message with little information. + * + * @param[in] error - the error code. + */ +void err_simple_msg(int error); + +/** + * Prints the error message with detailed information. + * + * @param[in] function - the function where the error occurred. + * @param[in] file - the source file where the error occurred. + * @param[in] line - the line in the file where the error occurred. + * @param[in] error - the error code. + */ +void err_full_msg(const char *function, const char *file, + int line, int error); + +/** + * Prints the error message respective to an error code. + * + * @param[out] e - the error occurred. + * @param[out] msg - the error message. + */ +void err_get_msg(err_t *e, char **msg); + +#endif + +/** + * Returns the code returned by the last function call and resets the current + * code. + * + * @returns ERR_OK if no errors occurred in the function, ERR_ERR otherwise. + */ +int err_get_code(void); + +#endif /* !RLC_ERR_H */ diff --git a/bls/contrib/relic/include/relic_fb.h b/bls/contrib/relic/include/relic_fb.h new file mode 100644 index 00000000..d8c593c6 --- /dev/null +++ b/bls/contrib/relic/include/relic_fb.h @@ -0,0 +1,995 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 . + */ + +/** + * @defgroup fb Binary field arithmetic + */ + +/** + * @file + * + * Interface of module for binary field arithmetic. + * + * @ingroup fb + */ + +#ifndef RLC_FB_H +#define RLC_FB_H + +#include "relic_bn.h" +#include "relic_dv.h" +#include "relic_conf.h" +#include "relic_types.h" + +/*============================================================================*/ +/* Constant definitions */ +/*============================================================================*/ + +/** + * Precision in bits of a binary field element. + */ +#define RLC_FB_BITS ((int)FB_POLYN) + +/** + * Size in digits of a block sufficient to store a binary field element. + */ +#define RLC_FB_DIGS ((int)RLC_CEIL(RLC_FB_BITS, RLC_DIG)) + +/** + * Size in bytes of a block sufficient to store a binary field element. + */ +#define RLC_FB_BYTES ((int)RLC_CEIL(RLC_FB_BITS, 8)) + +/** + * Finite field identifiers. + */ +enum { + /** AES pentaonimal. */ + PENTA_8 = 1, + /** Toy pentanomial. */ + PENTA_64, + /** Hankerson's trinomial for GLS curves. */ + TRINO_113, + /** Hankerson's trinomial for GLS curves. */ + TRINO_127, + /** GCM pentanomial */ + PENTA_128, + /** Pentanomial for ECC2K-130 challenge. */ + PENTA_131, + /** NIST 163-bit fast reduction polynomial. */ + NIST_163, + /** Square-root friendly 163-bit polynomial. */ + SQRT_163, + /** Example with 193 bits for Itoh-Tsuji. */ + TRINO_193, + /** NIST 233-bit fast reduction polynomial. */ + NIST_233, + /** Square-root friendly 233-bit polynomial. */ + SQRT_233, + /** SECG 239-bit fast reduction polynomial. */ + SECG_239, + /** Square-root friendly 239-bit polynomial. */ + SQRT_239, + /** Square-root friendly 251-bit polynomial. */ + SQRT_251, + /** eBATS curve_2_251 pentanomial. */ + PENTA_251, + /** Hankerson's trinomial for halving curve. */ + TRINO_257, + /** Scott's 271-bit pairing-friendly trinomial. */ + TRINO_271, + /** Scott's 271-bit pairing-friendly pentanomial. */ + PENTA_271, + /** NIST 283-bit fast reduction polynomial. */ + NIST_283, + /** Square-root friendly 283-bit polynomial. */ + SQRT_283, + /** Scott's 271-bit pairing-friendly trinomial. */ + TRINO_353, + /** Detrey's trinomial for genus 2 curves. */ + TRINO_367, + /** NIST 409-bit fast reduction polynomial. */ + NIST_409, + /** Hankerson's trinomial for genus 2 curves. */ + TRINO_439, + /** NIST 571-bit fast reduction polynomial. */ + NIST_571, + /** Square-root friendly 571-bit polynomial. */ + SQRT_571, + /** Scott's 1223-bit pairing-friendly trinomial. */ + TRINO_1223 +}; + +/** + * Size of a precomputation table for repeated squaring/square-root using the + * trivial approach. + */ +#define RLC_FB_TABLE_BASIC (1) + +/** + * Size of a precomputation table for repeated squaring/square-root using the + * faster approach. + */ +#define RLC_FB_TABLE_QUICK ((RLC_DIG / 4) * RLC_FB_DIGS * 16) + +/** + * Size of a precomputation table for repeated squaring/square-root using the + * chosen algorithm. + */ +#if FB_ITR == BASIC +#define RLC_FB_TABLE RLC_FB_TABLE_BASIC +#else +#define RLC_FB_TABLE RLC_FB_TABLE_QUICK +#endif + +/** + * Maximum size of a precomputation table. + */ +#ifdef STRIP +#define RLC_FB_TABLE_MAX RLC_FB_TABLE +#else +#define RLC_FB_TABLE_MAX RLC_FB_TABLE_QUICK +#endif + +/*============================================================================*/ +/* Type definitions */ +/*============================================================================*/ + +/** + * Represents a binary field element. + */ +#if ALLOC == AUTO +typedef rlc_align dig_t fb_t[RLC_FB_DIGS + RLC_PAD(RLC_FB_BYTES) / (RLC_DIG / 8)]; +#else +typedef dig_t *fb_t; +#endif + +/** + * Represents a binary field element with automatic memory allocation. + */ +typedef rlc_align dig_t fb_st[RLC_FB_DIGS + RLC_PAD(RLC_FB_BYTES) / (RLC_DIG / 8)]; + +/*============================================================================*/ +/* Macro definitions */ +/*============================================================================*/ + +/** + * Initializes a binary field element with a null value. + * + * @param[out] A - the binary field element to initialize. + */ +#if ALLOC == AUTO +#define fb_null(A) /* empty */ +#else +#define fb_null(A) A = NULL; +#endif + +/** + * Calls a function to allocate a binary field element. + * + * @param[out] A - the new binary field element. + * @throw ERR_NO_MEMORY - if there is no available memory. + */ +#if ALLOC == DYNAMIC +#define fb_new(A) dv_new_dynam((dv_t *)&(A), RLC_FB_DIGS) +#elif ALLOC == AUTO +#define fb_new(A) /* empty */ +#elif ALLOC == STACK +#define fb_new(A) \ + A = (dig_t *)alloca(RLC_FB_BYTES + RLC_PAD(RLC_FB_BYTES)); \ + A = (dig_t *)RLC_ALIGN(A); \ + +#endif + +/** + * Calls a function to free a binary field element. + * + * @param[out] A - the binary field element to clean and free. + */ +#if ALLOC == DYNAMIC +#define fb_free(A) dv_free_dynam((dv_t *)&(A)) +#elif ALLOC == AUTO +#define fb_free(A) /* empty */ +#elif ALLOC == STACK +#define fb_free(A) A = NULL; +#endif + +/** + * Multiples two binary field elements. Computes c = a * b. + * + * @param[out] C - the result. + * @param[in] A - the first binary field element to multiply. + * @param[in] B - the second binary field element to multiply. + */ +#if FB_KARAT > 0 +#define fb_mul(C, A, B) fb_mul_karat(C, A, B) +#elif FB_MUL == BASIC +#define fb_mul(C, A, B) fb_mul_basic(C, A, B) +#elif FB_MUL == INTEG +#define fb_mul(C, A, B) fb_mul_integ(C, A, B) +#elif FB_MUL == LODAH +#define fb_mul(C, A, B) fb_mul_lodah(C, A, B) +#endif + +/** + * Squares a binary field element. Computes c = a * a. + * + * @param[out] C - the result. + * @param[in] A - the binary field element to square. + */ +#if FB_SQR == BASIC +#define fb_sqr(C, A) fb_sqr_basic(C, A) +#elif FB_SQR == QUICK +#define fb_sqr(C, A) fb_sqr_quick(C, A) +#elif FB_SQR == INTEG +#define fb_sqr(C, A) fb_sqr_integ(C, A) +#endif + +/** + * Extracts the square root of a binary field element. Computes c = a^(1/2). + * + * @param[out] C - the result. + * @param[in] A - the binary field element. + */ +#if FB_SRT == BASIC +#define fb_srt(C, A) fb_srt_basic(C, A) +#elif FB_SRT == QUICK +#define fb_srt(C, A) fb_srt_quick(C, A) +#endif + +/** + * Reduces a multiplication result modulo a binary irreducible polynomial. + * Computes c = a mod f(z). + * + * @param[out] C - the result. + * @param[in] A - the multiplication result to reduce. + */ +#if FB_RDC == BASIC +#define fb_rdc(C, A) fb_rdc_basic(C, A) +#elif FB_RDC == QUICK +#define fb_rdc(C, A) fb_rdc_quick(C, A) +#endif + +/** + * Compute the trace of a binary field element. Computes c = Tr(a). + * + * @param[in] A - the binary field element. + * @return the trace of the binary field element. + */ +#if FB_TRC == BASIC +#define fb_trc(A) fb_trc_basic(A) +#elif FB_TRC == QUICK +#define fb_trc(A) fb_trc_quick(A) +#endif + +/** + * Solves a quadratic equation for c, Tr(a) = 0. Computes c such that + * c^2 + c = a. + * + * @param[out] C - the result. + * @param[in] A - the binary field element. + */ +#if FB_SLV == BASIC +#define fb_slv(C, A) fb_slv_basic(C, A) +#elif FB_SLV == QUICK +#define fb_slv(C, A) fb_slv_quick(C, A) +#endif + +/** + * Inverts a binary field element. Computes c = a^{-1}. + * + * @param[out] C - the result. + * @param[in] A - the binary field element to invert. + */ +#if FB_INV == BASIC +#define fb_inv(C, A) fb_inv_basic(C, A) +#elif FB_INV == BINAR +#define fb_inv(C, A) fb_inv_binar(C, A) +#elif FB_INV == EXGCD +#define fb_inv(C, A) fb_inv_exgcd(C, A) +#elif FB_INV == ALMOS +#define fb_inv(C, A) fb_inv_almos(C, A) +#elif FB_INV == ITOHT +#define fb_inv(C, A) fb_inv_itoht(C, A) +#elif FB_INV == BRUCH +#define fb_inv(C, A) fb_inv_bruch(C, A) +#elif FB_INV == CTAIA +#define fb_inv(C, A) fb_inv_ctaia(C, A) +#elif FB_INV == LOWER +#define fb_inv(C, A) fb_inv_lower(C, A) +#endif + +/** + * Exponentiates a binary field element. Computes c = a^b. + * + * @param[out] C - the result. + * @param[in] A - the basis. + * @param[in] B - the exponent. + */ +#if FB_EXP == BASIC +#define fb_exp(C, A, B) fb_exp_basic(C, A, B) +#elif FB_EXP == SLIDE +#define fb_exp(C, A, B) fb_exp_slide(C, A, B) +#elif FB_EXP == MONTY +#define fb_exp(C, A, B) fb_exp_monty(C, A, B) +#endif + +/** + * Precomputed the table for repeated squaring/square-root. + * + * @param[out] T - the table. + * @param[in] B - the exponent. + */ +#if FB_ITR == BASIC +#define fb_itr_pre(T, B) (void)(T), (void)(B) +#elif FB_ITR == QUICK +#define fb_itr_pre(T, B) fb_itr_pre_quick(T, B) +#endif + +/** + * Computes the repeated Frobenius (squaring) or inverse Frobenius (square-root) + * of a binary field element. If the number of arguments is 3, then simple + * consecutive squaring/square-root is used. If the number of arguments if 4, + * then a table-based method is used and the fourth argument is + * a pointer fo the precomputed table. The variant with 4 arguments + * should be used when several 2^k/2^-k powers are computed with the same + * k. Computes c = a^(2^b), where b can be positive or negative. + * + * @param[out] C - the result. + * @param[in] A - the binary field element to exponentiate. + * @param[in] B - the exponent. + * @param[in] ... - the modulus and an optional argument. + */ +#define fb_itr(C, A, ...) RLC_CAT(fb_itr, RLC_OPT(__VA_ARGS__)) (C, A, __VA_ARGS__) + +/** + * Reduces a multiple precision integer modulo another integer. This macro + * should not be called directly. Use bn_mod() with 4 arguments instead. + * + * @param[out] C - the result. + * @param[in] A - the binary field element to exponentiate. + * @param[in] B - the exponent. + * @param[in] T - the precomputed table for the exponent. + */ +#if FB_ITR == BASIC +#define fb_itr_imp(C, A, B, T) fb_itr_basic(C, A, B) +#elif FB_ITR == QUICK +#define fb_itr_imp(C, A, B, T) fb_itr_quick(C, A, T) +#endif +/*============================================================================*/ + /* Function prototypes */ +/*============================================================================*/ +/** + * Initializes the binary field arithmetic layer. + */ +void fb_poly_init(void); + +/** + * Finalizes the binary field arithmetic layer. + */ +void fb_poly_clean(void); + +/** + * Returns the irreducible polynomial f(z) configured for the binary field. + * + * @return the irreducible polynomial. + */ +dig_t *fb_poly_get(void); + +/** + * Configures the irreducible polynomial of the binary field as a dense + * polynomial. + * + * @param[in] f - the new irreducible polynomial. + */ +void fb_poly_set_dense(const fb_t f); + +/** + * Configures a trinomial as the irreducible polynomial by its non-zero + * coefficients. The other coefficients are RLC_FB_BITS and 0. + * + * @param[in] a - the second coefficient. + */ +void fb_poly_set_trino(int a); + +/** + * Configures a pentanomial as the binary field modulo by its non-zero + * coefficients. The other coefficients are RLC_FB_BITS and 0. + * + * @param[in] a - the second coefficient. + * @param[in] b - the third coefficient. + * @param[in] c - the fourth coefficient. + */ +void fb_poly_set_penta(int a, int b, int c); + +/** + * Returns the square root of z. + * + * @return the square root of z. + */ +dig_t *fb_poly_get_srz(void); + +/** + * Returns sqrt(z) * (i represented as a polynomial). + * + * @return the precomputed result. + */ +const dig_t *fb_poly_tab_srz(int i); + +/** + * Returns a table for accelerating repeated squarings. + * + * @param the number of the table. + * @return the precomputed result. + */ +const fb_t *fb_poly_tab_sqr(int i); + +/** + * Returns an addition chain for (RLC_FB_BITS - 1). + * + * @param[out] len - the number of elements in the addition chain. + * + * @return a pointer to the addition chain. + */ +const int *fb_poly_get_chain(int *len); + +/** + * Returns the non-zero coefficients of the configured trinomial or pentanomial. + * If b is -1, the irreducible polynomial configured is a trinomial. + * The other coefficients are RLC_FB_BITS and 0. + * + * @param[out] a - the second coefficient. + * @param[out] b - the third coefficient. + * @param[out] c - the fourth coefficient. + */ +void fb_poly_get_rdc(int *a, int *b, int *c); + +/** + * Returns the non-zero bits used to compute the trace function. The -1 + * coefficient is the last coefficient. + * + * @param[out] a - the first coefficient. + * @param[out] b - the second coefficient. + * @param[out] c - the third coefficient. + */ +void fb_poly_get_trc(int *a, int *b, int *c); + +/** + * Returns the table of precomputed half-traces. + * + * @return the table of half-traces. + */ +const dig_t *fb_poly_get_slv(void); + +/** + * Assigns a standard irreducible polynomial as modulo of the binary field. + * + * @param[in] param - the standardized polynomial identifier. + */ +void fb_param_set(int param); + +/** + * Configures some finite field parameters for the current security level. + */ +void fb_param_set_any(void); + +/** + * Prints the currently configured irreducible polynomial. + */ +void fb_param_print(void); + +/** + * Adds a binary field element and the irreducible polynomial. Computes + * c = a + f(z). + * + * @param[out] c - the destination. + * @param[in] a - the binary field element. + */ +void fb_poly_add(fb_t c, const fb_t a); + +/** + * Copies the second argument to the first argument. + * + * @param[out] c - the result. + * @param[in] a - the binary field element to copy. + */ +void fb_copy(fb_t c, const fb_t a); + +/** + * Negates a binary field element. + * + * @param[out] c - the result. + * @param[out] a - the binary field element to negate. + */ +void fb_neg(fb_t c, const fb_t a); + +/** + * Assigns zero to a binary field element. + * + * @param[out] a - the binary field element to assign. + */ +void fb_zero(fb_t a); + +/** + * Tests if a binary field element is zero or not. + * + * @param[in] a - the binary field element to test. + * @return 1 if the argument is zero, 0 otherwise. + */ +int fb_is_zero(const fb_t a); + +/** + * Reads the bit stored in the given position on a binary field element. + * + * @param[in] a - the binary field element. + * @param[in] bit - the bit position. + * @return the bit value. + */ +int fb_get_bit(const fb_t a, int bit); + +/** + * Stores a bit in a given position on a binary field element. + * + * @param[out] a - the binary field element. + * @param[in] bit - the bit position. + * @param[in] value - the bit value. + */ +void fb_set_bit(fb_t a, int bit, int value); + +/** + * Assigns a small positive polynomial to a binary field element. + * + * The degree of the polynomial must be smaller than RLC_DIG. + * + * @param[out] c - the result. + * @param[in] a - the small polynomial to assign. + */ +void fb_set_dig(fb_t c, dig_t a); + +/** + * Returns the number of bits of a binary field element. + * + * @param[in] a - the binary field element. + * @return the number of bits. + */ +int fb_bits(const fb_t a); + +/** + * Assigns a random value to a binary field element. + * + * @param[out] a - the binary field element to assign. + */ +void fb_rand(fb_t a); + +/** + * Prints a binary field element to standard output. + * + * @param[in] a - the binary field element to print. + */ +void fb_print(const fb_t a); + +/** + * Returns the number of digits in radix necessary to store a binary field + * element. The radix must be a power of 2 included in the interval [2, 64]. + * + * @param[in] a - the binary field element. + * @param[in] radix - the radix. + * @throw ERR_NO_VALID - if the radix is invalid. + * @return the number of digits in the given radix. + */ +int fb_size_str(const fb_t a, int radix); + +/** + * Reads a binary field element from a string in a given radix. The radix must + * be a power of 2 included in the interval [2, 64]. + * + * @param[out] a - the result. + * @param[in] str - the string. + * @param[in] len - the size of the string. + * @param[in] radix - the radix. + * @throw ERR_NO_VALID - if the radix is invalid. + * @throw ERR_NO_BUFFER - if the string is too long. + */ +void fb_read_str(fb_t a, const char *str, int len, int radix); + +/** + * Writes a binary field element to a string in a given radix. The radix must + * be a power of 2 included in the interval [2, 64]. + * + * @param[out] str - the string. + * @param[in] len - the buffer capacity. + * @param[in] a - the binary field element to write. + * @param[in] radix - the radix. + * @throw ERR_NO_VALID - if the radix is invalid. + * @throw ERR_NO_BUFFER - if the buffer capacity is insufficient. + */ +void fb_write_str(char *str, int len, const fb_t a, int radix); + +/** + * Reads a binary field element from a byte vector in big-endian format. + * + * @param[out] a - the result. + * @param[in] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @throw ERR_NO_BUFFER - if the buffer capacity is not RLC_FP_BYTES. + */ +void fb_read_bin(fb_t a, const uint8_t *bin, int len); + +/** + * Writes a binary field element to a byte vector in big-endian format. + * + * @param[out] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @param[in] a - the binary field element to write. + * @throw ERR_NO_BUFFER - if the buffer capacity is not RLC_FP_BYTES. + */ +void fb_write_bin(uint8_t *bin, int len, const fb_t a); + +/** + * Returns the result of a comparison between two binary field elements. + * + * @param[in] a - the first binary field element. + * @param[in] b - the second binary field element. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fb_cmp(const fb_t a, const fb_t b); + +/** + * Returns the result of a comparison between a binary field element + * and a small binary field element. + * + * @param[in] a - the binary field element. + * @param[in] b - the small binary field element. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fb_cmp_dig(const fb_t a, dig_t b); + +/** + * Adds two binary field elements. Computes c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the first binary field element to add. + * @param[in] b - the second binary field element to add. + */ +void fb_add(fb_t c, const fb_t a, const fb_t b); + +/** + * Adds a binary field element and a small binary field element. + * Computes c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the binary field element to add. + * @param[in] b - the small binary field element to add. + */ +void fb_add_dig(fb_t c, const fb_t a, dig_t b); + +/** + * Multiples two binary field elements using Shift-and-add multiplication. + * + * @param[out] c - the result. + * @param[in] a - the first binary field element to multiply. + * @param[in] b - the second binary field element to multiply. + */ +void fb_mul_basic(fb_t c, const fb_t a, const fb_t b); + +/** + * Multiples two binary field elements using multiplication integrated with + * modular reduction. + * + * @param[out] c - the result. + * @param[in] a - the first binary field element to multiply. + * @param[in] b - the second binary field element to multiply. + */ +void fb_mul_integ(fb_t c, const fb_t a, const fb_t b); + +/** + * Multiples two binary field elements using Lopez-Dahab multiplication. + * + * @param[out] c - the result. + * @param[in] a - the first binary field element to multiply. + * @param[in] b - the second binary field element to multiply. + */ +void fb_mul_lodah(fb_t c, const fb_t a, const fb_t b); + +/** + * Multiplies a binary field element by a small binary field element. + * + * @param[out] c - the result. + * @param[in] a - the binary field element. + * @param[in] b - the small binary field element to multiply. + */ +void fb_mul_dig(fb_t c, const fb_t a, dig_t b); + +/** + * Multiples two binary field elements using Karatsuba multiplication. + * + * @param[out] c - the result. + * @param[in] a - the first binary field element. + * @param[in] b - the second binary field element. + */ +void fb_mul_karat(fb_t c, const fb_t a, const fb_t b); + +/** + * Squares a binary field element using bit-manipulation squaring. + * + * @param[out] c - the result. + * @param[in] a - the binary field element to square. + */ +void fb_sqr_basic(fb_t c, const fb_t a); + +/** + * Squares a binary field element with integrated modular reduction. + * + * @param[out] c - the result. + * @param[in] a - the binary field element to square. + */ +void fb_sqr_integ(fb_t c, const fb_t a); + +/** + * Squares a binary field element using table-based squaring. + * + * @param[out] c - the result. + * @param[in] a - the binary field element to square. + */ +void fb_sqr_quick(fb_t c, const fb_t a); + +/** + * Shifts a binary field element to the left. Computes c = a * z^bits mod f(z). + * + * @param[out] c - the result. + * @param[in] a - the binary field element to shift. + * @param[in] bits - the number of bits to shift. + */ +void fb_lsh(fb_t c, const fb_t a, int bits); + +/** +* Shifts a binary field element to the right. Computes c = a / (z^bits). + * + * @param[out] c - the result. + * @param[in] a - the binary field element to shift. + * @param[in] bits - the number of bits to shift. + */ +void fb_rsh(fb_t c, const fb_t a, int bits); + +/** + * Reduces a multiplication result modulo an irreducible polynomial using + * shift-and-add modular reduction. + * + * @param[out] c - the result. + * @param[in] a - the multiplication result to reduce. + */ +void fb_rdc_basic(fb_t c, dv_t a); + +/** + * Reduces a multiplication result modulo a trinomial or pentanomial. + * + * @param[out] c - the result. + * @param[in] a - the multiplication result to reduce. + */ +void fb_rdc_quick(fb_t c, dv_t a); + +/** + * Extracts the square root of a binary field element using repeated squaring. + * Computes c = a^{1/2}. + * + * @param[out] c - the result. + * @param[in] a - the binary field element to take a square root. + */ +void fb_srt_basic(fb_t c, const fb_t a); + +/** + * Extracts the square root of a binary field element using a fast square root + * extraction algorithm. + * + * @param[out] c - the result. + * @param[in] a - the binary field element to take a square root. + */ +void fb_srt_quick(fb_t c, const fb_t a); + +/** + * Computes the trace of a binary field element using repeated squaring. + * Returns Tr(a). + * + * @param[in] a - the binary field element. + * @return the trace of the binary field element. + */ +dig_t fb_trc_basic(const fb_t a); + +/** + * Computes the trace of a binary field element using a fast trace computation + * algorithm. Returns Tr(a). + * + * @param[in] a - the binary field element. + * @return the trace of the binary field element. + */ +dig_t fb_trc_quick(const fb_t a); + +/** + * Inverts a binary field element using Fermat's Little Theorem. + * + * @param[out] c - the result. + * @param[in] a - the binary field element to invert. + * @throw ERR_NO_VALID - if the field element is not invertible. + */ +void fb_inv_basic(fb_t c, const fb_t a); + +/** + * Inverts a binary field element using the binary method. + * + * @param[out] c - the result. + * @param[in] a - the binary field element to invert. + * @throw ERR_NO_VALID - if the field element is not invertible. + */ +void fb_inv_binar(fb_t c, const fb_t a); + +/** + * Inverts a binary field element using the Extended Euclidean algorithm. + * + * @param[out] c - the result. + * @param[in] a - the binary field element to invert. + * @throw ERR_NO_VALID - if the field element is not invertible. + */ +void fb_inv_exgcd(fb_t c, const fb_t a); + +/** + * Inverts a binary field element using the Almost Inverse algorithm. + * + * @param[out] c - the result. + * @param[in] a - the binary field element to invert. + * @throw ERR_NO_VALID - if the field element is not invertible. + */ +void fb_inv_almos(fb_t c, const fb_t a); + +/** + * Inverts a binary field element using Itoh-Tsuji inversion. + * + * @param[out] c - the result. + * @param[in] a - the binary field element to invert. + * @throw ERR_NO_VALID - if the field element is not invertible. + */ +void fb_inv_itoht(fb_t c, const fb_t a); + +/** + * Inverts a binary field element using the hardware-friendly + * Brunner-Curiger-Hofstetter algorithm. + * + * @param[out] c - the result. + * @param[in] a - the binary field element to invert. + * @throw ERR_NO_VALID - if the field element is not invertible. + */ +void fb_inv_bruch(fb_t c, const fb_t a); + +/** + * Inverts a binary field element in constant-time using + * the Wu-Wu-Shieh-Hwang algorithm. + * + * @param[out] c - the result. + * @param[in] a - the binary field element to invert. + * @throw ERR_NO_VALID - if the field element is not invertible. + */ +void fb_inv_ctaia(fb_t c, const fb_t a); + +/** + * Inverts a binary field element using a direct call to the lower layer. + * + * @param[out] c - the result. + * @param[in] a - the binary field element to invert. + * @throw ERR_NO_VALID - if the field element is not invertible. + */ +void fb_inv_lower(fb_t c, const fb_t a); + +/** + * Inverts multiple binary field elements. + * + * @param[out] c - the result. + * @param[in] a - the binary field elements to invert. + * @param[in] n - the number of elements. + */ +void fb_inv_sim(fb_t *c, const fb_t *a, int n); + +/** + * Exponentiates a binary field element through consecutive squaring. Computes + * c = a^(2^b). + * + * @param[out] c - the result. + * @param[in] a - the basis. + * @param[in] b - the exponent. + */ +void fb_exp_2b(fb_t c, const fb_t a, int b); + +/** + * Exponentiates a binary field element using the binary + * method. + * + * @param[out] c - the result. + * @param[in] a - the basis. + * @param[in] b - the exponent. + */ +void fb_exp_basic(fb_t c, const fb_t a, const bn_t b); + +/** + * Exponentiates a binary field element using the sliding window method. + * + * @param[out] c - the result. + * @param[in] a - the basis. + * @param[in] b - the exponent. + */ +void fb_exp_slide(fb_t c, const fb_t a, const bn_t b); + +/** + * Exponentiates a binary field element using the constant-time Montgomery + * powering ladder method. + * + * @param[out] c - the result. + * @param[in] a - the basis. + * @param[in] b - the exponent. + */ +void fb_exp_monty(fb_t c, const fb_t a, const bn_t b); + +/** + * Solves a quadratic equation for a, Tr(a) = 0 by repeated squarings and + * additions. + * + * @param[out] c - the result. + * @param[in] a - the binary field element to solve. + */ +void fb_slv_basic(fb_t c, const fb_t a); + +/** + * Solves a quadratic equation for a, Tr(a) = 0 with precomputed half-traces. + * + * @param[out] c - the result. + * @param[in] a - the binary field element to solve. + */ +void fb_slv_quick(fb_t c, const fb_t a); + +/** + * Computes the iterated squaring/square-root of a binary field element by + * consecutive squaring/square-root. Computes c = a^(2^b). + * + * @param[out] c - the result. + * @param[in] a - the basis. + * @param[in] b - the exponent. + */ +void fb_itr_basic(fb_t c, const fb_t a, int b); + +/** + * Precomputes a table for iterated squaring/square-root of a binary field + * element. + * + * @param[out] t - the precomputed table. + * @param[in] b - the exponent. + */ +void fb_itr_pre_quick(fb_t *t, int b); + +/** + * Computes the iterated squaring/square-root of a binary field element by + * a table based method. Computes c = a^(2^b). + * + * @param[out] c - the result. + * @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); + +#endif /* !RLC_FB_H */ diff --git a/bls/contrib/relic/include/relic_fbx.h b/bls/contrib/relic/include/relic_fbx.h new file mode 100644 index 00000000..8b125522 --- /dev/null +++ b/bls/contrib/relic/include/relic_fbx.h @@ -0,0 +1,204 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 . + */ + +/** + * @defgroup fbx Binary field extensions. + */ + +/** + * @file + * + * Interface of the module for extension field arithmetic over binary fields. + * + * @ingroup fbx + */ + +#ifndef RLC_FBX_H +#define RLC_FBX_H + +#include "relic_fb.h" +#include "relic_types.h" + +/*============================================================================*/ +/* Type definitions */ +/*============================================================================*/ + +/** + * Represents a quadratic extension binary field element. + * + * This extension field is constructed with the basis {1, s}, where s is a + * quadratic non-residue in the binary field. + */ +typedef fb_t fb2_t[2]; + +/*============================================================================*/ +/* Macro definitions */ +/*============================================================================*/ + +/** + * Initializes a quadratic extension binary field with a null value. + * + * @param[out] A - the quadratic extension element to initialize. + */ +#define fb2_null(A) \ + fb_null(A[0]); fb_null(A[1]); \ + +/** + * Calls a function to allocate a quadratic extension binary field element. + * + * @param[out] A - the new quadratic extension field element. + */ +#define fb2_new(A) \ + fb_new(A[0]); fb_new(A[1]); \ + +/** + * Calls a function to free a quadratic extension binary field element. + * + * @param[out] A - the quadratic extension field element to free. + */ +#define fb2_free(A) \ + fb_free(A[0]); fb_free(A[1]); \ + +/** + * Copies the second argument to the first argument. + * + * @param[out] C - the result. + * @param[in] A - the quadratic extension field element to copy. + */ +#define fb2_copy(C, A) \ + fb_copy(C[0], A[0]); fb_copy(C[1], A[1]); \ + +/** + * Negates a quadratic extension field element. + * + * f@param[out] C - the result. + * @param[out] A - the quadratic extension field element to negate. + */ +#define fb2_neg(C, A) \ + fb_neg(C[0], A[0]); fb_neg(C[1], A[1]); \ + +/** + * Assigns zero to a quadratic extension field element. + * + * @param[out] A - the quadratic extension field element to zero. + */ +#define fb2_zero(A) \ + fb_zero(A[0]); fb_zero(A[1]); \ + +/** + * Tests if a quadratic extension field element is zero or not. + * + * @param[in] A - the quadratic extension field element to test. + * @return 1 if the argument is zero, 0 otherwise. + */ +#define fb2_is_zero(A) \ + (fb_is_zero(A[0]) && fb_is_zero(A[1])) \ + +/** + * Assigns a random value to a quadratic extension field element. + * + * @param[out] A - the quadratic extension field element to assign. + */ +#define fb2_rand(A) \ + fb_rand(A[0]); fb_rand(A[1]); \ + +/** + * Prints a quadratic extension field element to standard output. + * + * @param[in] A - the quadratic extension field element to print. + */ +#define fb2_print(A) \ + fb_print(A[0]); fb_print(A[1]); \ + +/** + * Returns the result of a comparison between two quadratic extension field + * elements + * + * @param[in] A - the first quadratic extension field element. + * @param[in] B - the second quadratic extension field element. + * @return RLC_NE if a != b, RLC_EQ if a == b. + */ +#define fb2_cmp(A, B) \ + ((fb_cmp(A[0], B[0]) == RLC_EQ) && (fb_cmp(A[1], B[1]) == RLC_EQ) \ + ? RLC_EQ : RLC_NE) \ + +/** + * Adds two quadratic extension field elements. Computes c = a + b. + * + * @param[out] C - the result. + * @param[in] A - the first quadratic extension field element. + * @param[in] B - the second quadratic extension field element. + */ +#define fb2_add(C, A, B) \ + fb_add(C[0], A[0], B[0]); fb_add(C[1], A[1], B[1]); \ + +/*============================================================================*/ +/* Function prototypes */ +/*============================================================================*/ + +/** + * Multiples two quadratic extension field elements. Computes c = a * b. + * + * @param[out] c - the result. + * @param[in] a - the quadratic extension binary field element. + * @param[in] b - the quadratic extension binary field element. + */ +void fb2_mul(fb2_t c, fb2_t a, fb2_t b); + + /** + * Multiples a quadratic extension field element by a quadratic non-residue. + * Computes c = a * s. + * + * @param[out] c - the result. + * @param[in] a - the quadratic extension binary field element. + * @param[in] b - the quadratic extension binary field element. + */ + void fb2_mul_nor(fb2_t c, fb2_t a); + +/** + * Computes the square of a quadratic extension field element. Computes + * c = a * a. + * + * @param[out] c - the result. + * @param[in] a - the binary field element to square. + */ +void fb2_sqr(fb2_t c, fb2_t a); + +/** + * Solves a quadratic equation for c, Tr(a) = 0. Computes c such that + * c^2 + c = a. + * + * @param[out] c - the result. + * @param[in] a - the quadratic extension field element. + */ +void fb2_slv(fb2_t c, fb2_t a); + +/** + * Inverts a quadratic extension field element. Computes c = a^{-1}. + * + * @param[out] c - the result. + * @param[in] a - the quadratic extension field element to invert. + */ +void fb2_inv(fb2_t c, fb2_t a); + +#endif /* !RLC_FBX_H */ diff --git a/bls/contrib/relic/include/relic_fp.h b/bls/contrib/relic/include/relic_fp.h new file mode 100644 index 00000000..abdd090e --- /dev/null +++ b/bls/contrib/relic/include/relic_fp.h @@ -0,0 +1,1088 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 . + */ + +/** + * @defgroup fp Prime field arithmetic + */ + +/** + * @file + * + * Interface of the module for prime field arithmetic. + * + * @ingroup fp + */ + +#ifndef RLC_FP_H +#define RLC_FP_H + +#include "relic_dv.h" +#include "relic_bn.h" +#include "relic_conf.h" +#include "relic_types.h" + +/*============================================================================*/ +/* Constant definitions */ +/*============================================================================*/ + +/** + * Precision in bits of a prime field element. + */ +#define RLC_FP_BITS ((int)FP_PRIME) + +/** + * Size in digits of a block sufficient to store a prime field element. + */ +#define RLC_FP_DIGS ((int)RLC_CEIL(RLC_FP_BITS, RLC_DIG)) + +/** + * Size in bytes of a block sufficient to store a binary field element. + */ +#define RLC_FP_BYTES ((int)RLC_CEIL(RLC_FP_BITS, 8)) + +/* + * Finite field identifiers. + */ +enum { + /** SECG 160-bit fast reduction prime. */ + SECG_160 = 1, + /** SECG 160-bit denser reduction prime. */ + SECG_160D, + /** NIST 192-bit fast reduction prime. */ + NIST_192, + /** SECG 192-bit denser reduction prime. */ + SECG_192, + /** Curve22103 221-bit prime modulus. */ + PRIME_22103, + /** NIST 224-bit fast reduction polynomial. */ + NIST_224, + /** SECG 224-bit denser reduction prime. */ + SECG_224, + /** Curve4417 226-bit prime modulus. */ + PRIME_22605, + /* Curve1174 251-bit prime modulus. */ + PRIME_25109, + /** Curve25519 255-bit prime modulus. */ + PRIME_25519, + /** NIST 256-bit fast reduction polynomial. */ + NIST_256, + /** Brainpool random 256-bit prime. */ + BSI_256, + /** SECG 256-bit denser reduction prime. */ + SECG_256, + /** Curve67254 382-bit prime modulus. */ + PRIME_382105, + /** Curve383187 383-bit prime modulus. */ + PRIME_383187, + /** NIST 384-bit fast reduction polynomial. */ + NIST_384, + /** Curve511187 511-bit prime modulus. */ + PRIME_511187, + /** NIST 521-bit fast reduction polynomial. */ + NIST_521, + /** 158-bit prime for BN curve. */ + BN_158, + /** 254-bit prime provided in Nogami et al. for BN curves. */ + BN_254, + /** 256-bit prime provided in Barreto et al. for BN curves. */ + BN_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, + /** 446-bit prime provided by Barreto for BN curve. */ + BN_446, + /** 446-bit prime for BLS curve of embedding degree 12. */ + B12_446, + /** 455-bit prime for BLS curve of embedding degree 12. */ + B12_455, + /** 477-bit prime for BLS curve of embedding degree 24. */ + B24_477, + /** 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, + /** 569-bit prime for KSS curve with embedding degree 54. */ + K54_569, + /** 575-bit prime for BLS curve with embedding degree 48. */ + B48_575, + /** 638-bit prime provided in Barreto et al. for BN curve. */ + BN_638, + /** 638-bit prime for BLS curve with embedding degree 12. */ + B12_638, + /** 1536-bit prime for supersingular curve with embedding degree k = 2. */ + SS_1536, +}; + +/** + * Constant used to indicate that there's some room left in the storage of + * prime field elements. This can be used to avoid carries. + */ +#if ((FP_PRIME % WSIZE) != 0) && ((FP_PRIME % WSIZE) <= (WSIZE - 2)) +#if ((2 * FP_PRIME % WSIZE) != 0) && ((2 * FP_PRIME % WSIZE) <= (WSIZE - 2)) +#define RLC_FP_ROOM +#else +#undef RLC_FP_ROOM +#endif +#else +#undef RLC_FP_ROOM +#endif + +/*============================================================================*/ +/* Type definitions */ +/*============================================================================*/ + +/** + * Represents a prime field element. + * + * A field element is represented as a digit vector. These digits are organized + * in little-endian format, that is, the least significant digits are + * stored in the first positions of the vector. + */ +#if ALLOC == AUTO +typedef rlc_align dig_t fp_t[RLC_FP_DIGS + RLC_PAD(RLC_FP_BYTES)/(RLC_DIG / 8)]; +#else +typedef dig_t *fp_t; +#endif + +/** + * Represents a prime field element with automatic memory allocation. + */ +typedef rlc_align dig_t fp_st[RLC_FP_DIGS + RLC_PAD(RLC_FP_BYTES)/(RLC_DIG / 8)]; + +/*============================================================================*/ +/* Macro definitions */ +/*============================================================================*/ + +/** + * Initializes a binary field element with a null value. + * + * @param[out] A - the binary field element to initialize. + */ +#if ALLOC == AUTO +#define fp_null(A) /* empty */ +#else +#define fp_null(A) A = NULL; +#endif + +/** + * Calls a function to allocate and initialize a prime field element. + * + * @param[out] A - the new prime field element. + */ +#if ALLOC == DYNAMIC +#define fp_new(A) dv_new_dynam((dv_t *)&(A), RLC_FP_DIGS) +#elif ALLOC == AUTO +#define fp_new(A) /* empty */ +#elif ALLOC == STACK +#define fp_new(A) \ + A = (dig_t *)alloca(RLC_FP_BYTES + RLC_PAD(RLC_FP_BYTES)); \ + A = (dig_t *)RLC_ALIGN(A); \ + +#endif + +/** + * Calls a function to clean and free a prime field element. + * + * @param[out] A - the prime field element to clean and free. + */ +#if ALLOC == DYNAMIC +#define fp_free(A) dv_free_dynam((dv_t *)&(A)) +#elif ALLOC == AUTO +#define fp_free(A) /* empty */ +#elif ALLOC == STACK +#define fp_free(A) A = NULL; +#endif + +/** + * Adds two prime field elements. Computes c = a + b. + * + * @param[out] C - the result. + * @param[in] A - the first prime field element. + * @param[in] B - the second prime field element. + */ +#if FP_ADD == BASIC +#define fp_add(C, A, B) fp_add_basic(C, A, B) +#elif FP_ADD == INTEG +#define fp_add(C, A, B) fp_add_integ(C, A, B) +#endif + +/** + * Subtracts a prime field element from another. Computes C = A - B. + * + * @param[out] C - the result. + * @param[in] A - the first prime field element. + * @param[in] B - the second prime field element. + */ +#if FP_ADD == BASIC +#define fp_sub(C, A, B) fp_sub_basic(C, A, B) +#elif FP_ADD == INTEG +#define fp_sub(C, A, B) fp_sub_integ(C, A, B) +#endif + +/** + * Negates a prime field element from another. Computes C = -A. + * + * @param[out] C - the result. + * @param[in] A - the prime field element to negate. + */ +#if FP_ADD == BASIC +#define fp_neg(C, A) fp_neg_basic(C, A) +#elif FP_ADD == INTEG +#define fp_neg(C, A) fp_neg_integ(C, A) +#endif + +/** + * Doubles a prime field element. Computes C = A + A. + * + * @param[out] C - the result. + * @param[in] A - the first prime field element. + */ +#if FP_ADD == BASIC +#define fp_dbl(C, A) fp_dbl_basic(C, A) +#elif FP_ADD == INTEG +#define fp_dbl(C, A) fp_dbl_integ(C, A) +#endif + +/** + * Halves a prime field element. Computes C = A/2. + * + * @param[out] C - the result. + * @param[in] A - the first prime field element. + */ +#if FP_ADD == BASIC +#define fp_hlv(C, A) fp_hlv_basic(C, A) +#elif FP_ADD == INTEG +#define fp_hlv(C, A) fp_hlv_integ(C, A) +#endif + +/** + * Multiples two prime field elements. Computes C = A * B. + * + * @param[out] C - the result. + * @param[in] A - the first prime field element. + * @param[in] B - the second prime field element. + */ +#if FP_KARAT > 0 +#define fp_mul(C, A, B) fp_mul_karat(C, A, B) +#elif FP_MUL == BASIC +#define fp_mul(C, A, B) fp_mul_basic(C, A, B) +#elif FP_MUL == COMBA +#define fp_mul(C, A, B) fp_mul_comba(C, A, B) +#elif FP_MUL == INTEG +#define fp_mul(C, A, B) fp_mul_integ(C, A, B) +#endif + +/** + * Squares a prime field element. Computes C = A * A. + * + * @param[out] C - the result. + * @param[in] A - the prime field element to square. + */ +#if FP_KARAT > 0 +#define fp_sqr(C, A) fp_sqr_karat(C, A) +#elif FP_SQR == BASIC +#define fp_sqr(C, A) fp_sqr_basic(C, A) +#elif FP_SQR == COMBA +#define fp_sqr(C, A) fp_sqr_comba(C, A) +#elif FP_SQR == MULTP +#define fp_sqr(C, A) fp_mul(C, A, A) +#elif FP_SQR == INTEG +#define fp_sqr(C, A) fp_sqr_integ(C, A) +#endif + +/** + * Reduces a multiplication result modulo a prime field order. Computes + * C = A mod p. + * + * @param[out] C - the result. + * @param[in] A - the multiplication result to reduce. + */ +#if FP_RDC == BASIC +#define fp_rdc(C, A) fp_rdc_basic(C, A) +#elif FP_RDC == MONTY +#define fp_rdc(C, A) fp_rdc_monty(C, A) +#elif FP_RDC == QUICK +#define fp_rdc(C, A) fp_rdc_quick(C, A) +#endif + +/** + * Reduces a multiplication result modulo a prime field order using Montgomery + * modular reduction. + * + * @param[out] C - the result. + * @param[in] A - the multiplication result to reduce. + */ +#if FP_MUL == BASIC +#define fp_rdc_monty(C, A) fp_rdc_monty_basic(C, A) +#else +#define fp_rdc_monty(C, A) fp_rdc_monty_comba(C, A) +#endif + +/** + * Inverts a prime field element. Computes C = A^{-1}. + * + * @param[out] C - the result. + * @param[in] A - the prime field element to invert. + */ +#if FP_INV == BASIC +#define fp_inv(C, A) fp_inv_basic(C, A) +#elif FP_INV == BINAR +#define fp_inv(C, A) fp_inv_binar(C, A) +#elif FP_INV == MONTY +#define fp_inv(C, A) fp_inv_monty(C, A) +#elif FP_INV == EXGCD +#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 == LOWER +#define fp_inv(C, A) fp_inv_lower(C, A) +#endif + +/** + * Exponentiates a prime field element. Computes C = A^B (mod p). + * + * @param[out] C - the result. + * @param[in] A - the basis. + * @param[in] B - the exponent. + */ +#if FP_EXP == BASIC +#define fp_exp(C, A, B) fp_exp_basic(C, A, B) +#elif FP_EXP == SLIDE +#define fp_exp(C, A, B) fp_exp_slide(C, A, B) +#elif FP_EXP == MONTY +#define fp_exp(C, A, B) fp_exp_monty(C, A, B) +#endif + +/*============================================================================*/ +/* Function prototypes */ +/*============================================================================*/ + +/** + * Initializes the prime field arithmetic layer. + */ +void fp_prime_init(void); + +/** + * Finalizes the prime field arithmetic layer. + */ +void fp_prime_clean(void); + +/** + * Returns the order of the prime field. + * + * @return the order of the prime field. + */ +const dig_t *fp_prime_get(void); + +/** + * Returns the additional value used for modular reduction. + * + * @return the additional value used for modular reduction. + */ +const dig_t *fp_prime_get_rdc(void); + +/** + * Returns the additional value used for conversion from multiple precision + * integer to prime field element. + * + * @return the additional value used for importing integers. + */ +const dig_t *fp_prime_get_conv(void); + +/** + * Returns the result of prime order mod 8. + * + * @return the result of prime order mod 8. + */ +dig_t fp_prime_get_mod8(void); + +/** + * Returns the prime stored in special form. The most significant bit is + * RLC_FP_BITS. + * + * @param[out] len - the number of returned bits, can be NULL. + * + * @return the prime represented by it non-zero bits. + */ +const int *fp_prime_get_sps(int *len); + +/** + * Returns a non-quadratic residue in the prime field. + * + * @return the non-quadratic residue. + */ +int fp_prime_get_qnr(void); + +/** + * Returns a non-cubic residue in the prime field. + * + * @return the non-cubic residue. + */ +int fp_prime_get_cnr(void); + +/** + * Returns the 2-adicity of the prime modulus. + * + * @return the 2-adicity of the modulus. + */ +int fp_prime_get_2ad(void); + +/** + * Returns the prime field parameter identifier. + * + * @return the parameter identifier. + */ +int fp_param_get(void); + +/** + * Assigns the prime field modulus to a non-sparse prime. + * + * @param[in] p - the new prime field modulus. + */ +void fp_prime_set_dense(const bn_t p); + +/** + * Assigns the prime field modulus to a special form sparse prime. + * + * @param[in] spars - the list of powers of 2 describing the prime. + * @param[in] len - the number of powers. + */ +void fp_prime_set_pmers(const int *spars, int len); + +/** +* Assigns the prime field modulus to a parametrization from a family of + * pairing-friendly curves. + */ +void fp_prime_set_pairf(const bn_t x, int pairf); + +/** + * Computes the constants needed for evaluating Frobenius maps in higher + * extension fields. + */ +void fp_prime_calc(void); + +/** + * Imports a multiple precision integer as a prime field element, doing the + * necessary conversion. + * + * @param[out] c - the result. + * @param[in] a - the multiple precision integer to import. + */ +void fp_prime_conv(fp_t c, const bn_t a); + +/** + * Imports a single digit as a prime field element, doing the necessary + * conversion. + * + * @param[out] c - the result. + * @param[in] a - the digit to import. + */ +void fp_prime_conv_dig(fp_t c, dig_t a); + +/** + * Exports a prime field element as a multiple precision integer, doing the + * necessary conversion. + * + * @param[out] c - the result. + * @param[in] a - the prime field element to export. + */ +void fp_prime_back(bn_t c, const fp_t a); + +/** + * Assigns a prime modulus based on its identifier. + */ +void fp_param_set(int param); + +/** + * Assigns any pre-defined parameter as the prime modulus. + * + * @return RLC_OK if no errors occurred; RLC_ERR otherwise. + */ +int fp_param_set_any(void); + +/** + * Assigns the order of the prime field to any non-sparse prime. + * + * @return RLC_OK if no errors occurred; RLC_ERR otherwise. + */ +int fp_param_set_any_dense(void); + +/** + * Assigns the order of the prime field to any sparse prime. + * + * @return RLC_OK if no errors occurred; RLC_ERR otherwise. + */ +int fp_param_set_any_pmers(void); + +/** + * Assigns the order of the prime field to any towering-friendly prime. + * + * @return RLC_OK if no errors occurred; RLC_ERR otherwise. + */ +int fp_param_set_any_tower(void); + +/** + * Prints the currently configured prime modulus. + */ +void fp_param_print(void); + +/** + * Returns the variable used to parametrize the given prime modulus. + * + * @param[out] x - the integer parameter. + */ +void fp_prime_get_par(bn_t x); + +/** + * Returns the absolute value of the variable used to parameterize the given + * prime modulus in sparse form. + * + * @param[out] len - the length of the representation. + */ +const int *fp_prime_get_par_sps(int *len); + +/** + * Returns the absolute value of the variable used to parameterize the currently + * configured prime modulus in sparse form. The first argument must be an array + * of size (RLC_TERMS + 1). + * + * @param[out] s - the parameter in sparse form. + * @param[out] len - the length of the parameter in sparse form. + * @throw ERR_NO_BUFFER - if the buffer capacity is insufficient. + * @throw ERR_NO_VALID - if the current configuration is invalid. + * @return the integer parameter in sparse form. + */ +void fp_param_get_sps(int *s, int *len); + +/** + * Copies the second argument to the first argument. + * + * @param[out] c - the result. + * @param[in] a - the prime field element to copy. + */ +void fp_copy(fp_t c, const fp_t a); + +/** + * Assigns zero to a prime field element. + * + * @param[out] a - the prime field element to asign. + */ +void fp_zero(fp_t a); + +/** + * Tests if a prime field element is zero or not. + * + * @param[in] a - the prime field element to test. + * @return 1 if the argument is zero, 0 otherwise. + */ +int fp_is_zero(const fp_t a); + +/** + * Tests if a prime field element is even or odd. + * + * @param[in] a - the prime field element to test. + * @return 1 if the argument is even, 0 otherwise. + */ +int fp_is_even(const fp_t a); + +/** + * Reads the bit stored in the given position on a prime field element. + * + * @param[in] a - the prime field element. + * @param[in] bit - the bit position. + * @return the bit value. + */ +int fp_get_bit(const fp_t a, int bit); + +/** + * Stores a bit in a given position on a prime field element. + * + * @param[out] a - the prime field element. + * @param[in] bit - the bit position. + * @param[in] value - the bit value. + */ +void fp_set_bit(fp_t a, int bit, int value); + +/** + * Assigns a small positive constant to a prime field element. + * + * The constant must fit on a multiple precision digit, or dig_t type using + * only the number of bits specified on RLC_DIG. + * + * @param[out] c - the result. + * @param[in] a - the constant to assign. + */ +void fp_set_dig(fp_t c, dig_t a); + +/** + * Returns the number of bits of a prime field element. + * + * @param[in] a - the prime field element. + * @return the number of bits. + */ +int fp_bits(const fp_t a); + +/** + * Assigns a random value to a prime field element. + * + * @param[out] a - the prime field element to assign. + */ +void fp_rand(fp_t a); + +/** + * Prints a prime field element to standard output. + * + * @param[in] a - the prime field element to print. + */ +void fp_print(const fp_t a); + +/** + * Returns the number of digits in radix necessary to store a multiple precision + * integer. The radix must be a power of 2 included in the interval [2, 64]. + * + * @param[in] a - the prime field element. + * @param[in] radix - the radix. + * @throw ERR_NO_VALID - if the radix is invalid. + * @return the number of digits in the given radix. + */ +int fp_size_str(const fp_t a, int radix); + +/** + * Reads a prime field element from a string in a given radix. The radix must + * be a power of 2 included in the interval [2, 64]. + * + * @param[out] a - the result. + * @param[in] str - the string. + * @param[in] len - the size of the string. + * @param[in] radix - the radix. + * @throw ERR_NO_VALID - if the radix is invalid. + */ +void fp_read_str(fp_t a, const char *str, int len, int radix); + +/** + * Writes a prime field element to a string in a given radix. The radix must + * be a power of 2 included in the interval [2, 64]. + * + * @param[out] str - the string. + * @param[in] len - the buffer capacity. + * @param[in] a - the prime field element to write. + * @param[in] radix - the radix. + * @throw ERR_BUFFER - if the buffer capacity is insufficient. + * @throw ERR_NO_VALID - if the radix is invalid. + */ +void fp_write_str(char *str, int len, const fp_t a, int radix); + +/** + * Reads a prime field element from a byte vector in big-endian format. + * + * @param[out] a - the result. + * @param[in] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @throw ERR_NO_BUFFER - if the buffer capacity is not RLC_FP_BYTES. + */ +void fp_read_bin(fp_t a, const uint8_t *bin, int len); + +/** + * Writes a prime field element to a byte vector in big-endian format. + * + * @param[out] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @param[in] a - the prime field element to write. + * @throw ERR_NO_BUFFER - if the buffer capacity is not RLC_FP_BYTES. + */ +void fp_write_bin(uint8_t *bin, int len, const fp_t a); + +/** + * Returns the result of a comparison between two prime field elements. + * + * @param[in] a - the first prime field element. + * @param[in] b - the second prime field element. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fp_cmp(const fp_t a, const fp_t b); + +/** + * Returns the result of a signed comparison between a prime field element + * and a digit. + * + * @param[in] a - the prime field element. + * @param[in] b - the digit. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fp_cmp_dig(const fp_t a, dig_t b); + +/** + * Adds two prime field elements using basic addition. Computes c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the first prime field element to add. + * @param[in] b - the second prime field element to add. + */ +void fp_add_basic(fp_t c, const fp_t a, const fp_t b); + +/** + * Adds two prime field elements with integrated modular reduction. Computes + * c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the first prime field element to add. + * @param[in] b - the second prime field element to add. + */ +void fp_add_integ(fp_t c, const fp_t a, const fp_t b); + +/** + * Adds a prime field element and a digit. Computes c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the first prime field element to add. + * @param[in] b - the digit to add. + */ +void fp_add_dig(fp_t c, const fp_t a, dig_t b); + +/** + * Subtracts a prime field element from another using basic subtraction. + * Computes c = a - b. + * + * @param[out] c - the result. + * @param[in] a - the prime field element. + * @param[in] b - the prime field element to subtract. + */ +void fp_sub_basic(fp_t c, const fp_t a, const fp_t b); + +/** + * Subtracts a prime field element from another with integrated modular + * reduction. Computes c = a - b. + * + * @param[out] c - the result. + * @param[in] a - the prime field element. + * @param[in] b - the prime field element to subtract. + */ +void fp_sub_integ(fp_t c, const fp_t a, const fp_t b); + +/** + * Subtracts a digit from a prime field element. Computes c = a - b. + * + * @param[out] c - the result. + * @param[in] a - the prime field element. + * @param[in] b - the digit to subtract. + */ +void fp_sub_dig(fp_t c, const fp_t a, dig_t b); + +/** + * Negates a prime field element using basic negation. + * + * @param[out] c - the result. + * @param[out] a - the prime field element to negate. + */ +void fp_neg_basic(fp_t c, const fp_t a); + +/** + * Negates a prime field element using integrated negation. + * + * @param[out] c - the result. + * @param[out] a - the prime field element to negate. + */ +void fp_neg_integ(fp_t c, const fp_t a); + +/** + * Doubles a prime field element using basic addition. + * + * @param[out] c - the result. + * @param[in] a - the first prime field element to add. + */ +void fp_dbl_basic(fp_t c, const fp_t a); + +/** + * Doubles a prime field element with integrated modular reduction. + * + * @param[out] c - the result. + * @param[in] a - the first prime field element to add. + */ +void fp_dbl_integ(fp_t c, const fp_t a); + +/** + * Halves a prime field element. + * + * @param[out] c - the result. + * @param[in] a - the prime field element to halve. + */ +void fp_hlv_basic(fp_t c, const fp_t a); + +/** + * Halves a prime field element with integrated modular reduction. + * + * @param[out] c - the result. + * @param[in] a - the prime field element to halve. + */ +void fp_hlv_integ(fp_t c, const fp_t a); + +/** + * Multiples two prime field elements using Schoolbook multiplication. + * + * @param[out] c - the result. + * @param[in] a - the first prime field element to multiply. + * @param[in] b - the second prime field element to multiply. + */ +void fp_mul_basic(fp_t c, const fp_t a, const fp_t b); + +/** + * Multiples two prime field elements using Comba multiplication. + * + * @param[out] c - the result. + * @param[in] a - the first prime field element to multiply. + * @param[in] b - the second prime field element to multiply. + */ +void fp_mul_comba(fp_t c, const fp_t a, const fp_t b); + +/** + * Multiples two prime field elements using multiplication integrated with + * modular reduction. + * + * @param[out] c - the result. + * @param[in] a - the first prime field element to multiply. + * @param[in] b - the second prime field element to multiply. + */ +void fp_mul_integ(fp_t c, const fp_t a, const fp_t b); + +/** + * Multiples two prime field elements using Karatsuba multiplication. + * + * @param[out] c - the result. + * @param[in] a - the first prime field element to multiply. + * @param[in] b - the second prime field element to multiply. + */ +void fp_mul_karat(fp_t c, const fp_t a, const fp_t b); + +/** + * Multiplies a prime field element by a digit. Computes c = a * b. + * + * @param[out] c - the result. + * @param[in] a - the prime field element. + * @param[in] b - the digit to multiply. + */ +void fp_mul_dig(fp_t c, const fp_t a, dig_t b); + +/** + * Squares a prime field element using Schoolbook squaring. + * + * @param[out] c - the result. + * @param[in] a - the prime field element to square. + */ +void fp_sqr_basic(fp_t c, const fp_t a); + +/** + * Squares a prime field element using Comba squaring. + * + * @param[out] c - the result. + * @param[in] a - the prime field element to square. + */ +void fp_sqr_comba(fp_t c, const fp_t a); + +/** + * Squares two prime field elements using squaring integrated with + * modular reduction. + * + * @param[out] c - the result. + * @param[in] a - the binary field element to square. + */ +void fp_sqr_integ(fp_t c, const fp_t a); + +/** + * Squares a prime field element using Karatsuba squaring. + * + * @param[out] c - the result. + * @param[in] a - the prime field element to square. + */ +void fp_sqr_karat(fp_t c, const fp_t a); + +/** + * Shifts a prime field element number to the left. Computes + * c = a * 2^bits. + * + * @param[out] c - the result. + * @param[in] a - the prime field element to shift. + * @param[in] bits - the number of bits to shift. + */ +void fp_lsh(fp_t c, const fp_t a, int bits); + +/** + * Shifts a prime field element to the right. Computes c = floor(a / 2^bits). + * + * @param[out] c - the result. + * @param[in] a - the prime field element to shift. + * @param[in] bits - the number of bits to shift. + */ +void fp_rsh(fp_t c, const fp_t a, int bits); + +/** + * Reduces a multiplication result modulo the prime field modulo using + * division-based reduction. + * + * @param[out] c - the result. + * @param[in] a - the multiplication result to reduce. + */ +void fp_rdc_basic(fp_t c, dv_t a); + +/** + * Reduces a multiplication result modulo the prime field order using Shoolbook + * Montgomery reduction. + * + * @param[out] c - the result. + * @param[in] a - the multiplication result to reduce. + */ +void fp_rdc_monty_basic(fp_t c, dv_t a); + +/** + * Reduces a multiplication result modulo the prime field order using Comba + * Montgomery reduction. + * + * @param[out] c - the result. + * @param[in] a - the multiplication result to reduce. + */ +void fp_rdc_monty_comba(fp_t c, dv_t a); + +/** + * Reduces a multiplication result modulo the prime field modulo using + * fast reduction. + * + * @param[out] c - the result. + * @param[in] a - the multiplication result to reduce. + */ +void fp_rdc_quick(fp_t c, dv_t a); + +/** + * Inverts a prime field element using Fermat's Little Theorem. + * + * @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_basic(fp_t c, const fp_t a); + +/** + * Inverts a prime field element using the binary method. + * + * @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_binar(fp_t c, const fp_t a); + +/** + * Inverts a prime field element using Montgomery inversion. + * + * @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_monty(fp_t c, const fp_t a); + +/** + * Inverts a prime field element using the Euclidean Extended Algorithm. + * + * @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_exgcd(fp_t c, const fp_t a); + +/** + * Inverts a prime field element using the Euclidean Extended Algorithm, + * using bns and a custum prime modulus. + * + * @param[out] c - the result. + * @param[in] a - the prime field element to invert. + */ +void fp_inv_exgcd_bn(bn_t c, const bn_t u, const bn_t p); + +/** + * Inverts a prime field element using the constant-time division step approach + * 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_divst(fp_t c, const fp_t a); + +/** + * Inverts a prime field element using a direct call to the lower layer. + * + * @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_lower(fp_t c, const fp_t a); + +/** + * Inverts multiple prime field elements simultaneously. + * + * @param[out] c - the result. + * @param[in] a - the prime field elements to invert. + * @param[in] n - the number of elements. + */ +void fp_inv_sim(fp_t *c, const fp_t *a, int n); + +/** + * Exponentiates a prime field element using the binary + * method. + * + * @param[out] c - the result. + * @param[in] a - the basis. + * @param[in] b - the exponent. + */ +void fp_exp_basic(fp_t c, const fp_t a, const bn_t b); + +/** + * Exponentiates a prime field element using the sliding window method. + * + * @param[out] c - the result. + * @param[in] a - the basis. + * @param[in] b - the exponent. + */ +void fp_exp_slide(fp_t c, const fp_t a, const bn_t b); + +/** + * Exponentiates a prime field element using the constant-time Montgomery + * powering ladder method. + * + * @param[out] c - the result. + * @param[in] a - the basis. + * @param[in] b - the exponent. + */ +void fp_exp_monty(fp_t c, const fp_t a, const bn_t b); + +/** + * Extracts the square root of a prime field element. Computes c = sqrt(a). The + * other square root is the negation of c. + * + * @param[out] c - the result. + * @param[in] a - the prime field element. + * @return - 1 if there is a square root, 0 otherwise. + */ +int fp_srt(fp_t c, const fp_t a); + +#endif /* !RLC_FP_H */ diff --git a/bls/contrib/relic/include/relic_fpx.h b/bls/contrib/relic/include/relic_fpx.h new file mode 100644 index 00000000..7e46fa69 --- /dev/null +++ b/bls/contrib/relic/include/relic_fpx.h @@ -0,0 +1,4497 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 . + */ + +/** + * @defgroup fpx Prime field extensions. + */ + +/** + * @file + * + * Interface of the module for prime extension field arithmetic. + * + * @ingroup fpx + */ + +#ifndef RLC_FPX_H +#define RLC_FPX_H + +#include "relic_fp.h" +#include "relic_types.h" + +/*============================================================================*/ +/* Type definitions */ +/*============================================================================*/ + +/** + * Represents a quadratic extension prime field element. + * + * This extension is constructed with the basis {1, i}, where i is an adjoined + * square root in the prime field. + */ +typedef fp_t fp2_t[2]; + +/** + * Represents a double-precision quadratic extension field element. + */ +typedef dv_t dv2_t[2]; + +/** + * Represents a quadratic extension field element with automatic memory + * allocation. + */ +typedef fp_st fp2_st[2]; + +/** + * Represents a cubic extension prime field element. + * + * This extension is constructed with the basis {1, j}, where j is an adjoined + * cube root in the prime field. + */ +typedef fp_t fp3_t[3]; + +/** + * Represents a double-precision cubic extension field element. + */ +typedef dv_t dv3_t[3]; + +/** + * Represents a cubic extension field element with automatic memory + * allocation. + */ +typedef fp_st fp3_st[3]; + +/** + * Represents a quartic extension prime field element. + * + * This extension is constructed with the basis {1, v}, where v^2 = E is an + * adjoined root in the underlying quadratic extension. + */ +typedef fp2_t fp4_t[2]; + +/** + * Represents a double-precision quartic extension field element. + */ +typedef dv2_t dv4_t[2]; + +/** + * Represents a quartic extension field element with automatic memory + * allocation. + */ +typedef fp2_st fp4_st[2]; + +/** + * Represents a sextic extension field element. + * + * This extension is constructed with the basis {1, v, v^2}, where v^3 = E is an + * adjoined root in the underlying quadratic extension. + */ +typedef fp2_t fp6_t[3]; + +/** + * Represents a double-precision sextic extension field element. + */ +typedef dv2_t dv6_t[3]; + +/** + * Represents an octic extension prime field element. + * + * This extension is constructed with the basis {1, w}, where w^2 = v is an + * adjoined root in the underlying quadratic extension. + */ +typedef fp4_t fp8_t[2]; + +/** + * Represents a double-precision octic extension field element. + */ +typedef dv4_t dv8_t[2]; + +/** + * Represents an octic extension field element with automatic memory + * allocation. + */ +typedef fp4_st fp8_st[2]; + +/** + * Represents an octic extension prime field element. + * + * This extension is constructed with the basis {1, w, w^2}, where w^3 = v is an + * adjoined root in the underlying quadratic extension. + */ +typedef fp3_t fp9_t[3]; + +/** + * Represents a double-precision octic extension field element. + */ +typedef dv3_t dv9_t[3]; + +/** + * Represents an octic extension field element with automatic memory + * allocation. + */ +typedef fp3_st fp9_st[3]; + +/** + * Represents a double-precision dodecic extension field element. + */ +typedef dv6_t dv12_t[2]; + +/** + * Represents a dodecic extension field element. + * + * This extension is constructed with the basis {1, w}, where w^2 = v is an + * adjoined root in the underlying sextic extension. + */ +typedef fp6_t fp12_t[2]; + +/** + * Represents a double-precision octdecic extension field element. + */ +typedef dv9_t dv18_t[2]; + +/** + * Represents an octdecic extension field element. + * + * This extension is constructed with the basis {1, w}, where w^2 = v is an + * adjoined root in the underlying sextic extension. + */ +typedef fp9_t fp18_t[2]; + +/** + * Represents a double-precision 24-degree extension field element. + */ +typedef dv8_t dv24_t[3]; + +/** + * Represents a 24-degree extension field element. + * + * This extension is constructed with the basis {1, t, t^2}, where t^3 = w is an + * adjoined root in the underlying dodecic extension. + */ +typedef fp8_t fp24_t[3]; + +/** + * Represents a double-precision 48-degree extension field element. + */ +typedef dv24_t dv48_t[2]; + +/** + * Represents a 48-degree extension field element. + * + * This extension is constructed with the basis {1, u}, where u^2 = t is an + * adjoined root in the underlying dodecic extension. + */ +typedef fp24_t fp48_t[2]; + +/** + * Represents a double-precision 48-degree extension field element. + */ +typedef dv18_t dv54_t[3]; + +/** + * Represents a 54-degree extension field element. + * + * This extension is constructed with the basis {1, t, t^2}, where u^3 = w is an + * adjoined root in the underlying dodecic extension. + */ +typedef fp18_t fp54_t[3]; + +/*============================================================================*/ +/* Macro definitions */ +/*============================================================================*/ + +/** + * Initializes a double-precision quadratic extension field element with null. + * +* @param[out] A - the quadratic extension element to initialize. + */ +#define dv2_null(A) \ + dv_null(A[0]); dv_null(A[1]); \ + + +/** + * Allocates a double-precision quadratic extension field element. + * + * @param[out] A - the new quadratic extension field element. + */ +#define dv2_new(A) \ + dv_new(A[0]); dv_new(A[1]); \ + +/** + * Frees a double-precision quadratic extension field element. + * + * @param[out] A - the quadratic extension field element to free. + */ +#define dv2_free(A) \ + dv_free(A[0]); dv_free(A[1]); \ + +/** + * Initializes a quadratic extension field element with null. + * +* @param[out] A - the quadratic extension element to initialize. + */ +#define fp2_null(A) \ + fp_null(A[0]); fp_null(A[1]); \ + +/** + * Allocates a quadratic extension field element. + * + * @param[out] A - the new quadratic extension field element. + */ +#define fp2_new(A) \ + fp_new(A[0]); fp_new(A[1]); \ + +/** + * Frees a quadratic extension field element. + * + * @param[out] A - the quadratic extension field element to free. + */ +#define fp2_free(A) \ + fp_free(A[0]); fp_free(A[1]); \ + +/** + * Adds two quadratic extension field elements. Computes C = A + B. + * + * @param[out] C - the result. + * @param[in] A - the first quadratic extension field element. + * @param[in] B - the second quadratic extension field element. + */ +#if FPX_QDR == BASIC +#define fp2_add(C, A, B) fp2_add_basic(C, A, B) +#elif FPX_QDR == INTEG +#define fp2_add(C, A, B) fp2_add_integ(C, A, B) +#endif + +/** + * Subtracts a quadratic extension field element from another. + * Computes C = A - B. + * + * @param[out] C - the result. + * @param[in] A - the first quadratic extension field element. + * @param[in] B - the second quadratic extension field element. + */ +#if FPX_QDR == BASIC +#define fp2_sub(C, A, B) fp2_sub_basic(C, A, B) +#elif FPX_QDR == INTEG +#define fp2_sub(C, A, B) fp2_sub_integ(C, A, B) +#endif + +/** + * Doubles a quadratic extension field element. Computes C = A + A. + * + * @param[out] C - the result. + * @param[in] A - the quadratic extension field element. + */ +#if FPX_QDR == BASIC +#define fp2_dbl(C, A) fp2_dbl_basic(C, A) +#elif FPX_QDR == INTEG +#define fp2_dbl(C, A) fp2_dbl_integ(C, A) +#endif + +/** + * Adds a quadratic extension field element and a digit. Computes c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the quadratic extension field element. + * @param[in] b - the digit to add. + */ +void fp2_add_dig(fp2_t c, const fp2_t a, dig_t b); + +/** + * Subtracts a quadratic extension field element and a digit. Computes c = a - b. + * + * @param[out] c - the result. + * @param[in] a - the quadratic extension field element. + * @param[in] b - the digit to subtract. + */ +void fp2_sub_dig(fp2_t c, const fp2_t a, dig_t b); + +/** + * Multiplies two quadratic extension field elements. Computes C = A * B. + * + * @param[out] C - the result. + * @param[in] A - the first quadratic extension field element. + * @param[in] B - the second quadratic extension field element. + */ +#if FPX_QDR == BASIC +#define fp2_mul(C, A, B) fp2_mul_basic(C, A, B) +#elif FPX_QDR == INTEG +#define fp2_mul(C, A, B) fp2_mul_integ(C, A, B) +#endif + +/** + * Multiplies a quadratic extension field by the quadratic/cubic non-residue. + * Computes C = A * E, where E is a non-square/non-cube in the quadratic + * extension. + * + * @param[out] C - the result. + * @param[in] A - the quadratic extension field element to multiply. + */ +#if FPX_QDR == BASIC +#define fp2_mul_nor(C, A) fp2_mul_nor_basic(C, A) +#elif FPX_QDR == INTEG +#define fp2_mul_nor(C, A) fp2_mul_nor_integ(C, A) +#endif + +/** + * Squares a quadratic extension field element. Computes C = A * A. + * + * @param[out] C - the result. + * @param[in] A - the quadratic extension field element to square. + */ +#if FPX_QDR == BASIC +#define fp2_sqr(C, A) fp2_sqr_basic(C, A) +#elif FPX_QDR == INTEG +#define fp2_sqr(C, A) fp2_sqr_integ(C, A) +#endif + +/** + * Initializes a double-precision cubic extension field element with a null + * value. + * +* @param[out] A - the cubic extension element to initialize. + */ +#define dv3_null(A) \ + dv_null(A[0]); dv_null(A[1]); dv_null(A[2]); \ + +/** + * Allocates a double-precision cubic extension field element. + * + * @param[out] A - the new cubic extension field element. + */ +#define dv3_new(A) \ + dv_new(A[0]); dv_new(A[1]); dv_new(A[2]); \ + +/** + * Frees a double-precision cubic extension field element. + * + * @param[out] A - the cubic extension field element to free. + */ +#define dv3_free(A) \ + dv_free(A[0]); dv_free(A[1]); dv_free(A[2]); \ + +/** + * Initializes a cubic extension field element with null. + * +* @param[out] A - the cubic extension element to initialize. + */ +#define fp3_null(A) \ + fp_null(A[0]); fp_null(A[1]); fp_null(A[2]); \ + +/** + * Allocates a cubic extension field element. + * + * @param[out] A - the new cubic extension field element. + */ +#define fp3_new(A) \ + fp_new(A[0]); fp_new(A[1]); fp_new(A[2]); \ + +/** + * Frees a cubic extension field element. + * + * @param[out] A - the cubic extension field element to free. + */ +#define fp3_free(A) \ + fp_free(A[0]); fp_free(A[1]); fp_free(A[2]); \ + +/** + * Adds two cubic extension field elements. Computes C = A + B. + * + * @param[out] C - the result. + * @param[in] A - the first cubic extension field element. + * @param[in] B - the second cubic extension field element. + */ +#if FPX_CBC == BASIC +#define fp3_add(C, A, B) fp3_add_basic(C, A, B) +#elif FPX_CBC == INTEG +#define fp3_add(C, A, B) fp3_add_integ(C, A, B) +#endif + +/** + * Subtracts a cubic extension field element from another. + * Computes C = A - B. + * + * @param[out] C - the result. + * @param[in] A - the first cubic extension field element. + * @param[in] B - the second cubic extension field element. + */ +#if FPX_CBC == BASIC +#define fp3_sub(C, A, B) fp3_sub_basic(C, A, B) +#elif FPX_CBC == INTEG +#define fp3_sub(C, A, B) fp3_sub_integ(C, A, B) +#endif + +/** + * Doubles a cubic extension field element. Computes C = A + A. + * + * @param[out] C - the result. + * @param[in] A - the cubic extension field element. + */ +#if FPX_CBC == BASIC +#define fp3_dbl(C, A) fp3_dbl_basic(C, A) +#elif FPX_CBC == INTEG +#define fp3_dbl(C, A) fp3_dbl_integ(C, A) +#endif + +/** + * Multiplies two cubic extension field elements. Computes C = A * B. + * + * @param[out] C - the result. + * @param[in] A - the first cubic extension field element. + * @param[in] B - the second cubic extension field element. + */ +#if FPX_CBC == BASIC +#define fp3_mul(C, A, B) fp3_mul_basic(C, A, B) +#elif FPX_CBC == INTEG +#define fp3_mul(C, A, B) fp3_mul_integ(C, A, B) +#endif + +/** + * Squares a cubic extension field element. Computes C = A * A. + * + * @param[out] C - the result. + * @param[in] A - the cubic extension field element to square. + */ +#if FPX_CBC == BASIC +#define fp3_sqr(C, A) fp3_sqr_basic(C, A) +#elif FPX_CBC == INTEG +#define fp3_sqr(C, A) fp3_sqr_integ(C, A) +#endif + +/** + * Initializes a double-precision quartic extension field with null. + * + * @param[out] A - the quartic extension element to initialize. + */ +#define dv4_null(A) \ + dv2_null(A[0]); dv2_null(A[1]); \ + +/** + * Allocates a double-precision quartic extension field element. + * + * @param[out] A - the new quartic extension field element. + */ +#define dv4_new(A) \ + dv2_new(A[0]); dv2_new(A[1]); \ + +/** + * Frees a double-precision quartic extension field element. + * + * @param[out] A - the quartic extension field element to free. + */ +#define dv4_free(A) \ + dv2_free(A[0]); dv2_free(A[1]); \ + +/** + * Initializes a quartic extension field with null. + * + * @param[out] A - the quartic extension element to initialize. + */ +#define fp4_null(A) \ + fp2_null(A[0]); fp2_null(A[1]); \ + +/** + * Allocates a quartic extension field element. + * + * @param[out] A - the new quartic extension field element. + */ +#define fp4_new(A) \ + fp2_new(A[0]); fp2_new(A[1]); \ + +/** + * Frees a quartic extension field element. + * + * @param[out] A - the quartic extension field element to free. + */ +#define fp4_free(A) \ + fp2_free(A[0]); fp2_free(A[1]); \ + +/** + * Multiplies two quartic extension field elements. Computes C = A * B. + * + * @param[out] C - the result. + * @param[in] A - the first quartic extension field element. + * @param[in] B - the second quartic extension field element. + */ +#if FPX_RDC == BASIC +#define fp4_mul(C, A, B) fp4_mul_basic(C, A, B) +#elif FPX_RDC == LAZYR +#define fp4_mul(C, A, B) fp4_mul_lazyr(C, A, B) +#endif + +/** + * Squares a quartic extension field element. Computes C = A * A. + * + * @param[out] C - the result. + * @param[in] A - the quartic extension field element to square. + */ +#if FPX_RDC == BASIC +#define fp4_sqr(C, A) fp4_sqr_basic(C, A) +#elif FPX_RDC == LAZYR +#define fp4_sqr(C, A) fp4_sqr_lazyr(C, A) +#endif + +/** + * Initializes a double-precision sextic extension field with null. + * + * @param[out] A - the sextic extension element to initialize. + */ +#define dv6_null(A) \ + dv2_null(A[0]); dv2_null(A[1]); dv2_null(A[2]); \ + +/** + * Allocates a double-precision sextic extension field element. + * + * @param[out] A - the new sextic extension field element. + */ +#define dv6_new(A) \ + dv2_new(A[0]); dv2_new(A[1]); dv2_new(A[2]); \ + +/** + * Frees a double-precision sextic extension field element. + * + * @param[out] A - the sextic extension field element to free. + */ +#define dv6_free(A) \ + dv2_free(A[0]); dv2_free(A[1]); dv2_free(A[2]); \ + +/** + * Initializes a sextic extension field with null. + * + * @param[out] A - the sextic extension element to initialize. + */ +#define fp6_null(A) \ + fp2_null(A[0]); fp2_null(A[1]); fp2_null(A[2]); \ + +/** + * Allocates a sextic extension field element. + * + * @param[out] A - the new sextic extension field element. + */ +#define fp6_new(A) \ + fp2_new(A[0]); fp2_new(A[1]); fp2_new(A[2]); \ + +/** + * Frees a sextic extension field element. + * + * @param[out] A - the sextic extension field element to free. + */ +#define fp6_free(A) \ + fp2_free(A[0]); fp2_free(A[1]); fp2_free(A[2]); \ + +/** + * Multiplies two sextic extension field elements. Computes C = A * B. + * + * @param[out] C - the result. + * @param[in] A - the first sextic extension field element. + * @param[in] B - the second sextic extension field element. + */ +#if FPX_RDC == BASIC +#define fp6_mul(C, A, B) fp6_mul_basic(C, A, B) +#elif FPX_RDC == LAZYR +#define fp6_mul(C, A, B) fp6_mul_lazyr(C, A, B) +#endif + +/** + * Squares a sextic extension field element. Computes C = A * A. + * + * @param[out] C - the result. + * @param[in] A - the sextic extension field element to square. + */ +#if FPX_RDC == BASIC +#define fp6_sqr(C, A) fp6_sqr_basic(C, A) +#elif FPX_RDC == LAZYR +#define fp6_sqr(C, A) fp6_sqr_lazyr(C, A) +#endif + +/** + * Initializes a double-precision octic extension field with null. + * + * @param[out] A - the octic extension element to initialize. + */ +#define dv8_null(A) \ + dv4_null(A[0]); dv4_null(A[1]); \ + +/** + * Allocates a double-precision octic extension field element. + * + * @param[out] A - the new octic extension field element. + */ +#define dv8_new(A) \ + dv4_new(A[0]); dv4_new(A[1]); \ + +/** + * Frees a double-precision octic extension field element. + * + * @param[out] A - the octic extension field element to free. + */ +#define dv8_free(A) \ + dv4_free(A[0]); dv4_free(A[1]); \ + +/** + * Initializes an octic extension field with null. + * + * @param[out] A - the octic extension element to initialize. + */ +#define fp8_null(A) \ + fp4_null(A[0]); fp4_null(A[1]); \ + +/** + * Allocates an octic extension field element. + * + * @param[out] A - the new octic extension field element. + */ +#define fp8_new(A) \ + fp4_new(A[0]); fp4_new(A[1]); \ + +/** + * Frees an octic extension field element. + * + * @param[out] A - the octic extension field element to free. + */ +#define fp8_free(A) \ + fp4_free(A[0]); fp4_free(A[1]); \ + +/** + * Multiplies two octic extension field elements. Computes C = A * B. + * + * @param[out] C - the result. + * @param[in] A - the first octic extension field element. + * @param[in] B - the second octic extension field element. + */ +#if FPX_RDC == BASIC +#define fp8_mul(C, A, B) fp8_mul_basic(C, A, B) +#elif FPX_RDC == LAZYR +#define fp8_mul(C, A, B) fp8_mul_lazyr(C, A, B) +#endif + +/** + * Squares an octic extension field element. Computes C = A * A. + * + * @param[out] C - the result. + * @param[in] A - the octic extension field element to square. + */ +#if FPX_RDC == BASIC +#define fp8_sqr(C, A) fp8_sqr_basic(C, A) +#elif FPX_RDC == LAZYR +#define fp8_sqr(C, A) fp8_sqr_lazyr(C, A) +#endif + +/** + * Initializes a double-precision nonic extension field with null. + * + * @param[out] A - the octic extension element to initialize. + */ +#define dv9_null(A) \ + dv3_null(A[0]); dv3_null(A[1]); dv3_null(A[2]); \ + +/** + * Allocates a double-precision nonic extension field element. + * + * @param[out] A - the new nonic extension field element. + */ +#define dv9_new(A) \ + dv3_new(A[0]); dv3_new(A[1]); dv3_new(A[2]); \ + +/** + * Frees a double-precision nonic extension field element. + * + * @param[out] A - the nonic extension field element to free. + */ +#define dv9_free(A) \ + dv3_free(A[0]); dv3_free(A[1]); dv3_free(A[2]); \ + +/** + * Initializes a nonic extension field with null. + * + * @param[out] A - the nonic extension element to initialize. + */ +#define fp9_null(A) \ + fp3_null(A[0]); fp3_null(A[1]); fp3_null(A[2]); \ + +/** + * Allocates a nonic extension field element. + * + * @param[out] A - the new nonic extension field element. + */ +#define fp9_new(A) \ + fp3_new(A[0]); fp3_new(A[1]); fp3_new(A[2]); \ + +/** + * Frees a nonic extension field element. + * + * @param[out] A - the nonic extension field element to free. + */ +#define fp9_free(A) \ + fp3_free(A[0]); fp3_free(A[1]); fp3_free(A[2]); \ + +/** + * Multiplies two nonic extension field elements. Computes C = A * B. + * + * @param[out] C - the result. + * @param[in] A - the first nonic extension field element. + * @param[in] B - the second nonic extension field element. + */ +#if FPX_RDC == BASIC +#define fp9_mul(C, A, B) fp9_mul_basic(C, A, B) +#elif FPX_RDC == LAZYR +#define fp9_mul(C, A, B) fp9_mul_lazyr(C, A, B) +#endif + +/** + * Squares a nonic extension field element. Computes C = A * A. + * + * @param[out] C - the result. + * @param[in] A - the nonic extension field element to square. + */ +#if FPX_RDC == BASIC +#define fp9_sqr(C, A) fp9_sqr_basic(C, A) +#elif FPX_RDC == LAZYR +#define fp9_sqr(C, A) fp9_sqr_lazyr(C, A) +#endif + +/** + * Initializes a double-precision dodecic extension field with null. + * + * @param[out] A - the dodecic extension element to initialize. + */ +#define dv12_null(A) \ + dv6_null(A[0]); dv6_null(A[1]); \ + +/** + * Allocates a double-precision dodecic extension field element. + * + * @param[out] A - the new dodecic extension field element. + */ +#define dv12_new(A) \ + dv6_new(A[0]); dv6_new(A[1]); \ + +/** + * Frees a double-precision dodecic extension field element. + * + * @param[out] A - the dodecic extension field element to free. + */ +#define dv12_free(A) \ + dv6_free(A[0]); dv6_free(A[1]); \ + +/** + * Initializes a dodecic extension field with null. + * + * @param[out] A - the dodecic extension element to initialize. + */ +#define fp12_null(A) \ + fp6_null(A[0]); fp6_null(A[1]); \ + +/** + * Allocates a dodecic extension field element. + * + * @param[out] A - the new dodecic extension field element. + */ +#define fp12_new(A) \ + fp6_new(A[0]); fp6_new(A[1]); \ + +/** + * Frees a dodecic extension field element. + * + * @param[out] A - the dodecic extension field element to free. + */ +#define fp12_free(A) \ + fp6_free(A[0]); fp6_free(A[1]); \ + +/** + * Multiplies two dodecic extension field elements. Computes C = A * B. + * + * @param[out] C - the result. + * @param[in] A - the first dodecic extension field element. + * @param[in] B - the second dodecic extension field element. + */ +#if FPX_RDC == BASIC +#define fp12_mul(C, A, B) fp12_mul_basic(C, A, B) +#elif FPX_RDC == LAZYR +#define fp12_mul(C, A, B) fp12_mul_lazyr(C, A, B) +#endif + +/** + * Multiplies a dense and a sparse dodecic extension field elements. Computes + * C = A * B. + * + * @param[out] C - the result. + * @param[in] A - the dense dodecic extension field element. + * @param[in] B - the sparse dodecic extension field element. + */ +#if FPX_RDC == BASIC +#define fp12_mul_dxs(C, A, B) fp12_mul_dxs_basic(C, A, B) +#elif FPX_RDC == LAZYR +#define fp12_mul_dxs(C, A, B) fp12_mul_dxs_lazyr(C, A, B) +#endif + +/** + * Squares a dodecic extension field element. Computes C = A * A. + * + * @param[out] C - the result. + * @param[in] A - the dodecic extension field element to square. + */ +#if FPX_RDC == BASIC +#define fp12_sqr(C, A) fp12_sqr_basic(C, A) +#elif FPX_RDC == LAZYR +#define fp12_sqr(C, A) fp12_sqr_lazyr(C, A) +#endif + +/** + * Squares a dodecic extension field element in the cyclotomic subgroup. + * Computes C = A * A. + * + * @param[out] C - the result. + * @param[in] A - the dodecic extension field element to square. + */ +#if FPX_RDC == BASIC +#define fp12_sqr_cyc(C, A) fp12_sqr_cyc_basic(C, A) +#elif FPX_RDC == LAZYR +#define fp12_sqr_cyc(C, A) fp12_sqr_cyc_lazyr(C, A) +#endif + +/** + * Squares a dodecic extension field element in the cyclotomic subgroup in + * compressed form. Computes C = A * A. + * + * @param[out] C - the result. + * @param[in] A - the dodecic extension field element to square. + */ +#if FPX_RDC == BASIC +#define fp12_sqr_pck(C, A) fp12_sqr_pck_basic(C, A) +#elif FPX_RDC == LAZYR +#define fp12_sqr_pck(C, A) fp12_sqr_pck_lazyr(C, A) +#endif + +/** + * Initializes a double-precision sextic extension field with null. + * + * @param[out] A - the sextic extension element to initialize. + */ +#define dv18_null(A) \ + dv9_null(A[0]); dv9_null(A[1]); \ + +/** + * Allocates a double-precision sextic extension field element. + * + * @param[out] A - the new sextic extension field element. + */ +#define dv18_new(A) \ + dv9_new(A[0]); dv9_new(A[1]); \ + +/** + * Frees a double-precision sextic extension field element. + * + * @param[out] A - the sextic extension field element to free. + */ +#define dv18_free(A) \ + dv9_free(A[0]); dv9_free(A[1]); \ + +/** + * Initializes an octdecic extension field with null. + * + * @param[out] A - the octdecic extension element to initialize. + */ +#define fp18_null(A) \ + fp9_null(A[0]); fp9_null(A[1]); \ + +/** + * Allocates an octdecic extension field element. + * + * @param[out] A - the new octdecic extension field element. + */ +#define fp18_new(A) \ + fp9_new(A[0]); fp9_new(A[1]); \ + +/** + * Frees an octdecic extension field element. + * + * @param[out] A - the octdecic extension field element to free. + */ +#define fp18_free(A) \ + fp9_free(A[0]); fp9_free(A[1]); \ + +/** + * Multiplies two octdecic extension field elements. Computes C = A * B. + * + * @param[out] C - the result. + * @param[in] A - the first octdecic extension field element. + * @param[in] B - the second octdecic extension field element. + */ +#if FPX_RDC == BASIC +#define fp18_mul(C, A, B) fp18_mul_basic(C, A, B) +#elif FPX_RDC == LAZYR +#define fp18_mul(C, A, B) fp18_mul_lazyr(C, A, B) +#endif + +/** + * Multiplies a dense and a sparse octdecic extension field elements. Computes + * C = A * B. + * + * @param[out] C - the result. + * @param[in] A - the dense octdecic extension field element. + * @param[in] B - the sparse octdecic extension field element. + */ +#if FPX_RDC == BASIC +#define fp18_mul_dxs(C, A, B) fp18_mul_dxs_basic(C, A, B) +#elif FPX_RDC == LAZYR +#define fp18_mul_dxs(C, A, B) fp18_mul_dxs_lazyr(C, A, B) +#endif + +/** + * Squares an octdecic extension field element. Computes C = A * A. + * + * @param[out] C - the result. + * @param[in] A - the octdecic extension field element to square. + */ +#if FPX_RDC == BASIC +#define fp18_sqr(C, A) fp18_sqr_basic(C, A) +#elif FPX_RDC == LAZYR +#define fp18_sqr(C, A) fp18_sqr_lazyr(C, A) +#endif + +/** + * Initializes a double-precision 24-degree extension field with null. + * + * @param[out] A - the 24-degree extension element to initialize. + */ +#define dv24_null(A) \ + dv8_null(A[0]); dv8_null(A[1]); dv8_null(A[2]); \ + +/** + * Allocates a double-precision 24-degree extension field element. + * + * @param[out] A - the new 24-degree extension field element. + */ +#define dv24_new(A) \ + dv8_new(A[0]); dv8_new(A[1]); dv8_new(A[2]); \ + +/** + * Frees a double-precision 24-degree extension field element. + * + * @param[out] A - the 24-degree extension field element to free. + */ +#define dv24_free(A) \ + dv8_free(A[0]); dv8_free(A[1]); dv8_free(A[2]); \ + +/** + * Initializes a 24-degree extension field with null. + * + * @param[out] A - the 24-degree extension element to initialize. + */ +#define fp24_null(A) \ + fp8_null(A[0]); fp8_null(A[1]); fp8_null(A[2]); \ + +/** + * Allocates a 24-degree extension field element. + * + * @param[out] A - the new 24-degree extension field element. + */ +#define fp24_new(A) \ + fp8_new(A[0]); fp8_new(A[1]); fp8_new(A[2]); \ + +/** + * Frees a 24-degree extension field element. + * + * @param[out] A - the 24-degree extension field element to free. + */ +#define fp24_free(A) \ + fp8_free(A[0]); fp8_free(A[1]); fp8_free(A[2]); \ + +/** + * Multiplies two 24-degree extension field elements. Computes C = A * B. + * + * @param[out] C - the result. + * @param[in] A - the first 24-degree extension field element. + * @param[in] B - the second 24-degree extension field element. + */ +#if FPX_RDC == BASIC +#define fp24_mul(C, A, B) fp24_mul_basic(C, A, B) +#elif FPX_RDC == LAZYR +#define fp24_mul(C, A, B) fp24_mul_lazyr(C, A, B) +#endif + +/** + * Squares a 24-degree extension field element. 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(C, A) fp24_sqr_basic(C, A) +#elif FPX_RDC == LAZYR +#define fp24_sqr(C, A) fp24_sqr_lazyr(C, A) +#endif + +/** + * Initializes a double-precision 48-degree extension field with null. + * + * @param[out] A - the 48-degree extension element to initialize. + */ +#define dv48_null(A) \ + dv24_null(A[0]); dv24_null(A[1]); \ + +/** + * Allocates a double-precision 48-degree extension field element. + * + * @param[out] A - the new 48-degree extension field element. + */ +#define dv48_new(A) \ + dv24_new(A[0]); dv24_new(A[1]); \ + +/** + * Frees a double-precision 48-degree extension field element. + * + * @param[out] A - the 48-degree extension field element to free. + */ +#define dv48_free(A) \ + dv24_free(A[0]); dv24_free(A[1]); \ + +/** + * Initializes a 48-degree extension field with null. + * + * @param[out] A - the 48-degree extension element to initialize. + */ +#define fp48_null(A) \ + fp24_null(A[0]); fp24_null(A[1]); \ + +/** + * Allocates a 48-degree extension field element. + * + * @param[out] A - the new 48-degree extension field element. + */ +#define fp48_new(A) \ + fp24_new(A[0]); fp24_new(A[1]); \ + +/** + * Frees a 48-degree extension field element. + * + * @param[out] A - the 48-degree extension field element to free. + */ +#define fp48_free(A) \ + fp24_free(A[0]); fp24_free(A[1]); \ + +/** + * Multiplies two 48-degree extension field elements. Computes C = A * B. + * + * @param[out] C - the result. + * @param[in] A - the first 48-degree extension field element. + * @param[in] B - the second 48-degree extension field element. + */ +#if FPX_RDC == BASIC +#define fp48_mul(C, A, B) fp48_mul_basic(C, A, B) +#elif FPX_RDC == LAZYR +#define fp48_mul(C, A, B) fp48_mul_lazyr(C, A, B) +#endif + +/** + * Squares a 48-degree extension field element. Computes C = A * A. + * + * @param[out] C - the result. + * @param[in] A - the 48-degree extension field element to square. + */ +#if FPX_RDC == BASIC +#define fp48_sqr(C, A) fp48_sqr_basic(C, A) +#elif FPX_RDC == LAZYR +#define fp48_sqr(C, A) fp48_sqr_lazyr(C, A) +#endif + +/** + * Squares a 48-degree extension field element in the cyclotomic subgroup. + * Computes C = A * A. + * + * @param[out] C - the result. + * @param[in] A - the 48-degree extension field element to square. + */ +#if FPX_RDC == BASIC +#define fp48_sqr_cyc(C, A) fp48_sqr_cyc_basic(C, A) +#elif FPX_RDC == LAZYR +#define fp48_sqr_cyc(C, A) fp48_sqr_cyc_lazyr(C, A) +#endif + +/** + * Squares a 48-degree extension field element in the cyclotomic subgroup in + * compressed form. Computes C = A * A. + * + * @param[out] C - the result. + * @param[in] A - the 48-degree extension field element to square. + */ +#if FPX_RDC == BASIC +#define fp48_sqr_pck(C, A) fp48_sqr_pck_basic(C, A) +#elif FPX_RDC == LAZYR +#define fp48_sqr_pck(C, A) fp48_sqr_pck_lazyr(C, A) +#endif + +/** + * Initializes a double-precision 54-degree extension field with null. + * + * @param[out] A - the 54-degree extension element to initialize. + */ +#define dv54_null(A) \ + dv18_null(A[0]); dv18_null(A[1]); dv18_null(A[2]); \ + +/** + * Allocates a double-precision 54-degree extension field element. + * + * @param[out] A - the new 54-degree extension field element. + */ +#define dv54_new(A) \ + dv18_new(A[0]); dv18_new(A[1]); dv18_new(A[2]); \ + +/** + * Frees a double-precision 54-degree extension field element. + * + * @param[out] A - the 54-degree extension field element to free. + */ +#define dv54_free(A) \ + dv18_free(A[0]); dv18_free(A[1]); dv18_free(A[2]); \ + +/** + * Initializes a 54-degree extension field with null. + * + * @param[out] A - the 54-degree extension element to initialize. + */ +#define fp54_null(A) \ + fp18_null(A[0]); fp18_null(A[1]); fp18_null(A[2]); \ + +/** + * Allocates a 54-degree extension field element. + * + * @param[out] A - the new 54-degree extension field element. + */ +#define fp54_new(A) \ + fp18_new(A[0]); fp18_new(A[1]); fp18_new(A[2]); \ + +/** + * Frees a 54-degree extension field element. + * + * @param[out] A - the 54-degree extension field element to free. + */ +#define fp54_free(A) \ + fp18_free(A[0]); fp18_free(A[1]); fp18_free(A[2]); \ + +/** + * Multiplies two 54-degree extension field elements. Computes C = A * B. + * + * @param[out] C - the result. + * @param[in] A - the first 54-degree extension field element. + * @param[in] B - the second 54-degree extension field element. + */ +#if FPX_RDC == BASIC +#define fp54_mul(C, A, B) fp54_mul_basic(C, A, B) +#elif FPX_RDC == LAZYR +#define fp54_mul(C, A, B) fp54_mul_lazyr(C, A, B) +#endif + +/** + * Squares a 54-degree extension field element. Computes C = A * A. + * + * @param[out] C - the result. + * @param[in] A - the 54-degree extension field element to square. + */ +#if FPX_RDC == BASIC +#define fp54_sqr(C, A) fp54_sqr_basic(C, A) +#elif FPX_RDC == LAZYR +#define fp54_sqr(C, A) fp54_sqr_lazyr(C, A) +#endif + +/** + * Squares a 54-degree extension field element in the cyclotomic subgroup. + * Computes C = A * A. + * + * @param[out] C - the result. + * @param[in] A - the 54-degree extension field element to square. + */ +#if FPX_RDC == BASIC +#define fp54_sqr_cyc(C, A) fp54_sqr_cyc_basic(C, A) +#elif FPX_RDC == LAZYR +#define fp54_sqr_cyc(C, A) fp54_sqr_cyc_lazyr(C, A) +#endif + +/** + * Squares a 54-degree extension field element in the cyclotomic subgroup in + * compressed form. Computes C = A * A. + * + * @param[out] C - the result. + * @param[in] A - the 54-degree extension field element to square. + */ +#if FPX_RDC == BASIC +#define fp54_sqr_pck(C, A) fp54_sqr_pck_basic(C, A) +#elif FPX_RDC == LAZYR +#define fp54_sqr_pck(C, A) fp54_sqr_pck_lazyr(C, A) +#endif + +/*============================================================================*/ +/* Function prototypes */ +/*============================================================================*/ + +/** + * Initializes the quadratic extension field arithmetic module. + */ +void fp2_field_init(void); + +/** + * Return the integer part (u) of the quadratic non-residue (i + u). + */ +int fp2_field_get_qnr(void); + +/** + * Copies the second argument to the first argument. + * + * @param[out] C - the result. + * @param[in] A - the quadratic extension field element to copy. + */ +void fp2_copy(fp2_t c, fp2_t a); + +/** + * Assigns zero to a quadratic extension field element. + * + * @param[out] A - the quadratic extension field element to zero. + */ +void fp2_zero(fp2_t a); + +/** + * Tests if a quadratic extension field element is zero or not. + * + * @param[in] A - the quadratic extension field element to test. + * @return 1 if the argument is zero, 0 otherwise. + */ +int fp2_is_zero(fp2_t a); + +/** + * Assigns a random value to a quadratic extension field element. + * + * @param[out] A - the quadratic extension field element to assign. + */ +void fp2_rand(fp2_t a); + +/** + * Prints a quadratic extension field element to standard output. + * + * @param[in] A - the quadratic extension field element to print. + */ +void fp2_print(fp2_t a); + +/** + * Returns the number of bytes necessary to store a quadratic extension field + * element. + * + * @param[in] a - the extension field element. + * @param[in] pack - the flag to indicate compression. + * @return the number of bytes. + */ +int fp2_size_bin(fp2_t a, int pack); + +/** + * Reads a quadratic extension field element from a byte vector in big-endian + * format. + * + * @param[out] a - the result. + * @param[in] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @throw ERR_NO_BUFFER - if the buffer capacity is not correct. + */ +void fp2_read_bin(fp2_t a, const uint8_t *bin, int len); + +/** + * Writes a quadratic extension field element to a byte vector in big-endian + * format. + * + * @param[out] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @param[in] a - the extension field element to write. + * @param[in] pack - the flag to indicate compression. + * @throw ERR_NO_BUFFER - if the buffer capacity is not correct. + */ +void fp2_write_bin(uint8_t *bin, int len, fp2_t a, int pack); + +/** + * Returns the result of a comparison between two quadratic extension field + * elements. + * + * @param[in] A - the first quadratic extension field element. + * @param[in] B - the second quadratic extension field element. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fp2_cmp(fp2_t a, fp2_t b); + +/** + * Returns the result of a signed comparison between a quadratic extension field + * element and a digit. + * + * @param[in] a - the quadratic extension field element. + * @param[in] b - the digit. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fp2_cmp_dig(fp2_t a, dig_t b); + +/** + * Assigns a quadratic extension field element to a digit. + * + * @param[in] a - the quadratic extension field element. + * @param[in] b - the digit. + */ +void fp2_set_dig(fp2_t a, dig_t b); + +/** + * Adds two quadratic extension field elements using basic arithmetic. + * + * @param[out] c - the result. + * @param[in] a - the first quadratic extension field element. + * @param[in] b - the second quadratic extension field element. + */ +void fp2_add_basic(fp2_t c, fp2_t a, fp2_t b); + +/** + * Adds two quadratic extension field elements using integrated modular + * reduction. + * + * @param[out] c - the result. + * @param[in] a - the first quadratic extension field element. + * @param[in] b - the second quadratic extension field element. + */ +void fp2_add_integ(fp2_t c, fp2_t a, fp2_t b); + +/** + * Subtracts a quadratic extension field element from another using basic + * arithmetic. + * + * @param[out] C - the result. + * @param[in] A - the first quadratic extension field element. + * @param[in] B - the second quadratic extension field element. + */ +void fp2_sub_basic(fp2_t c, fp2_t a, fp2_t b); + +/** + * Subtracts a quadratic extension field element from another using integrated + * modular reduction. + * + * @param[out] C - the result. + * @param[in] A - the first quadratic extension field element. + * @param[in] B - the second quadratic extension field element. + */ +void fp2_sub_integ(fp2_t c, fp2_t a, fp2_t b); + +/** + * Negates a quadratic extension field element. + * + * @param[out] C - the result. + * @param[out] A - the quadratic extension field element to negate. + */ +void fp2_neg(fp2_t c, fp2_t a); + +/** + * Doubles a quadratic extension field element using basic arithmetic. + * + * @param[out] c - the result. + * @param[in] a - the quadratic extension field element to double. + */ +void fp2_dbl_basic(fp2_t c, fp2_t a); + +/** + * Doubles a quadratic extension field element using integrated modular + * reduction. + * + * @param[out] c - the result. + * @param[in] a - the quadratic extension field element to double. + */ +void fp2_dbl_integ(fp2_t c, fp2_t a); + +/** + * Multiples two quadratic extension field elements using basic arithmetic. + * + * @param[out] c - the result. + * @param[in] a - the first quadratic extension field element. + * @param[in] b - the second quadratic extension field element. + */ +void fp2_mul_basic(fp2_t c, fp2_t a, fp2_t b); + +/** + * Multiples two quadratic extension field elements using integrated modular + * reduction. + * + * @param[out] c - the result. + * @param[in] a - the first quadratic extension field element. + * @param[in] b - the second quadratic extension field element. + */ +void fp2_mul_integ(fp2_t c, fp2_t a, fp2_t b); + +/** + * Multiplies a quadratic extension field element by the adjoined root. + * Computes c = a * u. + * + * @param[out] c - the result. + * @param[in] a - the quadratic extension field element to multiply. + */ +void fp2_mul_art(fp2_t c, fp2_t a); + +/** + * Multiplies a quadratic extension field element by a quadratic/cubic + * non-residue. + * + * @param[out] c - the result. + * @param[in] a - the quadratic extension field element to multiply. + */ +void fp2_mul_nor_basic(fp2_t c, fp2_t a); + +/** + * Multiplies a quadratic extension field element by a quadratic/cubic + * non-residue using integrated modular reduction. + * + * @param[out] c - the result. + * @param[in] a - the quadratic extension field element to multiply. + */ +void fp2_mul_nor_integ(fp2_t c, fp2_t a); + +/** + * Multiplies a quadratic 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 fp2_mul_frb(fp2_t c, fp2_t a, int i, int j); + +/** + * Multiplies a quadratic extension field element by a digit. Computes c = a * b. + * + * @param[out] c - the result. + * @param[in] a - the quadratic extension field element. + * @param[in] b - the digit to multiply. + */ +void fp2_mul_dig(fp2_t c, const fp2_t a, dig_t b); + +/** + * Computes the square of a quadratic extension field element using basic + * arithmetic. + * + * @param[out] c - the result. + * @param[in] a - the quadratic extension field element to square. + */ +void fp2_sqr_basic(fp2_t c, fp2_t a); + +/** + * Computes the square of a quadratic extension field element using integrated + * modular reduction. + * + * @param[out] c - the result. + * @param[in] a - the quadratic extension field element to square. + */ +void fp2_sqr_integ(fp2_t c, fp2_t a); + +/** + * Inverts a quadratic extension field element. Computes c = 1/a. + * + * @param[out] c - the result. + * @param[in] a - the quadratic extension field element to invert. + */ +void fp2_inv(fp2_t c, fp2_t a); + +/** + * Computes the inverse of a cyclotomic quadratic extension field element. + * + * @param[out] c - the result. + * @param[in] a - the quadratic extension field element to invert. + */ +void fp2_inv_cyc(fp2_t c, fp2_t a); + +/** + * Inverts multiple quadratic extension field elements simultaneously. + * + * @param[out] c - the result. + * @param[in] a - the quadratic extension field elements to invert. + * @param[in] n - the number of elements. + */ +void fp2_inv_sim(fp2_t *c, fp2_t *a, int n); + +/** + * Tests if a quadratic extension field element is cyclotomic. + * + * @param[in] a - the quadratic extension field element to test. + * @return 1 if the extension field element is cyclotomic, 0 otherwise. + */ +int fp2_test_cyc(fp2_t a); + +/** + * Converts a quadratic extension field element to a cyclotomic element. + * Computes c = a^(p - 1). + * + * @param[out] c - the result. + * @param[in] a - the quadratic extension field element. + */ +void fp2_conv_cyc(fp2_t c, fp2_t a); + +/** + * Computes a power of a quadratic extension field element. + * + * @param[out] c - the result. + * @param[in] a - the quadratic extension element to exponentiate. + * @param[in] b - the exponent. + */ +void fp2_exp(fp2_t c, fp2_t a, bn_t b); + +/** + * Computes a power of a quadratic extension field element by a small exponent. + * + * @param[out] c - the result. + * @param[in] a - the basis. + * @param[in] b - the exponent. + */ +void fp2_exp_dig(fp2_t c, fp2_t a, dig_t b); + +/** + * Computes a power of a cyclotomic quadratic extension field element. + * + * @param[out] c - the result. + * @param[in] a - the cyclotomic element to exponentiate. + * @param[in] b - the exponent. + */ +void fp2_exp_cyc(fp2_t c, fp2_t a, bn_t b); + +/** + * Computes a power of the Frobenius map of a quadratic extension field element. + * When i is odd, this is the same as computing the conjugate of the extension + * field element. + * + * @param[out] c - the result. + * @param[in] a - the quadratic extension element to conjugate. + * @param[in] i - the power of the Frobenius map. + */ +void fp2_frb(fp2_t c, fp2_t a, int i); + +/** + * Extracts the square root of a quadratic 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 fp2_srt(fp2_t c, fp2_t a); + +/** + * Compresses an extension field element. + * + * @param[out] r - the result. + * @param[in] p - the extension field element to compress. + */ +void fp2_pck(fp2_t c, fp2_t a); + +/** + * Decompresses a quadratic extension field element. + * + * @param[out] r - the result. + * @param[in] p - the quadratic extension field element. + * @return if the decompression was successful + */ +int fp2_upk(fp2_t c, fp2_t a); + +/** + * Initializes the cubic extension field arithmetic module. + */ +void fp3_field_init(void); + +/** + * Copies the second argument to the first argument. + * + * @param[out] C - the result. + * @param[in] A - the cubic extension field element to copy. + */ +void fp3_copy(fp3_t c, fp3_t a); + +/** + * Assigns zero to a cubic extension field element. + * + * @param[out] A - the cubic extension field element to zero. + */ +void fp3_zero(fp3_t a); + +/** + * Tests if a cubic extension field element is zero or not. + * + * @param[in] A - the cubic extension field element to test. + * @return 1 if the argument is zero, 0 otherwise. + */ +int fp3_is_zero(fp3_t a); + +/** + * Assigns a random value to a cubic extension field element. + * + * @param[out] A - the cubic extension field element to assign. + */ +void fp3_rand(fp3_t a); + +/** + * Prints a cubic extension field element to standard output. + * + * @param[in] A - the cubic extension field element to print. + */ +void fp3_print(fp3_t a); + +/** + * Returns the number of bytes necessary to store a cubic extension field + * element. + * + * @param[out] size - the result. + * @param[in] a - the extension field element. + */ +int fp3_size_bin(fp3_t a); + +/** + * Reads a cubic extension field element from a byte vector in big-endian + * format. + * + * @param[out] a - the result. + * @param[in] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @throw ERR_NO_BUFFER - if the buffer capacity is not correct. + */ +void fp3_read_bin(fp3_t a, const uint8_t *bin, int len); + +/** + * Writes a cubic extension field element to a byte vector in big-endian + * format. + * + * @param[out] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @param[in] a - the extension field element to write. + * @throw ERR_NO_BUFFER - if the buffer capacity is not correct. + */ +void fp3_write_bin(uint8_t *bin, int len, fp3_t a); + +/** + * Returns the result of a comparison between two cubic extension field + * elements. + * + * @param[in] A - the first cubic extension field element. + * @param[in] B - the second cubic extension field element. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fp3_cmp(fp3_t a, fp3_t b); + +/** + * Returns the result of a signed comparison between a cubic extension field + * element and a digit. + * + * @param[in] a - the cubic extension field element. + * @param[in] b - the digit. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fp3_cmp_dig(fp3_t a, dig_t b); + +/** + * Assigns a cubic extension field element to a digit. + * + * @param[in] a - the cubic extension field element. + * @param[in] b - the digit. + */ +void fp3_set_dig(fp3_t a, dig_t b); + +/** + * Adds two cubic extension field elements using basic arithmetic. + * + * @param[out] c - the result. + * @param[in] a - the first cubic extension field element. + * @param[in] b - the second cubic extension field element. + */ +void fp3_add_basic(fp3_t c, fp3_t a, fp3_t b); + +/** + * Adds two cubic extension field elements using integrated modular reduction. + * + * @param[out] c - the result. + * @param[in] a - the first cubic extension field element. + * @param[in] b - the second cubic extension field element. + */ +void fp3_add_integ(fp3_t c, fp3_t a, fp3_t b); + +/** + * Subtracts a cubic extension field element from another using basic + * arithmetic. + * + * @param[out] C - the result. + * @param[in] A - the first cubic extension field element. + * @param[in] B - the second cubic extension field element. + */ +void fp3_sub_basic(fp3_t c, fp3_t a, fp3_t b); + +/** + * Subtracts a cubic extension field element from another using integrated + * modular reduction. + * + * @param[out] C - the result. + * @param[in] A - the first cubic extension field element. + * @param[in] B - the second cubic extension field element. + */ +void fp3_sub_integ(fp3_t c, fp3_t a, fp3_t b); + +/** + * Negates a cubic extension field element. Computes c = -a. + * + * @param[out] C - the result. + * @param[out] A - the cubic extension field element to negate. + */ +void fp3_neg(fp3_t c, fp3_t a); + +/** + * Doubles a cubic extension field element using basic arithmetic. + * + * @param[out] c - the result. + * @param[in] a - the cubic extension field element to double. + */ +void fp3_dbl_basic(fp3_t c, fp3_t a); + +/** + * Doubles a cubic extension field element using integrated modular reduction. + * + * @param[out] c - the result. + * @param[in] a - the cubic extension field element to double. + */ +void fp3_dbl_integ(fp3_t c, fp3_t a); + +/** + * Multiples two cubic extension field elements using basic arithmetic. + * + * @param[out] c - the result. + * @param[in] a - the first cubic extension field element. + * @param[in] b - the second cubic extension field element. + */ +void fp3_mul_basic(fp3_t c, fp3_t a, fp3_t b); + +/** + * Multiples two cubic extension field elements using integrated modular + * reduction. + * + * @param[out] c - the result. + * @param[in] a - the first cubic extension field element. + * @param[in] b - the second cubic extension field element. + */ +void fp3_mul_integ(fp3_t c, fp3_t a, fp3_t b); + +/** + * Multiplies a cubic extension field element by a cubic non-residue. + * + * @param[out] c - the result. + * @param[in] a - the cubic extension field element to multiply. + */ +void fp3_mul_nor(fp3_t c, fp3_t a); + +/** + * Multiplies a cubic extension field element by a power of the constant + * needed to compute a power of the Frobenius map. If the flag is zero, the map + * is computed on the cubic extension directly; otherwise the map is computed on + * a higher extension. + * + * @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 fp3_mul_frb(fp3_t c, fp3_t a, int i, int j); + +/** + * Computes the square of a cubic extension field element using basic + * arithmetic. + * + * @param[out] c - the result. + * @param[in] a - the cubic extension field element to square. + */ +void fp3_sqr_basic(fp3_t c, fp3_t a); + +/** + * Computes the square of a cubic extension field element using integrated + * modular reduction. + * + * @param[out] c - the result. + * @param[in] a - the cubic extension field element to square. + */ +void fp3_sqr_integ(fp3_t c, fp3_t a); + +/** + * Inverts a cubic extension field element. Computes c = 1/a. + * + * @param[out] c - the result. + * @param[in] a - the cubic extension field element to invert. + */ +void fp3_inv(fp3_t c, fp3_t a); + +/** + * Inverts multiple cubic extension field elements simultaneously. + * + * @param[out] c - the result. + * @param[in] a - the cubic extension field elements to invert. + * @param[in] n - the number of elements. + */ +void fp3_inv_sim(fp3_t *c, fp3_t *a, int n); + +/** + * Computes a power of a cubic extension field element. Computes c = a^b. + * + * @param[out] c - the result. + * @param[in] a - the cubic extension element to exponentiate. + * @param[in] b - the exponent. + */ +void fp3_exp(fp3_t c, fp3_t a, bn_t b); + +/** + * Computes a power of the Frobenius map of a cubic extension field element. + * + * @param[out] c - the result. + * @param[in] a - the cubic extension element to exponentiate. + * @param[in] i - the power of the Frobenius map. + */ +void fp3_frb(fp3_t c, fp3_t a, int i); + +/** + * Extracts the square root of a cubic 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 fp3_srt(fp3_t c, fp3_t a); + +/** + * Copies the second argument to the first argument. + * + * @param[out] C - the result. + * @param[in] A - the sextic extension field element to copy. + */ +void fp4_copy(fp4_t c, fp4_t a); + +/** + * Assigns zero to a quartic extension field element. + * + * @param[out] A - the quartic extension field element to zero. + */ +void fp4_zero(fp4_t a); + +/** + * Tests if a quartic extension field element is zero or not. + * + * @param[in] A - the quartic extension field element to test. + * @return 1 if the argument is zero, 0 otherwise. + */ +int fp4_is_zero(fp4_t a); + +/** + * Assigns a random value to a quartic extension field element. + * + * @param[out] A - the quartic extension field element to assign. + */ +void fp4_rand(fp4_t a); + +/** + * Prints a quartic extension field element to standard output. + * + * @param[in] A - the quartic extension field element to print. + */ +void fp4_print(fp4_t a); + +/** + * Returns the number of bytes necessary to store a quartic extension field + * element. + * + * @param[out] size - the result. + * @param[in] a - the extension field element. + */ +int fp4_size_bin(fp4_t a); + +/** + * Reads a quartic extension field element from a byte vector in big-endian + * format. + * + * @param[out] a - the result. + * @param[in] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @throw ERR_NO_BUFFER - if the buffer capacity is not correct. + */ +void fp4_read_bin(fp4_t a, const uint8_t *bin, int len); + +/** + * Writes a quartic extension field element to a byte vector in big-endian + * format. + * + * @param[out] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @param[in] a - the extension field element to write. + * @throw ERR_NO_BUFFER - if the buffer capacity is not correct. + */ +void fp4_write_bin(uint8_t *bin, int len, fp4_t a); + +/** + * Returns the result of a comparison between two quartic extension field + * elements. + * + * @param[in] A - the first quartic extension field element. + * @param[in] B - the second quartic extension field element. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fp4_cmp(fp4_t a, fp4_t b); + +/** + * Returns the result of a signed comparison between a quartic extension field + * element and a digit. + * + * @param[in] a - the quartic extension field element. + * @param[in] b - the digit. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fp4_cmp_dig(fp4_t a, dig_t b); + +/** + * Assigns a quartic extension field element to a digit. + * + * @param[in] a - the quartic extension field element. + * @param[in] b - the digit. + */ +void fp4_set_dig(fp4_t a, dig_t b); + +/** + * Adds two quartic extension field elements. Computes c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the first quartic extension field element. + * @param[in] b - the second quartic extension field element. + */ +void fp4_add(fp4_t c, fp4_t a, fp4_t b); + +/** + * Subtracts a quartic extension field element from another. Computes + * c = a - b. + * + * @param[out] c - the result. + * @param[in] a - the quartic extension field element. + * @param[in] b - the quartic extension field element. + */ +void fp4_sub(fp4_t c, fp4_t a, fp4_t b); + +/** + * Negates a quartic extension field element. Computes c = -a. + * + * @param[out] C - the result. + * @param[out] A - the quartic extension field element to negate. + */ +void fp4_neg(fp4_t c, fp4_t a); + +/** + * Doubles a quartic extension field element. Computes c = 2 * a. + * + * @param[out] c - the result. + * @param[in] a - the quartic extension field element to double. + */ +void fp4_dbl(fp4_t c, fp4_t a); + +/** + * Multiples two quartic extension field elements without performing modular + * reduction. + * + * @param[out] c - the result. + * @param[in] a - the quartic extension field element. + * @param[in] b - the quartic extension field element. + */ +void fp4_mul_unr(dv4_t c, fp4_t a, fp4_t b); + +/** + * Multiples two quartic extension field elements. + * + * @param[out] c - the result. + * @param[in] a - the quartic extension field element. + * @param[in] b - the quartic extension field element. + */ +void fp4_mul_basic(fp4_t c, fp4_t a, fp4_t b); + +/** + * Multiples two quartic extension field elements using lazy reduction. + * + * @param[out] c - the result. + * @param[in] a - the quartic extension field element. + * @param[in] b - the quartic extension field element. + */ +void fp4_mul_lazyr(fp4_t c, fp4_t a, fp4_t b); + +/** + * Multiplies a quartic extension field element by the adjoined root. + * + * @param[out] c - the result. + * @param[in] a - the quartic extension field element to multiply. + */ +void fp4_mul_art(fp4_t c, fp4_t a); + +/** + * Multiples a dense quartic extension field element by a sparse element. + * + * @param[out] c - the result. + * @param[in] a - a quartic extension field element. + * @param[in] b - a sparse quartic extension field element. + */ +void fp4_mul_dxs(fp4_t c, fp4_t a, fp4_t b); + +/** + * Computes the square of a quartic extension field element without performing + * modular reduction. + * + * @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); + +/** + * Computes the squares of a quartic extension field element using basic + * arithmetic. + * + * @param[out] c - the result. + * @param[in] a - the quartic extension field element to square. + */ +void fp4_sqr_basic(fp4_t c, fp4_t a); + +/** + * Computes the square of a quartic extension field element using lazy reduction. + * + * @param[out] c - the result. + * @param[in] a - the quartic extension field element to square. + */ +void fp4_sqr_lazyr(fp4_t c, fp4_t a); + +/** + * Inverts a quartic extension field element. Computes c = 1/a. + * + * @param[out] c - the result. + * @param[in] a - the quartic extension field element to invert. + */ +void fp4_inv(fp4_t c, fp4_t a); + +/** + * Computes the inverse of a cyclotomic quartic extension field element. + * + * For cyclotomic elements, this is equivalent to computing the conjugate. + * A cyclotomic element is one previously raised to the (p^2 - 1)-th power. + * + * @param[out] c - the result. + * @param[in] a - the quartic extension field element to invert. + */ +void fp4_inv_cyc(fp4_t c, fp4_t a); + +/** + * Computes a power of a quartic extension field element. Computes c = a^b. + * + * @param[out] c - the result. + * @param[in] a - the quartic extension element to exponentiate. + * @param[in] b - the exponent. + */ +void fp4_exp(fp4_t c, fp4_t a, bn_t b); + +/** + * Computes a power of the Frobenius endomorphism of a quartic extension field + * element. Computes c = a^p^i. + * + * @param[out] c - the result. + * @param[in] a - a quartic extension field element. + * @param[in] i - the power of the Frobenius map. + */ +void fp4_frb(fp4_t c, fp4_t a, int i); + +/** + * Copies the second argument to the first argument. + * + * @param[out] C - the result. + * @param[in] A - the sextic extension field element to copy. + */ +void fp6_copy(fp6_t c, fp6_t a); + +/** + * Assigns zero to a sextic extension field element. + * + * @param[out] A - the sextic extension field element to zero. + */ +void fp6_zero(fp6_t a); + +/** + * Tests if a sextic extension field element is zero or not. + * + * @param[in] A - the sextic extension field element to test. + * @return 1 if the argument is zero, 0 otherwise. + */ +int fp6_is_zero(fp6_t a); + +/** + * Assigns a random value to a sextic extension field element. + * + * @param[out] A - the sextic extension field element to assign. + */ +void fp6_rand(fp6_t a); + +/** + * Prints a sextic extension field element to standard output. + * + * @param[in] A - the sextic extension field element to print. + */ +void fp6_print(fp6_t a); + +/** + * Returns the number of bytes necessary to store a quadratic extension field + * element. + * + * @param[out] size - the result. + * @param[in] a - the extension field element. + */ +int fp6_size_bin(fp6_t a); + +/** + * Reads a quadratic extension field element from a byte vector in big-endian + * format. + * + * @param[out] a - the result. + * @param[in] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @throw ERR_NO_BUFFER - if the buffer capacity is not correct. + */ +void fp6_read_bin(fp6_t a, const uint8_t *bin, int len); + +/** + * Writes a sextic extension field element to a byte vector in big-endian + * format. + * + * @param[out] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @param[in] a - the extension field element to write. + * @throw ERR_NO_BUFFER - if the buffer capacity is not correct. + */ +void fp6_write_bin(uint8_t *bin, int len, fp6_t a); + +/** + * Returns the result of a comparison between two sextic extension field + * elements. + * + * @param[in] A - the first sextic extension field element. + * @param[in] B - the second sextic extension field element. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fp6_cmp(fp6_t a, fp6_t b); + +/** + * Returns the result of a signed comparison between a sextic extension field + * element and a digit. + * + * @param[in] a - the sextic extension field element. + * @param[in] b - the digit. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fp6_cmp_dig(fp6_t a, dig_t b); + +/** + * Assigns a sextic extension field element to a digit. + * + * @param[in] a - the sextic extension field element. + * @param[in] b - the digit. + */ +void fp6_set_dig(fp6_t a, dig_t b); + +/** + * Adds two sextic extension field elements. Computes c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the first sextic extension field element. + * @param[in] b - the second sextic extension field element. + */ +void fp6_add(fp6_t c, fp6_t a, fp6_t b); + +/** + * Subtracts a sextic extension field element from another. Computes + * c = a - b. + * + * @param[out] c - the result. + * @param[in] a - the sextic extension field element. + * @param[in] b - the sextic extension field element. + */ +void fp6_sub(fp6_t c, fp6_t a, fp6_t b); + +/** + * Negates a sextic extension field element. Computes c = -a. + * + * @param[out] C - the result. + * @param[out] A - the sextic extension field element to negate. + */ +void fp6_neg(fp6_t c, fp6_t a); + +/** + * Doubles a sextic extension field element. Computes c = 2 * a. + * + * @param[out] c - the result. + * @param[in] a - the sextic extension field element to double. + */ +void fp6_dbl(fp6_t c, fp6_t a); + +/** + * Multiples two sextic extension field elements without performing modular + * reduction. + * + * @param[out] c - the result. + * @param[in] a - the sextic extension field element. + * @param[in] b - the sextic extension field element. + */ +void fp6_mul_unr(dv6_t c, fp6_t a, fp6_t b); + +/** + * Multiples two sextic extension field elements. + * + * @param[out] c - the result. + * @param[in] a - the sextic extension field element. + * @param[in] b - the sextic extension field element. + */ +void fp6_mul_basic(fp6_t c, fp6_t a, fp6_t b); + +/** + * Multiples two sextic extension field elements using lazy reduction. + * + * @param[out] c - the result. + * @param[in] a - the sextic extension field element. + * @param[in] b - the sextic extension field element. + */ +void fp6_mul_lazyr(fp6_t c, fp6_t a, fp6_t b); + +/** + * Multiplies a sextic extension field element by the adjoined root. + * + * @param[out] c - the result. + * @param[in] a - the sextic extension field element to multiply. + */ +void fp6_mul_art(fp6_t c, fp6_t a); + +/** + * Multiples a dense sextic extension field element by a sparse element. + * + * @param[out] c - the result. + * @param[in] a - a sextic extension field element. + * @param[in] b - a sparse sextic extension field element. + */ +void fp6_mul_dxs(fp6_t c, fp6_t a, fp6_t b); + +/** + * Computes the square of a sextic extension field element without performing + * modular reduction. + * + * @param[out] c - the result. + * @param[in] a - the sextic extension field element to square. + */ +void fp6_sqr_unr(dv6_t c, fp6_t a); + +/** + * Computes the squares of a sextic extension field element using basic + * arithmetic. + * + * @param[out] c - the result. + * @param[in] a - the sextic extension field element to square. + */ +void fp6_sqr_basic(fp6_t c, fp6_t a); + +/** + * Computes the square of a sextic extension field element using lazy reduction. + * + * @param[out] c - the result. + * @param[in] a - the sextic extension field element to square. + */ +void fp6_sqr_lazyr(fp6_t c, fp6_t a); + +/** + * Inverts a sextic extension field element. Computes c = 1/a. + * + * @param[out] c - the result. + * @param[in] a - the sextic extension field element to invert. + */ +void fp6_inv(fp6_t c, fp6_t a); + +/** + * Computes a power of a sextic extension field element. Computes c = a^b. + * + * @param[out] c - the result. + * @param[in] a - the sextic extension element to exponentiate. + * @param[in] b - the exponent. + */ +void fp6_exp(fp6_t c, fp6_t a, bn_t b); + +/** + * Computes a power of the Frobenius endomorphism of a sextic extension field + * element. Computes c = a^p^i. + * + * @param[out] c - the result. + * @param[in] a - a sextic extension field element. + * @param[in] i - the power of the Frobenius map. + */ +void fp6_frb(fp6_t c, fp6_t a, int i); + +/** + * Copies the second argument to the first argument. + * + * @param[out] C - the result. + * @param[in] A - the octic extension field element to copy. + */ +void fp8_copy(fp8_t c, fp8_t a); + +/** + * Assigns zero to an octic extension field element. + * + * @param[out] A - the octic extension field element to zero. + */ +void fp8_zero(fp8_t a); + +/** + * Tests if an octic extension field element is zero or not. + * + * @param[in] A - the octic extension field element to test. + * @return 1 if the argument is zero, 0 otherwise. + */ +int fp8_is_zero(fp8_t a); + +/** + * Assigns a random value to an octic extension field element. + * + * @param[out] A - the octic extension field element to assign. + */ +void fp8_rand(fp8_t a); + +/** + * Prints an octic extension field element to standard output. + * + * @param[in] A - the octic extension field element to print. + */ +void fp8_print(fp8_t a); + +/** + * Returns the number of bytes necessary to store an octic extension field + * element. + * + * @param[in] a - the extension field element. + * @param[in] pack - the flag to indicate compression. + * @return the number of bytes. + */ +int fp8_size_bin(fp8_t a, int pack); + +/** + * Reads an octic extension field element from a byte vector in big-endian + * format. + * + * @param[out] a - the result. + * @param[in] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @throw ERR_NO_BUFFER - if the buffer capacity is not correct. + */ +void fp8_read_bin(fp8_t a, const uint8_t *bin, int len); + +/** + * Writes an octic extension field element to a byte vector in big-endian + * format. + * + * @param[out] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @param[in] a - the extension field element to write. + * @throw ERR_NO_BUFFER - if the buffer capacity is not correct. + */ +void fp8_write_bin(uint8_t *bin, int len, fp8_t a); + +/** + * Returns the result of a comparison between two octic extension field + * elements. + * + * @param[in] A - the first octic extension field element. + * @param[in] B - the second octic extension field element. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fp8_cmp(fp8_t a, fp8_t b); + +/** + * Returns the result of a signed comparison between an octic extension field + * element and a digit. + * + * @param[in] a - the octic extension field element. + * @param[in] b - the digit. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fp8_cmp_dig(fp8_t a, dig_t b); + +/** + * Assigns an octic extension field element to a digit. + * + * @param[in] a - the octic extension field element. + * @param[in] b - the digit. + */ +void fp8_set_dig(fp8_t a, dig_t b); + +/** + * Adds two octic extension field elements. Computes c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the first octic extension field element. + * @param[in] b - the second octic extension field element. + */ +void fp8_add(fp8_t c, fp8_t a, fp8_t b); + +/** + * Subtracts an octic extension field element from another. Computes + * c = a - b. + * + * @param[out] c - the result. + * @param[in] a - the octic extension field element. + * @param[in] b - the octic extension field element. + */ +void fp8_sub(fp8_t c, fp8_t a, fp8_t b); + +/** + * Negates an octic extension field element. Computes c = -a. + * + * @param[out] C - the result. + * @param[out] A - the octic extension field element to negate. + */ +void fp8_neg(fp8_t c, fp8_t a); + +/** + * Doubles an octic extension field element. Computes c = 2 * a. + * + * @param[out] c - the result. + * @param[in] a - the octic extension field element to double. + */ +void fp8_dbl(fp8_t c, fp8_t a); + +/** + * Multiples two octic extension field elements without performing modular + * reduction. + * + * @param[out] c - the result. + * @param[in] a - the octic extension field element. + * @param[in] b - the octic extension field element. + */ +void fp8_mul_unr(dv8_t c, fp8_t a, fp8_t b); + +/** + * Multiples two octic extension field elements. + * + * @param[out] c - the result. + * @param[in] a - the octic extension field element. + * @param[in] b - the octic extension field element. + */ +void fp8_mul_basic(fp8_t c, fp8_t a, fp8_t b); + +/** + * Multiples two octic extension field elements using lazy reduction. + * + * @param[out] c - the result. + * @param[in] a - the octic extension field element. + * @param[in] b - the octic extension field element. + */ +void fp8_mul_lazyr(fp8_t c, fp8_t a, fp8_t b); + +/** + * Multiplies an octic extension field element by the adjoined root. + * + * @param[out] c - the result. + * @param[in] a - the octic extension field element to multiply. + */ +void fp8_mul_art(fp8_t c, fp8_t a); + +/** + * Multiples a dense octic extension field element by a sparse element. + * + * @param[out] c - the result. + * @param[in] a - an octic extension field element. + * @param[in] b - a sparse octic extension field element. + */ +void fp8_mul_dxs(fp8_t c, fp8_t a, fp8_t b); + +/** + * Computes the square of an octic extension field element without performing + * modular reduction. + * + * @param[out] c - the result. + * @param[in] a - the octic extension field element to square. + */ +void fp8_sqr_unr(dv8_t c, fp8_t a); + +/** + * Computes the squares of an octic extension field element using basic + * arithmetic. + * + * @param[out] c - the result. + * @param[in] a - the octic extension field element to square. + */ +void fp8_sqr_basic(fp8_t c, fp8_t a); + +/** + * Computes the square of an octic extension field element using lazy reduction. + * + * @param[out] c - the result. + * @param[in] a - the octic extension field element to square. + */ +void fp8_sqr_lazyr(fp8_t c, fp8_t a); + +/** + * Computes the square of a cyclotomic octic extension field element. + * + * @param[out] c - the result. + * @param[in] a - the cyclotomic extension element to square. + */ +void fp8_sqr_cyc(fp8_t c, fp8_t a); + +/** + * Inverts an octic extension field element. Computes c = 1/a. + * + * @param[out] c - the result. + * @param[in] a - the octic extension field element to invert. + */ +void fp8_inv(fp8_t c, fp8_t a); + +/** + * Computes the inverse of a cyclotomic octic extension field element. + * + * For cyclotomic elements, this is equivalent to computing the conjugate. + * A cyclotomic element is one previously raised to the (p^4 - 1)-th power. + * + * @param[out] c - the result. + * @param[in] a - the octic extension field element to invert. + */ +void fp8_inv_cyc(fp8_t c, fp8_t a); + +/** + * Inverts multiple octic extension field elements simultaneously. + * + * @param[out] c - the result. + * @param[in] a - the octic extension field elements to invert. + * @param[in] n - the number of elements. + */ +void fp8_inv_sim(fp8_t *c, fp8_t *a, int n); + +/** + * Tests if an octic extension field element is cyclotomic. + * + * @param[in] a - the octic extension field element to test. + * @return 1 if the extension field element is cyclotomic, 0 otherwise. + */ +int fp8_test_cyc(fp8_t a); + +/** + * Converts an octic extension field element to a cyclotomic element. Computes + * c = a^(p^4 - 1). + * + * @param[out] c - the result. + * @param[in] a - the octic extension field element. + */ +void fp8_conv_cyc(fp8_t c, fp8_t a); + +/** + * Computes a power of an octic extension field element. Computes c = a^b. + * + * @param[out] c - the result. + * @param[in] a - the octic extension element to exponentiate. + * @param[in] b - the exponent. + */ +void fp8_exp(fp8_t c, fp8_t a, bn_t b); + +/** + * Computes a power of a cyclotomic octic extension field element. + * + * @param[out] c - the result. + * @param[in] a - the basis. + * @param[in] b - the exponent. + */ +void fp8_exp_cyc(fp8_t c, fp8_t a, bn_t b); + +/** + * Computes a power of the Frobenius endomorphism of an octic extension field + * element. Computes c = a^p^i. + * + * @param[out] c - the result. + * @param[in] a - an octic extension field element. + * @param[in] i - the power of the Frobenius map. + */ +void fp8_frb(fp8_t c, fp8_t a, int i); + +/** + * Copies the second argument to the first argument. + * + * @param[out] C - the result. + * @param[in] A - the nonic extension field element to copy. + */ +void fp9_copy(fp9_t c, fp9_t a); + +/** + * Assigns zero to a nonic extension field element. + * + * @param[out] A - the nonic extension field element to zero. + */ +void fp9_zero(fp9_t a); + +/** + * Tests if a nonic extension field element is zero or not. + * + * @param[in] A - the nonic extension field element to test. + * @return 1 if the argument is zero, 0 otherwise. + */ +int fp9_is_zero(fp9_t a); + +/** + * Assigns a random value to a nonic extension field element. + * + * @param[out] A - the nonic extension field element to assign. + */ +void fp9_rand(fp9_t a); + +/** + * Prints a nonic extension field element to standard output. + * + * @param[in] A - the nonic extension field element to print. + */ +void fp9_print(fp9_t a); + +/** + * Returns the number of bytes necessary to store a quadratic extension field + * element. + * + * @param[out] size - the result. + * @param[in] a - the extension field element. + */ +int fp9_size_bin(fp9_t a); + +/** + * Reads a quadratic extension field element from a byte vector in big-endian + * format. + * + * @param[out] a - the result. + * @param[in] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @throw ERR_NO_BUFFER - if the buffer capacity is not correct. + */ +void fp9_read_bin(fp9_t a, const uint8_t *bin, int len); + +/** + * Writes a nonic extension field element to a byte vector in big-endian + * format. + * + * @param[out] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @param[in] a - the extension field element to write. + * @throw ERR_NO_BUFFER - if the buffer capacity is not correct. + */ +void fp9_write_bin(uint8_t *bin, int len, fp9_t a); + +/** + * Returns the result of a comparison between two nonic extension field + * elements. + * + * @param[in] A - the first nonic extension field element. + * @param[in] B - the second nonic extension field element. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fp9_cmp(fp9_t a, fp9_t b); + +/** + * Returns the result of a signed comparison between a nonic extension field + * element and a digit. + * + * @param[in] a - the nonic extension field element. + * @param[in] b - the digit. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fp9_cmp_dig(fp9_t a, dig_t b); + +/** + * Assigns a nonic extension field element to a digit. + * + * @param[in] a - the nonic extension field element. + * @param[in] b - the digit. + */ +void fp9_set_dig(fp9_t a, dig_t b); + +/** + * Adds two nonic extension field elements. Computes c = a + b. + * + * @param[out] c - the result. + * @param[in] a - the first nonic extension field element. + * @param[in] b - the second nonic extension field element. + */ +void fp9_add(fp9_t c, fp9_t a, fp9_t b); + +/** + * Subtracts a nonic extension field element from another. Computes + * c = a - b. + * + * @param[out] c - the result. + * @param[in] a - the nonic extension field element. + * @param[in] b - the nonic extension field element. + */ +void fp9_sub(fp9_t c, fp9_t a, fp9_t b); + +/** + * Negates a nonic extension field element. Computes c = -a. + * + * @param[out] C - the result. + * @param[out] A - the nonic extension field element to negate. + */ +void fp9_neg(fp9_t c, fp9_t a); + +/** + * Doubles a nonic extension field element. Computes c = 2 * a. + * + * @param[out] c - the result. + * @param[in] a - the nonic extension field element to double. + */ +void fp9_dbl(fp9_t c, fp9_t a); + +/** + * Multiples two nonic extension field elements without performing modular + * reduction. + * + * @param[out] c - the result. + * @param[in] a - the nonic extension field element. + * @param[in] b - the nonic extension field element. + */ +void fp9_mul_unr(dv9_t c, fp9_t a, fp9_t b); + +/** + * Multiples two nonic extension field elements. + * + * @param[out] c - the result. + * @param[in] a - the nonic extension field element. + * @param[in] b - the nonic extension field element. + */ +void fp9_mul_basic(fp9_t c, fp9_t a, fp9_t b); + +/** + * Multiples two nonic extension field elements using lazy reduction. + * + * @param[out] c - the result. + * @param[in] a - the nonic extension field element. + * @param[in] b - the nonic extension field element. + */ +void fp9_mul_lazyr(fp9_t c, fp9_t a, fp9_t b); + +/** + * Multiplies a nonic extension field element by the adjoined root. + * + * @param[out] c - the result. + * @param[in] a - the nonic extension field element to multiply. + */ +void fp9_mul_art(fp9_t c, fp9_t a); + +/** + * Multiples a dense nonic extension field element by a sparse element. + * + * @param[out] c - the result. + * @param[in] a - a nonic extension field element. + * @param[in] b - a sparse nonic extension field element. + */ +void fp9_mul_dxs(fp9_t c, fp9_t a, fp9_t b); + +/** + * Computes the square of a nonic extension field element without performing + * modular reduction. + * + * @param[out] c - the result. + * @param[in] a - the nonic extension field element to square. + */ +void fp9_sqr_unr(dv9_t c, fp9_t a); + +/** + * Computes the squares of a nonic extension field element using basic + * arithmetic. + * + * @param[out] c - the result. + * @param[in] a - the nonic extension field element to square. + */ +void fp9_sqr_basic(fp9_t c, fp9_t a); + +/** + * Computes the square of a nonic extension field element using lazy reduction. + * + * @param[out] c - the result. + * @param[in] a - the nonic extension field element to square. + */ +void fp9_sqr_lazyr(fp9_t c, fp9_t a); + +/** + * Inverts a nonic extension field element. Computes c = 1/a. + * + * @param[out] c - the result. + * @param[in] a - the nonic extension field element to invert. + */ +void fp9_inv(fp9_t c, fp9_t a); + +/** + * Inverts multiple noinc extension field elements simultaneously. + * + * @param[out] c - the result. + * @param[in] a - the nonic extension field elements to invert. + * @param[in] n - the number of elements. + */ +void fp9_inv_sim(fp9_t *c, fp9_t *a, int n); + +/** + * Computes a power of a nonic extension field element. Computes c = a^b. + * + * @param[out] c - the result. + * @param[in] a - the nonic extension element to exponentiate. + * @param[in] b - the exponent. + */ +void fp9_exp(fp9_t c, fp9_t a, bn_t b); + +/** + * Computes a power of the Frobenius endomorphism of a nonic extension field + * element. Computes c = a^p^i. + * + * @param[out] c - the result. + * @param[in] a - a nonic extension field element. + * @param[in] i - the power of the Frobenius map. + */ +void fp9_frb(fp9_t c, fp9_t a, int i); + +/** + * Copies the second argument to the first argument. + * + * @param[out] C - the result. + * @param[in] A - the dodecic extension field element to copy. + */ +void fp12_copy(fp12_t c, fp12_t a); + +/** + * Assigns zero to a dodecic extension field element. + * + * @param[out] A - the dodecic extension field element to zero. + */ +void fp12_zero(fp12_t a); + +/** + * Tests if a dodecic extension field element is zero or not. + * + * @param[in] A - the dodecic extension field element to test. + * @return 1 if the argument is zero, 0 otherwise. + */ +int fp12_is_zero(fp12_t a); + +/** + * Assigns a random value to a dodecic extension field element. + * + * @param[out] A - the dodecic extension field element to assign. + */ +void fp12_rand(fp12_t a); + +/** + * Prints a dodecic extension field element to standard output. + * + * @param[in] A - the dodecic extension field element to print. + */ +void fp12_print(fp12_t a); + +/** + * Returns the number of bytes necessary to store a dodecic extension field + * element. + * + * @param[in] a - the extension field element. + * @param[in] pack - the flag to indicate compression. + * @return the number of bytes. + */ +int fp12_size_bin(fp12_t a, int pack); + +/** + * Reads a dodecic extension field element from a byte vector in big-endian + * format. + * + * @param[out] a - the result. + * @param[in] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @throw ERR_NO_BUFFER - if the buffer capacity is not correct. + */ +void fp12_read_bin(fp12_t a, const uint8_t *bin, int len); + +/** + * Writes a dodecic extension field element to a byte vector in big-endian + * format. + * + * @param[out] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @param[in] a - the extension field element to write. + * @param[in] pack - the flag to indicate compression. + * @throw ERR_NO_BUFFER - if the buffer capacity is not correct. + */ +void fp12_write_bin(uint8_t *bin, int len, fp12_t a, int pack); + +/** + * Returns the result of a comparison between two dodecic extension field + * elements. + * + * @param[in] a - the first dodecic extension field element. + * @param[in] b - the second dodecic extension field element. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fp12_cmp(fp12_t a, fp12_t b); + +/** + * Returns the result of a signed comparison between a dodecic extension field + * element and a digit. + * + * @param[in] a - the dodecic extension field element. + * @param[in] b - the digit. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fp12_cmp_dig(fp12_t a, dig_t b); + +/** + * Assigns a dodecic extension field element to a digit. + * + * @param[in] a - the dodecic extension field element. + * @param[in] b - the digit. + */ +void fp12_set_dig(fp12_t a, dig_t b); + +/** + * Adds two dodecic extension field elements. Computes C = A + B. + * + * @param[out] C - the result. + * @param[in] A - the first dodecic extension field element. + * @param[in] B - the second dodecic extension field element. + */ +void fp12_add(fp12_t c, fp12_t a, fp12_t b); + +/** + * Subtracts a dodecic extension field element from another. Computes + * C = A - B. + * + * @param[out] C - the result. + * @param[in] A - the first dodecic extension field element. + * @param[in] B - the second dodecic extension field element. + */ +void fp12_sub(fp12_t c, fp12_t a, fp12_t b); + +/** + * Negates a dodecic extension field element. + * + * @param[out] C - the result. + * @param[out] A - the dodecic extension field element to negate. + */ +void fp12_neg(fp12_t c, fp12_t a); + +/** + * Doubles a dodecic extension field element. Computes c = 2 * a. + * + * @param[out] c - the result. + * @param[in] a - the dodecic extension field element to double. + */ +void fp12_dbl(fp12_t c, fp12_t a); + +/** + * Multiples two dodecic extension field elements without performing modular + * reduction. + * + * @param[out] c - the result. + * @param[in] a - the dodecic extension field element. + * @param[in] b - the dodecic extension field element. + */ +void fp12_mul_unr(dv12_t c, fp12_t a, fp12_t b); + +/** + * Multiples two dodecic extension field elements using basic arithmetic. + * + * @param[out] c - the result. + * @param[in] a - the dodecic extension field element. + * @param[in] b - the dodecic extension field element. + */ +void fp12_mul_basic(fp12_t c, fp12_t a, fp12_t b); + +/** + * Multiples two dodecic extension field elements using lazy reduction. + * + * @param[out] c - the result. + * @param[in] a - the dodecic extension field element. + * @param[in] b - the dodecic extension field element. + */ +void fp12_mul_lazyr(fp12_t c, fp12_t a, fp12_t b); + +/** + * Multiplies a dodecic extension field element by the adjoined root. + * + * @param[out] c - the result. + * @param[in] a - the dodecic extension field element to multiply. + */ +void fp12_mul_art(fp12_t c, fp12_t a); + +/** + * Multiples a dense dodecic extension field element by a sparse element using + * basic arithmetic. + * + * @param[out] c - the result. + * @param[in] a - the dense dodecic extension field element. + * @param[in] b - the sparse dodecic extension field element. + */ +void fp12_mul_dxs_basic(fp12_t c, fp12_t a, fp12_t b); + +/** + * Multiples a dense dodecic extension field element by a sparse element using + * lazy reduction. + * + * @param[out] c - the result. + * @param[in] a - the dense dodecic extension field element. + * @param[in] b - the sparse dodecic extension field element. + */ +void fp12_mul_dxs_lazyr(fp12_t c, fp12_t a, fp12_t b); + +/** + * Computes the square of a dodecic extension field element without performing + * modular reduction. + * + * @param[out] c - the result. + * @param[in] a - the dodecic extension field element to square. + */ +void fp12_sqr_unr(dv12_t c, fp12_t a); + +/** + * Computes the square of a dodecic extension field element using basic + * arithmetic. + * + * @param[out] c - the result. + * @param[in] a - the dodecic extension field element to square. + */ +void fp12_sqr_basic(fp12_t c, fp12_t a); + +/** + * Computes the square of a dodecic extension field element using lazy + * reduction. + * + * @param[out] c - the result. + * @param[in] a - the dodecic extension field element to square. + */ +void fp12_sqr_lazyr(fp12_t c, fp12_t a); + +/** + * Computes the square of a cyclotomic dodecic 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 fp12_sqr_cyc_basic(fp12_t c, fp12_t a); + +/** + * Computes the square of a cyclotomic dodecic 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 fp12_sqr_cyc_lazyr(fp12_t c, fp12_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 fp12_sqr_pck_basic(fp12_t c, fp12_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 fp12_sqr_pck_lazyr(fp12_t c, fp12_t a); + +/** + * Tests if a dodecic extension field element belongs to the cyclotomic + * subgroup. + * + * @param[in] a - the dodecic extension field element to test. + * @return 1 if the extension field element is in the subgroup, 0 otherwise. + */ +int fp12_test_cyc(fp12_t a); + +/** + * Converts a dodecic 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 dodecic extension field element. + */ +void fp12_conv_cyc(fp12_t c, fp12_t a); + +/** + * Decompresses a compressed cyclotomic extension field element. + * + * @param[out] c - the result. + * @param[in] a - the dodecic extension field element to decompress. + */ +void fp12_back_cyc(fp12_t c, fp12_t a); + +/** + * Decompresses multiple compressed cyclotomic extension field elements. + * + * @param[out] c - the result. + * @param[in] a - the dodecic field elements to decompress. + * @param[in] n - the number of field elements to decompress. + */ +void fp12_back_cyc_sim(fp12_t *c, fp12_t *a, int n); + +/** + * Inverts a dodecic extension field element. Computes c = 1/a. + * + * @param[out] c - the result. + * @param[in] a - the dodecic extension field element to invert. + */ +void fp12_inv(fp12_t c, fp12_t a); + +/** + * Computes the inverse of a cyclotomic dodecic extension field element. + * For unitary elements, this is equivalent to computing the conjugate. + * A unitary element is one previously raised to the (p^6 - 1)-th power. + * + * @param[out] c - the result. + * @param[in] a - the dodecic extension field element to invert. + */ +void fp12_inv_cyc(fp12_t c, fp12_t a); + +/** + * Computes the Frobenius endomorphism of a dodecic extension element. + * Computes c = a^p. + * + * @param[out] c - the result. + * @param[in] a - a dodecic extension field element. + * @param[in] i - the power of the Frobenius map. + */ +void fp12_frb(fp12_t c, fp12_t a, int i); + +/** + * Computes a power of a dodecic extension field element. + * 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 fp12_exp(fp12_t c, fp12_t a, bn_t b); + +/** + * Computes a power of a dodecic 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 fp12_exp_dig(fp12_t c, fp12_t a, dig_t b); + +/** + * Computes a power of a cyclotomic dodecic extension field element. + * + * @param[out] c - the result. + * @param[in] a - the basis. + * @param[in] b - the exponent. + */ +void fp12_exp_cyc(fp12_t c, fp12_t a, bn_t b); + +/** + * Computes a power of a cyclotomic dodecic 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 fp12_exp_cyc_sps(fp12_t c, fp12_t a, const int *b, int l, int s); + +/** + * Compresses a dodecic extension field element. + * + * @param[out] r - the result. + * @param[in] p - the dodecic extension field element to compress. + */ +void fp12_pck(fp12_t c, fp12_t a); + +/** + * Decompresses a dodecic extension field element. + * + * @param[out] r - the result. + * @param[in] p - the dodecic extension field element to decompress. + * @return if the decompression was successful + */ +int fp12_upk(fp12_t c, fp12_t a); + +/** + * Copies the second argument to the first argument. + * + * @param[out] C - the result. + * @param[in] A - the octdecic extension field element to copy. + */ +void fp18_copy(fp18_t c, fp18_t a); + +/** + * Assigns zero to an octdecic extension field element. + * + * @param[out] A - the octdecic extension field element to zero. + */ +void fp18_zero(fp18_t a); + +/** + * Tests if an octdecic extension field element is zero or not. + * + * @param[in] A - the octdecic extension field element to test. + * @return 1 if the argument is zero, 0 otherwise. + */ +int fp18_is_zero(fp18_t a); + +/** + * Assigns a random value to an octdecic extension field element. + * + * @param[out] A - the octdecic extension field element to assign. + */ +void fp18_rand(fp18_t a); + +/** + * Prints an octdecic extension field element to standard output. + * + * @param[in] A - the octdecic extension field element to print. + */ +void fp18_print(fp18_t a); + +/** + * Returns the number of bytes necessary to store an octdecic extension field + * element. + * + * @param[in] a - the extension field element. + * @return the number of bytes. + */ +int fp18_size_bin(fp18_t a); + +/** + * Reads an octdecic extension field element from a byte vector in big-endian + * format. + * + * @param[out] a - the result. + * @param[in] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @throw ERR_NO_BUFFER - if the buffer capacity is not correct. + */ +void fp18_read_bin(fp18_t a, const uint8_t *bin, int len); + +/** + * Writes an octdecic extension field element to a byte vector in big-endian + * format. + * + * @param[out] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @param[in] a - the extension field element to write. + * @throw ERR_NO_BUFFER - if the buffer capacity is not correct. + */ +void fp18_write_bin(uint8_t *bin, int len, fp18_t a); + +/** + * Returns the result of a comparison between two octdecic extension field + * elements. + * + * @param[in] a - the first octdecic extension field element. + * @param[in] b - the second octdecic extension field element. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fp18_cmp(fp18_t a, fp18_t b); + +/** + * Returns the result of a signed comparison between an octdecic extension + * field element and a digit. + * + * @param[in] a - the octdecic extension field element. + * @param[in] b - the digit. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fp18_cmp_dig(fp18_t a, dig_t b); + +/** + * Assigns an octdecic extension field element to a digit. + * + * @param[in] a - the octdecic extension field element. + * @param[in] b - the digit. + */ +void fp18_set_dig(fp18_t a, dig_t b); + +/** + * Adds two octdecic extension field elements. Computes C = A + B. + * + * @param[out] C - the result. + * @param[in] A - the first octdecic extension field element. + * @param[in] B - the second octdecic extension field element. + */ +void fp18_add(fp18_t c, fp18_t a, fp18_t b); + +/** + * Subtracts an octdecic extension field element from another. Computes + * C = A - B. + * + * @param[out] C - the result. + * @param[in] A - the first octdecic extension field element. + * @param[in] B - the second octdecic extension field element. + */ +void fp18_sub(fp18_t c, fp18_t a, fp18_t b); + +/** + * Negates an octdecic extension field element. + * + * @param[out] C - the result. + * @param[out] A - the octdecic extension field element to negate. + */ +void fp18_neg(fp18_t c, fp18_t a); + +/** + * Doubles an octdecic extension field element. Computes c = 2 * a. + * + * @param[out] c - the result. + * @param[in] a - the octdecic extension field element to double. + */ +void fp18_dbl(fp18_t c, fp18_t a); + +/** + * Multiples two octdecic extension field elements without performing modular + * reduction. + * + * @param[out] c - the result. + * @param[in] a - the octdecic extension field element. + * @param[in] b - the octdecic extension field element. + */ +void fp18_mul_unr(dv18_t c, fp18_t a, fp18_t b); + +/** + * Multiples two octdecic extension field elements using basic arithmetic. + * + * @param[out] c - the result. + * @param[in] a - the octdecic extension field element. + * @param[in] b - the octdecic extension field element. + */ +void fp18_mul_basic(fp18_t c, fp18_t a, fp18_t b); + +/** + * Multiples two octdecic extension field elements using lazy reduction. + * + * @param[out] c - the result. + * @param[in] a - the octdecic extension field element. + * @param[in] b - the octdecic extension field element. + */ +void fp18_mul_lazyr(fp18_t c, fp18_t a, fp18_t b); + +/** + * Multiplies an octdecic extension field element by the adjoined root. + * + * @param[out] c - the result. + * @param[in] a - the octdecic extension field element to multiply. + */ +void fp18_mul_art(fp18_t c, fp18_t a); + +/** + * Multiples a dense octdecic extension field element by a sparse element using + * basic arithmetic. + * + * @param[out] c - the result. + * @param[in] a - the dense octdecic extension field element. + * @param[in] b - the sparse octdecic extension field element. + */ +void fp18_mul_dxs_basic(fp18_t c, fp18_t a, fp18_t b); + +/** + * Multiples a dense octdecic extension field element by a sparse element using + * lazy reduction. + * + * @param[out] c - the result. + * @param[in] a - the dense octdecic extension field element. + * @param[in] b - the sparse octdecic extension field element. + */ +void fp18_mul_dxs_lazyr(fp18_t c, fp18_t a, fp18_t b); + +/** + * Computes the square of an octdecic extension field element without performing + * modular reduction. + * + * @param[out] c - the result. + * @param[in] a - the octdecic extension field element to square. + */ +void fp18_sqr_unr(dv18_t c, fp18_t a); + +/** + * Computes the square of an octdecic extension field element using basic + * arithmetic. + * + * @param[out] c - the result. + * @param[in] a - the octdecic extension field element to square. + */ +void fp18_sqr_basic(fp18_t c, fp18_t a); + +/** + * Computes the square of an octdecic extension field element using lazy + * reduction. + * + * @param[out] c - the result. + * @param[in] a - the octdecic extension field element to square. + */ +void fp18_sqr_lazyr(fp18_t c, fp18_t a); + +/** + * Inverts an octdecic extension field element. Computes c = 1/a. + * + * @param[out] c - the result. + * @param[in] a - the octdecic extension field element to invert. + */ +void fp18_inv(fp18_t c, fp18_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^9 - 1)-th power. + * + * @param[out] c - the result. + * @param[in] a - the octdecic extension field element to invert. + */ +void fp18_inv_cyc(fp18_t c, fp18_t a); + +/** + * Converts an octdecic extension field element to a cyclotomic element. + * Computes c = a^(p^9 - 1). + * + * @param[out] c - the result. + * @param[in] a - an octdecic extension field element. + */ +void fp18_conv_cyc(fp18_t c, fp18_t a); + +/** + * Computes the Frobenius endomorphism of an octdecic extension element. + * Computes c = a^(p^i). + * + * @param[out] c - the result. + * @param[in] a - an octdecic extension field element. + * @param[in] i - the power of the Frobenius map. + */ +void fp18_frb(fp18_t c, fp18_t a, int i); + +/** + * Computes a power of an octdecic extension field element. + * Faster formulas are used if the field element is cyclotomic. + * + * @param[out] c - the result. + * @param[in] a - the basis. + * @param[in] b - the exponent. + */ +void fp18_exp(fp18_t c, fp18_t a, bn_t b); + +/** + * Copies the second argument to the first argument. + * + * @param[out] C - the result. + * @param[in] A - the 24-degree extension field element to copy. + */ +void fp24_copy(fp24_t c, fp24_t a); + +/** + * Assigns zero to a 24-degree extension field element. + * + * @param[out] A - the 24-degree extension field element to zero. + */ +void fp24_zero(fp24_t a); + +/** + * Tests if a 24-degree extension field element is zero or not. + * + * @param[in] A - the 24-degree extension field element to test. + * @return 1 if the argument is zero, 0 otherwise. + */ +int fp24_is_zero(fp24_t a); + +/** + * Assigns a random value to a 24-degree extension field element. + * + * @param[out] A - the 24-degree extension field element to assign. + */ +void fp24_rand(fp24_t a); + +/** + * Prints a 24-degree extension field element to standard output. + * + * @param[in] A - the 24-degree extension field element to print. + */ +void fp24_print(fp24_t a); + +/** + * Returns the number of bytes necessary to store a 24-degree extension field + * element. + * + * @param[in] a - the extension field element. + * @return the number of bytes. + */ +int fp24_size_bin(fp24_t a); + +/** + * Reads a 24-degree extension field element from a byte vector in big-endian + * format. + * + * @param[out] a - the result. + * @param[in] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @throw ERR_NO_BUFFER - if the buffer capacity is not correct. + */ +void fp24_read_bin(fp24_t a, const uint8_t *bin, int len); + +/** + * Writes a 24-degree extension field element to a byte vector in big-endian + * format. + * + * @param[out] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @param[in] a - the extension field element to write. + * @throw ERR_NO_BUFFER - if the buffer capacity is not correct. + */ +void fp24_write_bin(uint8_t *bin, int len, fp24_t a); + +/** + * Returns the result of a comparison between two 24-degree extension field + * elements. + * + * @param[in] a - the first 24-degree extension field element. + * @param[in] b - the second 24-degree extension field element. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fp24_cmp(fp24_t a, fp24_t b); + +/** + * Returns the result of a signed comparison between a 24-degree extension field + * element and a digit. + * + * @param[in] a - the 24-degree extension field element. + * @param[in] b - the digit. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fp24_cmp_dig(fp24_t a, dig_t b); + +/** + * Assigns a 24-degree extension field element to a digit. + * + * @param[in] a - the 24-degree extension field element. + * @param[in] b - the digit. + */ +void fp24_set_dig(fp24_t a, dig_t b); + +/** + * Adds two 24-degree extension field elements. Computes C = A + B. + * + * @param[out] C - the result. + * @param[in] A - the first 24-degree extension field element. + * @param[in] B - the second 24-degree extension field element. + */ +void fp24_add(fp24_t c, fp24_t a, fp24_t b); + +/** + * Subtracts a 24-degree extension field element from another. Computes + * C = A - B. + * + * @param[out] C - the result. + * @param[in] A - the first 24-degree extension field element. + * @param[in] B - the second 24-degree extension field element. + */ +void fp24_sub(fp24_t c, fp24_t a, fp24_t b); + +/** + * Negates a 24-degree extension field element. + * + * @param[out] C - the result. + * @param[out] A - the 24-degree extension field element to negate. + */ +void fp24_neg(fp24_t c, fp24_t a); + +/** + * Doubles a 24-degree extension field element. Computes c = 2 * a. + * + * @param[out] c - the result. + * @param[in] a - the octic extension field element to double. + */ +void fp24_dbl(fp24_t c, fp24_t a); + +/** + * Multiples two 24-degree extension field elements without performing modular + * reduction. + * + * @param[out] c - the result. + * @param[in] a - the 24-degree extension field element. + * @param[in] b - the 24-degree extension field element. + */ +void fp24_mul_unr(dv24_t c, fp24_t a, fp24_t b); + +/** + * Multiples two 24-degree extension field elements using basic arithmetic. + * + * @param[out] c - the result. + * @param[in] a - the 24-degree extension field element. + * @param[in] b - the 24-degree extension field element. + */ +void fp24_mul_basic(fp24_t c, fp24_t a, fp24_t b); + +/** + * Multiples two 24-degree extension field elements using lazy reduction. + * + * @param[out] c - the result. + * @param[in] a - the 24-degree extension field element. + * @param[in] b - the 24-degree extension field element. + */ +void fp24_mul_lazyr(fp24_t c, fp24_t a, fp24_t b); + +/** + * Multiplies a 24-degree extension field element by the adjoined root. + * + * @param[out] c - the result. + * @param[in] a - the dodecic extension field element to multiply. + */ +void fp24_mul_art(fp24_t c, fp24_t a); + +/** + * Multiples a dense 24-degree extension field element by a sparse element. + * + * @param[out] c - the result. + * @param[in] a - a 24-degree extension field element. + * @param[in] b - a 24-degree quartic extension field element. + */ +void fp24_mul_dxs(fp24_t c, fp24_t a, fp24_t b); + +/** + * Computes the square of a 24-degree extension field element without performing + * modular reduction. + * + * @param[out] c - the result. + * @param[in] a - the 24-degree extension field element to square. + */ +void fp24_sqr_unr(dv24_t c, fp24_t a); + +/** + * Computes the square of a 24-degree extension field element using basic + * arithmetic. + * + * @param[out] c - the result. + * @param[in] a - the 24-degree extension field element to square. + */ +void fp24_sqr_basic(fp24_t c, fp24_t a); + +/** + * Computes the square of a 24-degree extension field element using lazy + * reduction. + * + * @param[out] c - the result. + * @param[in] a - the 24-degree extension field element to square. + */ +void fp24_sqr_lazyr(fp24_t c, fp24_t a); + +/** + * Inverts a 24-degree extension field element. Computes c = 1/a. + * + * @param[out] c - the result. + * @param[in] a - the 24-degree extension field element to invert. + */ +void fp24_inv(fp24_t c, fp24_t a); + +/** + * Computes the Frobenius endomorphism of a 24-degree extension element. + * Computes c = a^p. + * + * @param[out] c - the result. + * @param[in] a - a 24-degree extension field element. + * @param[in] i - the power of the Frobenius map. + */ +void fp24_frb(fp24_t c, fp24_t a, int i); + +/** + * Computes a power of a 24-degree extension field element. + * 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(fp24_t c, fp24_t a, bn_t b); + +/** + * Copies the second argument to the first argument. + * + * @param[out] C - the result. + * @param[in] A - the 48-extension field element to copy. + */ +void fp48_copy(fp48_t c, fp48_t a); + +/** + * Assigns zero to a 48-extension field element. + * + * @param[out] A - the 48-extension field element to zero. + */ +void fp48_zero(fp48_t a); + +/** + * Tests if a 48-extension field element is zero or not. + * + * @param[in] A - the 48-extension field element to test. + * @return 1 if the argument is zero, 0 otherwise. + */ +int fp48_is_zero(fp48_t a); + +/** + * Assigns a random value to a 48-extension field element. + * + * @param[out] A - the 48-extension field element to assign. + */ +void fp48_rand(fp48_t a); + +/** + * Prints a 48-extension field element to standard output. + * + * @param[in] A - the 48-extension field element to print. + */ +void fp48_print(fp48_t a); + +/** + * Returns the number of bytes necessary to store a 48-extension field + * element. + * + * @param[in] a - the extension field element. + * @param[in] pack - the flag to indicate compression. + * @return the number of bytes. + */ +int fp48_size_bin(fp48_t a, int pack); + +/** + * Reads a 48-extension field element from a byte vector in big-endian + * format. + * + * @param[out] a - the result. + * @param[in] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @throw ERR_NO_BUFFER - if the buffer capacity is not correct. + */ +void fp48_read_bin(fp48_t a, const uint8_t *bin, int len); + +/** + * Writes a 48-extension field element to a byte vector in big-endian + * format. + * + * @param[out] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @param[in] a - the extension field element to write. + * @param[in] pack - the flag to indicate compression. + * @throw ERR_NO_BUFFER - if the buffer capacity is not correct. + */ +void fp48_write_bin(uint8_t *bin, int len, fp48_t a, int pack); + +/** + * Returns the result of a comparison between two 48-extension field + * elements. + * + * @param[in] a - the first 48-extension field element. + * @param[in] b - the second 48-extension field element. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fp48_cmp(fp48_t a, fp48_t b); + +/** + * Returns the result of a signed comparison between a 48-extension field + * element and a digit. + * + * @param[in] a - the 48-extension field element. + * @param[in] b - the digit. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fp48_cmp_dig(fp48_t a, dig_t b); + +/** + * Assigns a 48-extension field element to a digit. + * + * @param[in] a - the 48-extension field element. + * @param[in] b - the digit. + */ +void fp48_set_dig(fp48_t a, dig_t b); + +/** + * Adds two 48-extension field elements. Computes C = A + B. + * + * @param[out] C - the result. + * @param[in] A - the first 48-extension field element. + * @param[in] B - the second 48-extension field element. + */ +void fp48_add(fp48_t c, fp48_t a, fp48_t b); + +/** + * Subtracts a 48-extension field element from another. Computes + * C = A - B. + * + * @param[out] C - the result. + * @param[in] A - the first 48-extension field element. + * @param[in] B - the second 48-extension field element. + */ +void fp48_sub(fp48_t c, fp48_t a, fp48_t b); + +/** + * Negates a 48-extension field element. + * + * @param[out] C - the result. + * @param[out] A - the 48-extension field element to negate. + */ +void fp48_neg(fp48_t c, fp48_t a); + +/** + * Doubles a 48-extension field element. Computes c = 2 * a. + * + * @param[out] c - the result. + * @param[in] a - the 48-extension field element to double. + */ +void fp48_dbl(fp48_t c, fp48_t a); + +/** + * Multiples two 48-extension field elements without performing modular + * reduction. + * + * @param[out] c - the result. + * @param[in] a - the 48-extension field element. + * @param[in] b - the 48-extension field element. + */ +void fp48_mul_unr(dv48_t c, fp48_t a, fp48_t b); + +/** + * Multiples two 48-extension field elements using basic arithmetic. + * + * @param[out] c - the result. + * @param[in] a - the 48-extension field element. + * @param[in] b - the 48-extension field element. + */ +void fp48_mul_basic(fp48_t c, fp48_t a, fp48_t b); + +/** + * Multiples two 48-extension field elements using lazy reduction. + * + * @param[out] c - the result. + * @param[in] a - the 48-extension field element. + * @param[in] b - the 48-extension field element. + */ +void fp48_mul_lazyr(fp48_t c, fp48_t a, fp48_t b); + +/** + * Multiplies a 48-extension field element by the adjoined root. + * + * @param[out] c - the result. + * @param[in] a - the 48-extension field element to multiply. + */ +void fp48_mul_art(fp48_t c, fp48_t a); + +/** + * Multiples a dense 48-extension field element by a sparse element using + * basic arithmetic. Computes C = A * B. + * + * @param[out] c - the result. + * @param[in] a - the dense 48-extension field element. + * @param[in] b - the sparse 48-extension field element. + */ +void fp48_mul_dxs(fp48_t c, fp48_t a, fp48_t b); + +/** + * Computes the square of a 48-extension field element without performing + * modular reduction. + * + * @param[out] c - the result. + * @param[in] a - the 48-extension field element to square. + */ +void fp48_sqr_unr(dv48_t c, fp48_t a); + +/** + * Computes the square of a 48-extension field element using basic + * arithmetic. + * + * @param[out] c - the result. + * @param[in] a - the 48-extension field element to square. + */ +void fp48_sqr_basic(fp48_t c, fp48_t a); + +/** + * Computes the square of a 48-extension field element using lazy + * reduction. + * + * @param[out] c - the result. + * @param[in] a - the 48-extension field element to square. + */ +void fp48_sqr_lazyr(fp48_t c, fp48_t a); + +/** + * Computes the square of a cyclotomic 48-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 fp48_sqr_cyc_basic(fp48_t c, fp48_t a); + +/** + * Computes the square of a cyclotomic 48-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 fp48_sqr_cyc_lazyr(fp48_t c, fp48_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 fp48_sqr_pck_basic(fp48_t c, fp48_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 fp48_sqr_pck_lazyr(fp48_t c, fp48_t a); + +/** + * Tests if a 48-extension field element belongs to the cyclotomic + * subgroup. + * + * @param[in] a - the 48-extension field element to test. + * @return 1 if the extension field element is in the subgroup, 0 otherwise. + */ +int fp48_test_cyc(fp48_t a); + +/** + * Converts a 48-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 48-extension field element. + */ +void fp48_conv_cyc(fp48_t c, fp48_t a); + +/** + * Decompresses a compressed cyclotomic extension field element. + * + * @param[out] c - the result. + * @param[in] a - the 48-extension field element to decompress. + */ +void fp48_back_cyc(fp48_t c, fp48_t a); + +/** + * Decompresses multiple compressed cyclotomic extension field elements. + * + * @param[out] c - the result. + * @param[in] a - the 48 field elements to decompress. + * @param[in] n - the number of field elements to decompress. + */ +void fp48_back_cyc_sim(fp48_t *c, fp48_t *a, int n); + +/** + * Inverts a 48-extension field element. Computes c = 1/a. + * + * @param[out] c - the result. + * @param[in] a - the 48-extension field element to invert. + */ +void fp48_inv(fp48_t c, fp48_t a); + +/** + * Computes the inverse of a cyclotomic 48-extension field element. + * + * For unitary elements, this is equivalent to computing the conjugate. + * A unitary element is one previously raised to the (p^24 - 1)-th power. + * + * @param[out] c - the result. + * @param[in] a - the 48-extension field element to invert. + */ +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. + * + * @param[out] c - the result. + * @param[in] a - a 48-extension field element. + * @param[in] i - the power of the Frobenius map. + */ +void fp48_frb(fp48_t c, fp48_t a, int i); + +/** + * Computes a power of a 48-extension field element. + * 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 fp48_exp(fp48_t c, fp48_t a, bn_t b); + +/** + * Computes a power of a 48-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 fp48_exp_dig(fp48_t c, fp48_t a, dig_t b); + +/** + * Computes a power of a cyclotomic 48-extension field element. + * + * @param[out] c - the result. + * @param[in] a - the basis. + * @param[in] b - the exponent. + */ +void fp48_exp_cyc(fp48_t c, fp48_t a, bn_t b); + +/** + * Computes a power of a cyclotomic 48-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 fp48_exp_cyc_sps(fp48_t c, fp48_t a, const int *b, int l, int s); + +/** + * Compresses a 48-extension field element. + * + * @param[out] r - the result. + * @param[in] p - the 48-extension field element to compress. + */ +void fp48_pck(fp48_t c, fp48_t a); + +/** + * Decompresses a 48-extension field element. + * + * @param[out] r - the result. + * @param[in] p - the 48-extension field element to decompress. + * @return if the decompression was successful + */ +int fp48_upk(fp48_t c, fp48_t a); + +/** + * Copies the second argument to the first argument. + * + * @param[out] C - the result. + * @param[in] A - the 54-extension field element to copy. + */ +void fp54_copy(fp54_t c, fp54_t a); + +/** + * Assigns zero to a 54-extension field element. + * + * @param[out] A - the 54-extension field element to zero. + */ +void fp54_zero(fp54_t a); + +/** + * Tests if a 54-extension field element is zero or not. + * + * @param[in] A - the 54-extension field element to test. + * @return 1 if the argument is zero, 0 otherwise. + */ +int fp54_is_zero(fp54_t a); + +/** + * Assigns a random value to a 54-extension field element. + * + * @param[out] A - the 54-extension field element to assign. + */ +void fp54_rand(fp54_t a); + +/** + * Prints a 54-extension field element to standard output. + * + * @param[in] A - the 54-extension field element to print. + */ +void fp54_print(fp54_t a); + +/** + * Returns the number of bytes necessary to store a 54-extension field + * element. + * + * @param[in] a - the extension field element. + * @param[in] pack - the flag to indicate compression. + * @return the number of bytes. + */ +int fp54_size_bin(fp54_t a, int pack); + +/** + * Reads a 54-extension field element from a byte vector in big-endian + * format. + * + * @param[out] a - the result. + * @param[in] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @throw ERR_NO_BUFFER - if the buffer capacity is not correct. + */ +void fp54_read_bin(fp54_t a, const uint8_t *bin, int len); + +/** + * Writes a 54-extension field element to a byte vector in big-endian + * format. + * + * @param[out] bin - the byte vector. + * @param[in] len - the buffer capacity. + * @param[in] a - the extension field element to write. + * @param[in] pack - the flag to indicate compression. + * @throw ERR_NO_BUFFER - if the buffer capacity is not correct. + */ +void fp54_write_bin(uint8_t *bin, int len, fp54_t a, int pack); + +/** + * Returns the result of a comparison between two 54-extension field + * elements. + * + * @param[in] a - the first 54-extension field element. + * @param[in] b - the second 54-extension field element. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fp54_cmp(fp54_t a, fp54_t b); + +/** + * Returns the result of a signed comparison between a 54-extension field + * element and a digit. + * + * @param[in] a - the 54-extension field element. + * @param[in] b - the digit. + * @return RLC_EQ if a == b, and RLC_NE otherwise. + */ +int fp54_cmp_dig(fp54_t a, dig_t b); + +/** + * Assigns a 54-extension field element to a digit. + * + * @param[in] a - the 54-extension field element. + * @param[in] b - the digit. + */ +void fp54_set_dig(fp54_t a, dig_t b); + +/** + * Adds two 54-extension field elements. Computes C = A + B. + * + * @param[out] C - the result. + * @param[in] A - the first 54-extension field element. + * @param[in] B - the second 54-extension field element. + */ +void fp54_add(fp54_t c, fp54_t a, fp54_t b); + +/** + * Subtracts a 54-extension field element from another. Computes + * C = A - B. + * + * @param[out] C - the result. + * @param[in] A - the first 54-extension field element. + * @param[in] B - the second 54-extension field element. + */ +void fp54_sub(fp54_t c, fp54_t a, fp54_t b); + +/** + * Negates a 54-extension field element. + * + * @param[out] C - the result. + * @param[out] A - the 54-extension field element to negate. + */ +void fp54_neg(fp54_t c, fp54_t a); + +/** + * Doubles a 54-extension field element. Computes c = 2 * a. + * + * @param[out] c - the result. + * @param[in] a - the 54-extension field element to double. + */ +void fp54_dbl(fp54_t c, fp54_t a); + +/** + * Multiples two 54-extension field elements without performing modular + * reduction. + * + * @param[out] c - the result. + * @param[in] a - the 54-extension field element. + * @param[in] b - the 54-extension field element. + */ +void fp54_mul_unr(dv54_t c, fp54_t a, fp54_t b); + +/** + * Multiples two 54-extension field elements using basic arithmetic. + * + * @param[out] c - the result. + * @param[in] a - the 54-extension field element. + * @param[in] b - the 54-extension field element. + */ +void fp54_mul_basic(fp54_t c, fp54_t a, fp54_t b); + +/** + * Multiples two 54-extension field elements using lazy reduction. + * + * @param[out] c - the result. + * @param[in] a - the 54-extension field element. + * @param[in] b - the 54-extension field element. + */ +void fp54_mul_lazyr(fp54_t c, fp54_t a, fp54_t b); + +/** + * Multiplies a 54-extension field element by the adjoined root. + * + * @param[out] c - the result. + * @param[in] a - the 54-extension field element to multiply. + */ +void fp54_mul_art(fp54_t c, fp54_t a); + +/** + * Multiples a dense 54-extension field element by a sparse element using + * basic arithmetic. Computes C = A * B. + * + * @param[out] c - the result. + * @param[in] a - the dense 54-extension field element. + * @param[in] b - the sparse 54-extension field element. + */ +void fp54_mul_dxs(fp54_t c, fp54_t a, fp54_t b); + +/** + * Computes the square of a 54-extension field element without performing + * modular reduction. + * + * @param[out] c - the result. + * @param[in] a - the 54-extension field element to square. + */ +void fp54_sqr_unr(dv54_t c, fp54_t a); + +/** + * Computes the square of a 54-extension field element using basic + * arithmetic. + * + * @param[out] c - the result. + * @param[in] a - the 54-extension field element to square. + */ +void fp54_sqr_basic(fp54_t c, fp54_t a); + +/** + * Computes the square of a 54-extension field element using lazy + * reduction. + * + * @param[out] c - the result. + * @param[in] a - the 54-extension field element to square. + */ +void fp54_sqr_lazyr(fp54_t c, fp54_t a); + +/** + * Computes the square of a cyclotomic 54-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 fp54_sqr_cyc_basic(fp54_t c, fp54_t a); + +/** + * Computes the square of a cyclotomic 54-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 fp54_sqr_cyc_lazyr(fp54_t c, fp54_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 fp54_sqr_pck_basic(fp54_t c, fp54_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 fp54_sqr_pck_lazyr(fp54_t c, fp54_t a); + +/** + * Tests if a 54-extension field element belongs to the cyclotomic + * subgroup. + * + * @param[in] a - the 54-extension field element to test. + * @return 1 if the extension field element is in the subgroup, 0 otherwise. + */ +int fp54_test_cyc(fp54_t a); + +/** + * Converts a 54-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 54-extension field element. + */ +void fp54_conv_cyc(fp54_t c, fp54_t a); + +/** + * Decompresses a compressed cyclotomic extension field element. + * + * @param[out] c - the result. + * @param[in] a - the 54-extension field element to decompress. + */ +void fp54_back_cyc(fp54_t c, fp54_t a); + +/** + * Decompresses multiple compressed cyclotomic extension field elements. + * + * @param[out] c - the result. + * @param[in] a - the 54 field elements to decompress. + * @param[in] n - the number of field elements to decompress. + */ +void fp54_back_cyc_sim(fp54_t *c, fp54_t *a, int n); + +/** + * Inverts a 54-extension field element. Computes c = 1/a. + * + * @param[out] c - the result. + * @param[in] a - the 54-extension field element to invert. + */ +void fp54_inv(fp54_t c, fp54_t a); + +/** + * Computes the inverse of a cyclotomic 54-extension field element. + * + * For unitary elements, this is equivalent to computing the conjugate. + * A unitary element is one previously raised to the (p^24 - 1)-th power. + * + * @param[out] c - the result. + * @param[in] a - the 54-extension field element to invert. + */ +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. + * + * @param[out] c - the result. + * @param[in] a - a 54-extension field element. + * @param[in] i - the power of the Frobenius map. + */ +void fp54_frb(fp54_t c, fp54_t a, int i); + +/** + * Computes a power of a 54-extension field element. + * 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 fp54_exp(fp54_t c, fp54_t a, bn_t b); + +/** + * Computes a power of a 54-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 fp54_exp_dig(fp54_t c, fp54_t a, dig_t b); + +/** + * Computes a power of a cyclotomic 54-extension field element. + * + * @param[out] c - the result. + * @param[in] a - the basis. + * @param[in] b - the exponent. + */ +void fp54_exp_cyc(fp54_t c, fp54_t a, bn_t b); + +/** + * Computes a power of a cyclotomic 54-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 fp54_exp_cyc_sps(fp54_t c, fp54_t a, const int *b, int l, int s); + +/** + * Compresses a 54-extension field element. + * + * @param[out] r - the result. + * @param[in] p - the 54-extension field element to compress. + */ +void fp54_pck(fp54_t c, fp54_t a); + +/** + * Decompresses a 54-extension field element. + * + * @param[out] r - the result. + * @param[in] p - the 54-extension field element to decompress. + * @return if the decompression was successful + */ +int fp54_upk(fp54_t c, fp54_t a); + +#endif /* !RLC_FPX_H */ diff --git a/bls/contrib/relic/include/relic_label.h b/bls/contrib/relic/include/relic_label.h new file mode 100644 index 00000000..959a3b3d --- /dev/null +++ b/bls/contrib/relic/include/relic_label.h @@ -0,0 +1,2667 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 + * + * Symbol renaming to a#undef clashes when simultaneous linking multiple builds. + * + * @ingroup core + */ + +#ifndef RLC_LABEL_H +#define RLC_LABEL_H + +#include "relic_conf.h" + +#define PREFIX(F) _PREFIX(LABEL, F) +#define _PREFIX(A, B) __PREFIX(A, B) +#define __PREFIX(A, B) A ## _ ## B + +/*============================================================================*/ +/* Macro definitions */ +/*============================================================================*/ + +#ifdef LABEL + +#undef first_ctx +#define first_ctx PREFIX(first_ctx) +#undef core_ctx +#define core_ctx PREFIX(core_ctx) + +#undef core_init +#undef core_clean +#undef core_get +#undef core_set + +#define core_init PREFIX(core_init) +#define core_clean PREFIX(core_clean) +#define core_get PREFIX(core_get) +#define core_set PREFIX(core_set) + +#undef arch_init +#undef arch_clean +#undef arch_cycles +#undef arch_copy_rom + +#define arch_init PREFIX(arch_init) +#define arch_clean PREFIX(arch_clean) +#define arch_cycles PREFIX(arch_cycles) +#define arch_copy_rom PREFIX(arch_copy_rom) + +#undef bench_overhead +#undef bench_reset +#undef bench_before +#undef bench_after +#undef bench_compute +#undef bench_print +#undef bench_total + +#define bench_overhead PREFIX(bench_overhead) +#define bench_reset PREFIX(bench_reset) +#define bench_before PREFIX(bench_before) +#define bench_after PREFIX(bench_after) +#define bench_compute PREFIX(bench_compute) +#define bench_print PREFIX(bench_print) +#define bench_total PREFIX(bench_total) + +#undef err_simple_msg +#undef err_full_msg +#undef err_get_msg +#undef err_get_code + +#define err_simple_msg PREFIX(err_simple_msg) +#define err_full_msg PREFIX(err_full_msg) +#define err_get_msg PREFIX(err_get_msg) +#define err_get_code PREFIX(err_get_code) + +#undef rand_init +#undef rand_clean +#undef rand_seed +#undef rand_seed +#undef rand_bytes + +#define rand_init PREFIX(rand_init) +#define rand_clean PREFIX(rand_clean) +#define rand_seed PREFIX(rand_seed) +#define rand_seed PREFIX(rand_seed) +#define rand_bytes PREFIX(rand_bytes) + +#undef test_fail +#undef test_pass + +#define test_fail PREFIX(test_fail) +#define test_pass PREFIX(test_pass) + +#undef util_conv_endian +#undef util_conv_big +#undef util_conv_little +#undef util_conv_char +#undef util_bits_dig +#undef util_cmp_const +#undef util_printf +#undef util_print_dig + +#define util_conv_endian PREFIX(util_conv_endian) +#define util_conv_big PREFIX(util_conv_big) +#define util_conv_little PREFIX(util_conv_little) +#define util_conv_char PREFIX(util_conv_char) +#define util_bits_dig PREFIX(util_bits_dig) +#define util_cmp_const PREFIX(util_cmp_const) +#define util_printf PREFIX(util_printf) +#define util_print_dig PREFIX(util_print_dig) + +#undef conf_print +#define conf_print PREFIX(conf_print) + +#undef dv_t +#define dv_t PREFIX(dv_t) + +#undef dv_print +#undef dv_zero +#undef dv_copy +#undef dv_copy_cond +#undef dv_swap_cond +#undef dv_cmp +#undef dv_cmp_const +#undef dv_new_dynam +#undef dv_free_dynam + +#define dv_print PREFIX(dv_print) +#define dv_zero PREFIX(dv_zero) +#define dv_copy PREFIX(dv_copy) +#define dv_copy_cond PREFIX(dv_copy_cond) +#define dv_swap_cond PREFIX(dv_swap_cond) +#define dv_cmp PREFIX(dv_cmp) +#define dv_cmp_const PREFIX(dv_cmp_const) +#define dv_new_dynam PREFIX(dv_new_dynam) +#define dv_free_dynam PREFIX(dv_free_dynam) + + + +#undef bn_st +#undef bn_t +#define bn_st PREFIX(bn_st) +#define bn_t PREFIX(bn_t) + +#undef bn_init +#undef bn_clean +#undef bn_grow +#undef bn_trim +#undef bn_copy +#undef bn_abs +#undef bn_neg +#undef bn_sign +#undef bn_zero +#undef bn_is_zero +#undef bn_is_even +#undef bn_bits +#undef bn_get_bit +#undef bn_set_bit +#undef bn_ham +#undef bn_get_dig +#undef bn_set_dig +#undef bn_set_2b +#undef bn_rand +#undef bn_rand_mod +#undef bn_print +#undef bn_size_str +#undef bn_read_str +#undef bn_write_str +#undef bn_size_bin +#undef bn_read_bin +#undef bn_write_bin +#undef bn_size_raw +#undef bn_read_raw +#undef bn_write_raw +#undef bn_cmp_abs +#undef bn_cmp_dig +#undef bn_cmp +#undef bn_add +#undef bn_add_dig +#undef bn_sub +#undef bn_sub_dig +#undef bn_mul_dig +#undef bn_mul_basic +#undef bn_mul_comba +#undef bn_mul_karat +#undef bn_sqr_basic +#undef bn_sqr_comba +#undef bn_sqr_karat +#undef bn_dbl +#undef bn_hlv +#undef bn_lsh +#undef bn_rsh +#undef bn_div +#undef bn_div_rem +#undef bn_div_dig +#undef bn_div_rem_dig +#undef bn_mod_2b +#undef bn_mod_dig +#undef bn_mod_basic +#undef bn_mod_pre_barrt +#undef bn_mod_barrt +#undef bn_mod_pre_monty +#undef bn_mod_monty_conv +#undef bn_mod_monty_back +#undef bn_mod_monty_basic +#undef bn_mod_monty_comba +#undef bn_mod_pre_pmers +#undef bn_mod_pmers +#undef bn_mxp_basic +#undef bn_mxp_slide +#undef bn_mxp_monty +#undef bn_mxp_dig +#undef bn_srt +#undef bn_gcd_basic +#undef bn_gcd_lehme +#undef bn_gcd_stein +#undef bn_gcd_dig +#undef bn_gcd_ext_basic +#undef bn_gcd_ext_lehme +#undef bn_gcd_ext_stein +#undef bn_gcd_ext_mid +#undef bn_gcd_ext_dig +#undef bn_lcm +#undef bn_smb_leg +#undef bn_smb_jac +#undef bn_get_prime +#undef bn_is_prime +#undef bn_is_prime_basic +#undef bn_is_prime_rabin +#undef bn_is_prime_solov +#undef bn_gen_prime_basic +#undef bn_gen_prime_safep +#undef bn_gen_prime_stron +#undef bn_factor +#undef bn_is_factor +#undef bn_rec_win +#undef bn_rec_slw +#undef bn_rec_naf +#undef bn_rec_tnaf +#undef bn_rec_rtnaf +#undef bn_rec_tnaf_get +#undef bn_rec_tnaf_mod +#undef bn_rec_reg +#undef bn_rec_jsf +#undef bn_rec_glv + +#define bn_init PREFIX(bn_init) +#define bn_clean PREFIX(bn_clean) +#define bn_grow PREFIX(bn_grow) +#define bn_trim PREFIX(bn_trim) +#define bn_copy PREFIX(bn_copy) +#define bn_abs PREFIX(bn_abs) +#define bn_neg PREFIX(bn_neg) +#define bn_sign PREFIX(bn_sign) +#define bn_zero PREFIX(bn_zero) +#define bn_is_zero PREFIX(bn_is_zero) +#define bn_is_even PREFIX(bn_is_even) +#define bn_bits PREFIX(bn_bits) +#define bn_get_bit PREFIX(bn_get_bit) +#define bn_set_bit PREFIX(bn_set_bit) +#define bn_ham PREFIX(bn_ham) +#define bn_get_dig PREFIX(bn_get_dig) +#define bn_set_dig PREFIX(bn_set_dig) +#define bn_set_2b PREFIX(bn_set_2b) +#define bn_rand PREFIX(bn_rand) +#define bn_rand_mod PREFIX(bn_rand_mod) +#define bn_print PREFIX(bn_print) +#define bn_size_str PREFIX(bn_size_str) +#define bn_read_str PREFIX(bn_read_str) +#define bn_write_str PREFIX(bn_write_str) +#define bn_size_bin PREFIX(bn_size_bin) +#define bn_read_bin PREFIX(bn_read_bin) +#define bn_write_bin PREFIX(bn_write_bin) +#define bn_size_raw PREFIX(bn_size_raw) +#define bn_read_raw PREFIX(bn_read_raw) +#define bn_write_raw PREFIX(bn_write_raw) +#define bn_cmp_abs PREFIX(bn_cmp_abs) +#define bn_cmp_dig PREFIX(bn_cmp_dig) +#define bn_cmp PREFIX(bn_cmp) +#define bn_add PREFIX(bn_add) +#define bn_add_dig PREFIX(bn_add_dig) +#define bn_sub PREFIX(bn_sub) +#define bn_sub_dig PREFIX(bn_sub_dig) +#define bn_mul_dig PREFIX(bn_mul_dig) +#define bn_mul_basic PREFIX(bn_mul_basic) +#define bn_mul_comba PREFIX(bn_mul_comba) +#define bn_mul_karat PREFIX(bn_mul_karat) +#define bn_sqr_basic PREFIX(bn_sqr_basic) +#define bn_sqr_comba PREFIX(bn_sqr_comba) +#define bn_sqr_karat PREFIX(bn_sqr_karat) +#define bn_dbl PREFIX(bn_dbl) +#define bn_hlv PREFIX(bn_hlv) +#define bn_lsh PREFIX(bn_lsh) +#define bn_rsh PREFIX(bn_rsh) +#define bn_div PREFIX(bn_div) +#define bn_div_rem PREFIX(bn_div_rem) +#define bn_div_dig PREFIX(bn_div_dig) +#define bn_div_rem_dig PREFIX(bn_div_rem_dig) +#define bn_mod_2b PREFIX(bn_mod_2b) +#define bn_mod_dig PREFIX(bn_mod_dig) +#define bn_mod_basic PREFIX(bn_mod_basic) +#define bn_mod_pre_barrt PREFIX(bn_mod_pre_barrt) +#define bn_mod_barrt PREFIX(bn_mod_barrt) +#define bn_mod_pre_monty PREFIX(bn_mod_pre_monty) +#define bn_mod_monty_conv PREFIX(bn_mod_monty_conv) +#define bn_mod_monty_back PREFIX(bn_mod_monty_back) +#define bn_mod_monty_basic PREFIX(bn_mod_monty_basic) +#define bn_mod_monty_comba PREFIX(bn_mod_monty_comba) +#define bn_mod_pre_pmers PREFIX(bn_mod_pre_pmers) +#define bn_mod_pmers PREFIX(bn_mod_pmers) +#define bn_mxp_basic PREFIX(bn_mxp_basic) +#define bn_mxp_slide PREFIX(bn_mxp_slide) +#define bn_mxp_monty PREFIX(bn_mxp_monty) +#define bn_mxp_dig PREFIX(bn_mxp_dig) +#define bn_srt PREFIX(bn_srt) +#define bn_gcd_basic PREFIX(bn_gcd_basic) +#define bn_gcd_lehme PREFIX(bn_gcd_lehme) +#define bn_gcd_stein PREFIX(bn_gcd_stein) +#define bn_gcd_dig PREFIX(bn_gcd_dig) +#define bn_gcd_ext_basic PREFIX(bn_gcd_ext_basic) +#define bn_gcd_ext_lehme PREFIX(bn_gcd_ext_lehme) +#define bn_gcd_ext_stein PREFIX(bn_gcd_ext_stein) +#define bn_gcd_ext_mid PREFIX(bn_gcd_ext_mid) +#define bn_gcd_ext_dig PREFIX(bn_gcd_ext_dig) +#define bn_lcm PREFIX(bn_lcm) +#define bn_smb_leg PREFIX(bn_smb_leg) +#define bn_smb_jac PREFIX(bn_smb_jac) +#define bn_get_prime PREFIX(bn_get_prime) +#define bn_is_prime PREFIX(bn_is_prime) +#define bn_is_prime_basic PREFIX(bn_is_prime_basic) +#define bn_is_prime_rabin PREFIX(bn_is_prime_rabin) +#define bn_is_prime_solov PREFIX(bn_is_prime_solov) +#define bn_gen_prime_basic PREFIX(bn_gen_prime_basic) +#define bn_gen_prime_safep PREFIX(bn_gen_prime_safep) +#define bn_gen_prime_stron PREFIX(bn_gen_prime_stron) +#define bn_factor PREFIX(bn_factor) +#define bn_is_factor PREFIX(bn_is_factor) +#define bn_rec_win PREFIX(bn_rec_win) +#define bn_rec_slw PREFIX(bn_rec_slw) +#define bn_rec_naf PREFIX(bn_rec_naf) +#define bn_rec_tnaf PREFIX(bn_rec_tnaf) +#define bn_rec_rtnaf PREFIX(bn_rec_rtnaf) +#define bn_rec_tnaf_get PREFIX(bn_rec_tnaf_get) +#define bn_rec_tnaf_mod PREFIX(bn_rec_tnaf_mod) +#define bn_rec_reg PREFIX(bn_rec_reg) +#define bn_rec_jsf PREFIX(bn_rec_jsf) +#define bn_rec_glv PREFIX(bn_rec_glv) + +#undef bn_add1_low +#undef bn_addn_low +#undef bn_sub1_low +#undef bn_subn_low +#undef bn_cmp1_low +#undef bn_cmpn_low +#undef bn_lsh1_low +#undef bn_lshb_low +#undef bn_lshd_low +#undef bn_rsh1_low +#undef bn_rshb_low +#undef bn_rshd_low +#undef bn_mula_low +#undef bn_mul1_low +#undef bn_muln_low +#undef bn_muld_low +#undef bn_sqra_low +#undef bn_sqrn_low +#undef bn_divn_low +#undef bn_div1_low +#undef bn_modn_low + +#define bn_add1_low PREFIX(bn_add1_low) +#define bn_addn_low PREFIX(bn_addn_low) +#define bn_sub1_low PREFIX(bn_sub1_low) +#define bn_subn_low PREFIX(bn_subn_low) +#define bn_cmp1_low PREFIX(bn_cmp1_low) +#define bn_cmpn_low PREFIX(bn_cmpn_low) +#define bn_lsh1_low PREFIX(bn_lsh1_low) +#define bn_lshb_low PREFIX(bn_lshb_low) +#define bn_lshd_low PREFIX(bn_lshd_low) +#define bn_rsh1_low PREFIX(bn_rsh1_low) +#define bn_rshb_low PREFIX(bn_rshb_low) +#define bn_rshd_low PREFIX(bn_rshd_low) +#define bn_mula_low PREFIX(bn_mula_low) +#define bn_mul1_low PREFIX(bn_mul1_low) +#define bn_muln_low PREFIX(bn_muln_low) +#define bn_muld_low PREFIX(bn_muld_low) +#define bn_sqra_low PREFIX(bn_sqra_low) +#define bn_sqrn_low PREFIX(bn_sqrn_low) +#define bn_divn_low PREFIX(bn_divn_low) +#define bn_div1_low PREFIX(bn_div1_low) +#define bn_modn_low PREFIX(bn_modn_low) + +#undef fp_st +#undef fp_t +#define fp_st PREFIX(fp_st) +#define fp_t PREFIX(fp_t) + +#undef fp_prime_init +#undef fp_prime_clean +#undef fp_prime_get +#undef fp_prime_get_rdc +#undef fp_prime_get_conv +#undef fp_prime_get_mod8 +#undef fp_prime_get_sps +#undef fp_prime_get_qnr +#undef fp_prime_get_cnr +#undef fp_prime_get_2ad +#undef fp_param_get +#undef fp_prime_set_dense +#undef fp_prime_set_pmers +#undef fp_prime_set_pairf +#undef fp_prime_calc +#undef fp_prime_conv +#undef fp_prime_conv_dig +#undef fp_prime_back +#undef fp_param_set +#undef fp_param_set_any +#undef fp_param_set_any_dense +#undef fp_param_set_any_pmers +#undef fp_param_set_any_tower +#undef fp_param_print +#undef fp_prime_get_par +#undef fp_prime_get_par_sps +#undef fp_param_get_sps +#undef fp_copy +#undef fp_zero +#undef fp_is_zero +#undef fp_is_even +#undef fp_get_bit +#undef fp_set_bit +#undef fp_set_dig +#undef fp_bits +#undef fp_rand +#undef fp_print +#undef fp_size_str +#undef fp_read_str +#undef fp_write_str +#undef fp_read_bin +#undef fp_write_bin +#undef fp_cmp +#undef fp_cmp_dig +#undef fp_add_basic +#undef fp_add_integ +#undef fp_add_dig +#undef fp_sub_basic +#undef fp_sub_integ +#undef fp_sub_dig +#undef fp_neg_basic +#undef fp_neg_integ +#undef fp_dbl_basic +#undef fp_dbl_integ +#undef fp_hlv_basic +#undef fp_hlv_integ +#undef fp_mul_basic +#undef fp_mul_comba +#undef fp_mul_integ +#undef fp_mul_karat +#undef fp_mul_dig +#undef fp_sqr_basic +#undef fp_sqr_comba +#undef fp_sqr_integ +#undef fp_sqr_karat +#undef fp_lsh +#undef fp_rsh +#undef fp_rdc_basic +#undef fp_rdc_monty_basic +#undef fp_rdc_monty_comba +#undef fp_rdc_quick +#undef fp_inv_basic +#undef fp_inv_binar +#undef fp_inv_monty +#undef fp_inv_exgcd +#undef fp_inv_divst +#undef fp_inv_lower +#undef fp_inv_sim +#undef fp_exp_basic +#undef fp_exp_slide +#undef fp_exp_monty +#undef fp_srt + +#define fp_prime_init PREFIX(fp_prime_init) +#define fp_prime_clean PREFIX(fp_prime_clean) +#define fp_prime_get PREFIX(fp_prime_get) +#define fp_prime_get_rdc PREFIX(fp_prime_get_rdc) +#define fp_prime_get_conv PREFIX(fp_prime_get_conv) +#define fp_prime_get_mod8 PREFIX(fp_prime_get_mod8) +#define fp_prime_get_sps PREFIX(fp_prime_get_sps) +#define fp_prime_get_qnr PREFIX(fp_prime_get_qnr) +#define fp_prime_get_cnr PREFIX(fp_prime_get_cnr) +#define fp_prime_get_2ad PREFIX(fp_prime_get_2ad) +#define fp_param_get PREFIX(fp_param_get) +#define fp_prime_set_dense PREFIX(fp_prime_set_dense) +#define fp_prime_set_pmers PREFIX(fp_prime_set_pmers) +#define fp_prime_set_pairf PREFIX(fp_prime_set_pairf) +#define fp_prime_calc PREFIX(fp_prime_calc) +#define fp_prime_conv PREFIX(fp_prime_conv) +#define fp_prime_conv_dig PREFIX(fp_prime_conv_dig) +#define fp_prime_back PREFIX(fp_prime_back) +#define fp_param_set PREFIX(fp_param_set) +#define fp_param_set_any PREFIX(fp_param_set_any) +#define fp_param_set_any_dense PREFIX(fp_param_set_any_dense) +#define fp_param_set_any_pmers PREFIX(fp_param_set_any_pmers) +#define fp_param_set_any_tower PREFIX(fp_param_set_any_tower) +#define fp_param_print PREFIX(fp_param_print) +#define fp_prime_get_par PREFIX(fp_prime_get_par) +#define fp_prime_get_par_sps PREFIX(fp_prime_get_par_sps) +#define fp_param_get_sps PREFIX(fp_param_get_sps) +#define fp_copy PREFIX(fp_copy) +#define fp_zero PREFIX(fp_zero) +#define fp_is_zero PREFIX(fp_is_zero) +#define fp_is_even PREFIX(fp_is_even) +#define fp_get_bit PREFIX(fp_get_bit) +#define fp_set_bit PREFIX(fp_set_bit) +#define fp_set_dig PREFIX(fp_set_dig) +#define fp_bits PREFIX(fp_bits) +#define fp_rand PREFIX(fp_rand) +#define fp_print PREFIX(fp_print) +#define fp_size_str PREFIX(fp_size_str) +#define fp_read_str PREFIX(fp_read_str) +#define fp_write_str PREFIX(fp_write_str) +#define fp_read_bin PREFIX(fp_read_bin) +#define fp_write_bin PREFIX(fp_write_bin) +#define fp_cmp PREFIX(fp_cmp) +#define fp_cmp_dig PREFIX(fp_cmp_dig) +#define fp_add_basic PREFIX(fp_add_basic) +#define fp_add_integ PREFIX(fp_add_integ) +#define fp_add_dig PREFIX(fp_add_dig) +#define fp_sub_basic PREFIX(fp_sub_basic) +#define fp_sub_integ PREFIX(fp_sub_integ) +#define fp_sub_dig PREFIX(fp_sub_dig) +#define fp_neg_basic PREFIX(fp_neg_basic) +#define fp_neg_integ PREFIX(fp_neg_integ) +#define fp_dbl_basic PREFIX(fp_dbl_basic) +#define fp_dbl_integ PREFIX(fp_dbl_integ) +#define fp_hlv_basic PREFIX(fp_hlv_basic) +#define fp_hlv_integ PREFIX(fp_hlv_integ) +#define fp_mul_basic PREFIX(fp_mul_basic) +#define fp_mul_comba PREFIX(fp_mul_comba) +#define fp_mul_integ PREFIX(fp_mul_integ) +#define fp_mul_karat PREFIX(fp_mul_karat) +#define fp_mul_dig PREFIX(fp_mul_dig) +#define fp_sqr_basic PREFIX(fp_sqr_basic) +#define fp_sqr_comba PREFIX(fp_sqr_comba) +#define fp_sqr_integ PREFIX(fp_sqr_integ) +#define fp_sqr_karat PREFIX(fp_sqr_karat) +#define fp_lsh PREFIX(fp_lsh) +#define fp_rsh PREFIX(fp_rsh) +#define fp_rdc_basic PREFIX(fp_rdc_basic) +#define fp_rdc_monty_basic PREFIX(fp_rdc_monty_basic) +#define fp_rdc_monty_comba PREFIX(fp_rdc_monty_comba) +#define fp_rdc_quick PREFIX(fp_rdc_quick) +#define fp_inv_basic PREFIX(fp_inv_basic) +#define fp_inv_binar PREFIX(fp_inv_binar) +#define fp_inv_monty PREFIX(fp_inv_monty) +#define fp_inv_exgcd PREFIX(fp_inv_exgcd) +#define fp_inv_divst PREFIX(fp_inv_divst) +#define fp_inv_lower PREFIX(fp_inv_lower) +#define fp_inv_sim PREFIX(fp_inv_sim) +#define fp_exp_basic PREFIX(fp_exp_basic) +#define fp_exp_slide PREFIX(fp_exp_slide) +#define fp_exp_monty PREFIX(fp_exp_monty) +#define fp_srt PREFIX(fp_srt) + +#undef fp_add1_low +#undef fp_addn_low +#undef fp_addm_low +#undef fp_addd_low +#undef fp_addc_low +#undef fp_sub1_low +#undef fp_subn_low +#undef fp_subm_low +#undef fp_subd_low +#undef fp_subc_low +#undef fp_negm_low +#undef fp_dbln_low +#undef fp_dblm_low +#undef fp_hlvm_low +#undef fp_hlvd_low +#undef fp_lsh1_low +#undef fp_lshb_low +#undef fp_lshd_low +#undef fp_rsh1_low +#undef fp_rshb_low +#undef fp_rshd_low +#undef fp_mula_low +#undef fp_mul1_low +#undef fp_muln_low +#undef fp_mulm_low +#undef fp_sqrn_low +#undef fp_sqrm_low +#undef fp_rdcs_low +#undef fp_rdcn_low +#undef fp_invm_low + +#define fp_add1_low PREFIX(fp_add1_low) +#define fp_addn_low PREFIX(fp_addn_low) +#define fp_addm_low PREFIX(fp_addm_low) +#define fp_addd_low PREFIX(fp_addd_low) +#define fp_addc_low PREFIX(fp_addc_low) +#define fp_sub1_low PREFIX(fp_sub1_low) +#define fp_subn_low PREFIX(fp_subn_low) +#define fp_subm_low PREFIX(fp_subm_low) +#define fp_subd_low PREFIX(fp_subd_low) +#define fp_subc_low PREFIX(fp_subc_low) +#define fp_negm_low PREFIX(fp_negm_low) +#define fp_dbln_low PREFIX(fp_dbln_low) +#define fp_dblm_low PREFIX(fp_dblm_low) +#define fp_hlvm_low PREFIX(fp_hlvm_low) +#define fp_hlvd_low PREFIX(fp_hlvd_low) +#define fp_lsh1_low PREFIX(fp_lsh1_low) +#define fp_lshb_low PREFIX(fp_lshb_low) +#define fp_lshd_low PREFIX(fp_lshd_low) +#define fp_rsh1_low PREFIX(fp_rsh1_low) +#define fp_rshb_low PREFIX(fp_rshb_low) +#define fp_rshd_low PREFIX(fp_rshd_low) +#define fp_mula_low PREFIX(fp_mula_low) +#define fp_mul1_low PREFIX(fp_mul1_low) +#define fp_muln_low PREFIX(fp_muln_low) +#define fp_mulm_low PREFIX(fp_mulm_low) +#define fp_sqrn_low PREFIX(fp_sqrn_low) +#define fp_sqrm_low PREFIX(fp_sqrm_low) +#define fp_rdcs_low PREFIX(fp_rdcs_low) +#define fp_rdcn_low PREFIX(fp_rdcn_low) +#define fp_invm_low PREFIX(fp_invm_low) + +#undef fp_st +#undef fp_t +#define fp_st PREFIX(fp_st) +#define fp_t PREFIX(fp_t) + +#undef fb_poly_init +#undef fb_poly_clean +#undef fb_poly_get +#undef fb_poly_set_dense +#undef fb_poly_set_trino +#undef fb_poly_set_penta +#undef fb_poly_get_srz +#undef fb_poly_tab_srz +#undef fb_poly_tab_sqr +#undef fb_poly_get_chain +#undef fb_poly_get_rdc +#undef fb_poly_get_trc +#undef fb_poly_get_slv +#undef fb_param_set +#undef fb_param_set_any +#undef fb_param_print +#undef fb_poly_add +#undef fb_copy +#undef fb_neg +#undef fb_zero +#undef fb_is_zero +#undef fb_get_bit +#undef fb_set_bit +#undef fb_set_dig +#undef fb_bits +#undef fb_rand +#undef fb_print +#undef fb_size_str +#undef fb_read_str +#undef fb_write_str +#undef fb_read_bin +#undef fb_write_bin +#undef fb_cmp +#undef fb_cmp_dig +#undef fb_add +#undef fb_add_dig +#undef fb_mul_basic +#undef fb_mul_integ +#undef fb_mul_lodah +#undef fb_mul_dig +#undef fb_mul_karat +#undef fb_sqr_basic +#undef fb_sqr_integ +#undef fb_sqr_quick +#undef fb_lsh +#undef fb_rsh +#undef fb_rdc_basic +#undef fb_rdc_quick +#undef fb_srt_basic +#undef fb_srt_quick +#undef fb_trc_basic +#undef fb_trc_quick +#undef fb_inv_basic +#undef fb_inv_binar +#undef fb_inv_exgcd +#undef fb_inv_almos +#undef fb_inv_itoht +#undef fb_inv_bruch +#undef fb_inv_ctaia +#undef fb_inv_lower +#undef fb_inv_sim +#undef fb_exp_2b +#undef fb_exp_basic +#undef fb_exp_slide +#undef fb_exp_monty +#undef fb_slv_basic +#undef fb_slv_quick +#undef fb_itr_basic +#undef fb_itr_pre_quick +#undef fb_itr_quick + +#define fb_poly_init PREFIX(fb_poly_init) +#define fb_poly_clean PREFIX(fb_poly_clean) +#define fb_poly_get PREFIX(fb_poly_get) +#define fb_poly_set_dense PREFIX(fb_poly_set_dense) +#define fb_poly_set_trino PREFIX(fb_poly_set_trino) +#define fb_poly_set_penta PREFIX(fb_poly_set_penta) +#define fb_poly_get_srz PREFIX(fb_poly_get_srz) +#define fb_poly_tab_srz PREFIX(fb_poly_tab_srz) +#define fb_poly_tab_sqr PREFIX(fb_poly_tab_sqr) +#define fb_poly_get_chain PREFIX(fb_poly_get_chain) +#define fb_poly_get_rdc PREFIX(fb_poly_get_rdc) +#define fb_poly_get_trc PREFIX(fb_poly_get_trc) +#define fb_poly_get_slv PREFIX(fb_poly_get_slv) +#define fb_param_set PREFIX(fb_param_set) +#define fb_param_set_any PREFIX(fb_param_set_any) +#define fb_param_print PREFIX(fb_param_print) +#define fb_poly_add PREFIX(fb_poly_add) +#define fb_copy PREFIX(fb_copy) +#define fb_neg PREFIX(fb_neg) +#define fb_zero PREFIX(fb_zero) +#define fb_is_zero PREFIX(fb_is_zero) +#define fb_get_bit PREFIX(fb_get_bit) +#define fb_set_bit PREFIX(fb_set_bit) +#define fb_set_dig PREFIX(fb_set_dig) +#define fb_bits PREFIX(fb_bits) +#define fb_rand PREFIX(fb_rand) +#define fb_print PREFIX(fb_print) +#define fb_size_str PREFIX(fb_size_str) +#define fb_read_str PREFIX(fb_read_str) +#define fb_write_str PREFIX(fb_write_str) +#define fb_read_bin PREFIX(fb_read_bin) +#define fb_write_bin PREFIX(fb_write_bin) +#define fb_cmp PREFIX(fb_cmp) +#define fb_cmp_dig PREFIX(fb_cmp_dig) +#define fb_add PREFIX(fb_add) +#define fb_add_dig PREFIX(fb_add_dig) +#define fb_mul_basic PREFIX(fb_mul_basic) +#define fb_mul_integ PREFIX(fb_mul_integ) +#define fb_mul_lodah PREFIX(fb_mul_lodah) +#define fb_mul_dig PREFIX(fb_mul_dig) +#define fb_mul_karat PREFIX(fb_mul_karat) +#define fb_sqr_basic PREFIX(fb_sqr_basic) +#define fb_sqr_integ PREFIX(fb_sqr_integ) +#define fb_sqr_quick PREFIX(fb_sqr_quick) +#define fb_lsh PREFIX(fb_lsh) +#define fb_rsh PREFIX(fb_rsh) +#define fb_rdc_basic PREFIX(fb_rdc_basic) +#define fb_rdc_quick PREFIX(fb_rdc_quick) +#define fb_srt_basic PREFIX(fb_srt_basic) +#define fb_srt_quick PREFIX(fb_srt_quick) +#define fb_trc_basic PREFIX(fb_trc_basic) +#define fb_trc_quick PREFIX(fb_trc_quick) +#define fb_inv_basic PREFIX(fb_inv_basic) +#define fb_inv_binar PREFIX(fb_inv_binar) +#define fb_inv_exgcd PREFIX(fb_inv_exgcd) +#define fb_inv_almos PREFIX(fb_inv_almos) +#define fb_inv_itoht PREFIX(fb_inv_itoht) +#define fb_inv_bruch PREFIX(fb_inv_bruch) +#define fb_inv_ctaia PREFIX(fb_inv_ctaia) +#define fb_inv_lower PREFIX(fb_inv_lower) +#define fb_inv_sim PREFIX(fb_inv_sim) +#define fb_exp_2b PREFIX(fb_exp_2b) +#define fb_exp_basic PREFIX(fb_exp_basic) +#define fb_exp_slide PREFIX(fb_exp_slide) +#define fb_exp_monty PREFIX(fb_exp_monty) +#define fb_slv_basic PREFIX(fb_slv_basic) +#define fb_slv_quick PREFIX(fb_slv_quick) +#define fb_itr_basic PREFIX(fb_itr_basic) +#define fb_itr_pre_quick PREFIX(fb_itr_pre_quick) +#define fb_itr_quick PREFIX(fb_itr_quick) + +#undef fb_add1_low +#undef fb_addn_low +#undef fb_addd_low +#undef fb_lsh1_low +#undef fb_lshb_low +#undef fb_lshd_low +#undef fb_rsh1_low +#undef fb_rshb_low +#undef fb_rshd_low +#undef fb_lsha_low +#undef fb_mul1_low +#undef fb_muln_low +#undef fb_muld_low +#undef fb_mulm_low +#undef fb_sqrn_low +#undef fb_sqrl_low +#undef fb_sqrm_low +#undef fb_itrn_low +#undef fb_srtn_low +#undef fb_slvn_low +#undef fb_trcn_low +#undef fb_rdcn_low +#undef fb_rdc1_low +#undef fb_invn_low + +#define fb_add1_low PREFIX(fb_add1_low) +#define fb_addn_low PREFIX(fb_addn_low) +#define fb_addd_low PREFIX(fb_addd_low) +#define fb_lsh1_low PREFIX(fb_lsh1_low) +#define fb_lshb_low PREFIX(fb_lshb_low) +#define fb_lshd_low PREFIX(fb_lshd_low) +#define fb_rsh1_low PREFIX(fb_rsh1_low) +#define fb_rshb_low PREFIX(fb_rshb_low) +#define fb_rshd_low PREFIX(fb_rshd_low) +#define fb_lsha_low PREFIX(fb_lsha_low) +#define fb_mul1_low PREFIX(fb_mul1_low) +#define fb_muln_low PREFIX(fb_muln_low) +#define fb_muld_low PREFIX(fb_muld_low) +#define fb_mulm_low PREFIX(fb_mulm_low) +#define fb_sqrn_low PREFIX(fb_sqrn_low) +#define fb_sqrl_low PREFIX(fb_sqrl_low) +#define fb_sqrm_low PREFIX(fb_sqrm_low) +#define fb_itrn_low PREFIX(fb_itrn_low) +#define fb_srtn_low PREFIX(fb_srtn_low) +#define fb_slvn_low PREFIX(fb_slvn_low) +#define fb_trcn_low PREFIX(fb_trcn_low) +#define fb_rdcn_low PREFIX(fb_rdcn_low) +#define fb_rdc1_low PREFIX(fb_rdc1_low) +#define fb_invn_low PREFIX(fb_invn_low) + +#undef ep_st +#undef ep_t +#define ep_st PREFIX(ep_st) +#define ep_t PREFIX(ep_t) + +#undef ep_curve_init +#undef ep_curve_clean +#undef ep_curve_get_a +#undef ep_curve_get_b +#undef ep_curve_get_beta +#undef ep_curve_get_v1 +#undef ep_curve_get_v2 +#undef ep_curve_opt_a +#undef ep_curve_opt_b +#undef ep_curve_is_endom +#undef ep_curve_is_super +#undef ep_curve_is_pairf +#undef ep_curve_is_ctmap +#undef ep_curve_get_gen +#undef ep_curve_get_tab +#undef ep_curve_get_ord +#undef ep_curve_get_cof +#undef ep_curve_get_iso +#undef ep_curve_set_plain +#undef ep_curve_set_super +#undef ep_curve_set_endom +#undef ep_param_set +#undef ep_param_set_any +#undef ep_param_set_any_plain +#undef ep_param_set_any_endom +#undef ep_param_set_any_super +#undef ep_param_set_any_pairf +#undef ep_param_get +#undef ep_param_print +#undef ep_param_level +#undef ep_param_embed +#undef ep_is_infty +#undef ep_set_infty +#undef ep_copy +#undef ep_cmp +#undef ep_rand +#undef ep_rhs +#undef ep_is_valid +#undef ep_tab +#undef ep_print +#undef ep_size_bin +#undef ep_read_bin +#undef ep_write_bin +#undef ep_neg_basic +#undef ep_neg_projc +#undef ep_add_basic +#undef ep_add_slp_basic +#undef ep_add_projc +#undef ep_sub_basic +#undef ep_sub_projc +#undef ep_dbl_basic +#undef ep_dbl_slp_basic +#undef ep_dbl_projc +#undef ep_mul_basic +#undef ep_mul_slide +#undef ep_mul_monty +#undef ep_mul_lwnaf +#undef ep_mul_lwreg +#undef ep_mul_gen +#undef ep_mul_dig +#undef ep_mul_pre_basic +#undef ep_mul_pre_yaowi +#undef ep_mul_pre_nafwi +#undef ep_mul_pre_combs +#undef ep_mul_pre_combd +#undef ep_mul_pre_lwnaf +#undef ep_mul_fix_basic +#undef ep_mul_fix_yaowi +#undef ep_mul_fix_nafwi +#undef ep_mul_fix_combs +#undef ep_mul_fix_combd +#undef ep_mul_fix_lwnaf +#undef ep_mul_sim_basic +#undef ep_mul_sim_trick +#undef ep_mul_sim_inter +#undef ep_mul_sim_joint +#undef ep_mul_sim_gen +#undef ep_mul_sim_dig +#undef ep_norm +#undef ep_norm_sim +#undef ep_map +#undef ep_map_dst +#undef ep_pck +#undef ep_upk + +#define ep_curve_init PREFIX(ep_curve_init) +#define ep_curve_clean PREFIX(ep_curve_clean) +#define ep_curve_get_a PREFIX(ep_curve_get_a) +#define ep_curve_get_b PREFIX(ep_curve_get_b) +#define ep_curve_get_beta PREFIX(ep_curve_get_beta) +#define ep_curve_get_v1 PREFIX(ep_curve_get_v1) +#define ep_curve_get_v2 PREFIX(ep_curve_get_v2) +#define ep_curve_opt_a PREFIX(ep_curve_opt_a) +#define ep_curve_opt_b PREFIX(ep_curve_opt_b) +#define ep_curve_is_endom PREFIX(ep_curve_is_endom) +#define ep_curve_is_super PREFIX(ep_curve_is_super) +#define ep_curve_is_pairf PREFIX(ep_curve_is_pairf) +#define ep_curve_is_ctmap PREFIX(ep_curve_is_ctmap) +#define ep_curve_get_gen PREFIX(ep_curve_get_gen) +#define ep_curve_get_tab PREFIX(ep_curve_get_tab) +#define ep_curve_get_ord PREFIX(ep_curve_get_ord) +#define ep_curve_get_cof PREFIX(ep_curve_get_cof) +#define ep_curve_get_iso PREFIX(ep_curve_get_iso) +#define ep_curve_set_plain PREFIX(ep_curve_set_plain) +#define ep_curve_set_super PREFIX(ep_curve_set_super) +#define ep_curve_set_endom PREFIX(ep_curve_set_endom) +#define ep_param_set PREFIX(ep_param_set) +#define ep_param_set_any PREFIX(ep_param_set_any) +#define ep_param_set_any_plain PREFIX(ep_param_set_any_plain) +#define ep_param_set_any_endom PREFIX(ep_param_set_any_endom) +#define ep_param_set_any_super PREFIX(ep_param_set_any_super) +#define ep_param_set_any_pairf PREFIX(ep_param_set_any_pairf) +#define ep_param_get PREFIX(ep_param_get) +#define ep_param_print PREFIX(ep_param_print) +#define ep_param_level PREFIX(ep_param_level) +#define ep_param_embed PREFIX(ep_param_embed) +#define ep_is_infty PREFIX(ep_is_infty) +#define ep_set_infty PREFIX(ep_set_infty) +#define ep_copy PREFIX(ep_copy) +#define ep_cmp PREFIX(ep_cmp) +#define ep_rand PREFIX(ep_rand) +#define ep_rhs PREFIX(ep_rhs) +#define ep_is_valid PREFIX(ep_is_valid) +#define ep_tab PREFIX(ep_tab) +#define ep_print PREFIX(ep_print) +#define ep_size_bin PREFIX(ep_size_bin) +#define ep_read_bin PREFIX(ep_read_bin) +#define ep_write_bin PREFIX(ep_write_bin) +#define ep_neg_basic PREFIX(ep_neg_basic) +#define ep_neg_projc PREFIX(ep_neg_projc) +#define ep_add_basic PREFIX(ep_add_basic) +#define ep_add_slp_basic PREFIX(ep_add_slp_basic) +#define ep_add_projc PREFIX(ep_add_projc) +#define ep_sub_basic PREFIX(ep_sub_basic) +#define ep_sub_projc PREFIX(ep_sub_projc) +#define ep_dbl_basic PREFIX(ep_dbl_basic) +#define ep_dbl_slp_basic PREFIX(ep_dbl_slp_basic) +#define ep_dbl_projc PREFIX(ep_dbl_projc) +#define ep_mul_basic PREFIX(ep_mul_basic) +#define ep_mul_slide PREFIX(ep_mul_slide) +#define ep_mul_monty PREFIX(ep_mul_monty) +#define ep_mul_lwnaf PREFIX(ep_mul_lwnaf) +#define ep_mul_lwreg PREFIX(ep_mul_lwreg) +#define ep_mul_gen PREFIX(ep_mul_gen) +#define ep_mul_dig PREFIX(ep_mul_dig) +#define ep_mul_pre_basic PREFIX(ep_mul_pre_basic) +#define ep_mul_pre_yaowi PREFIX(ep_mul_pre_yaowi) +#define ep_mul_pre_nafwi PREFIX(ep_mul_pre_nafwi) +#define ep_mul_pre_combs PREFIX(ep_mul_pre_combs) +#define ep_mul_pre_combd PREFIX(ep_mul_pre_combd) +#define ep_mul_pre_lwnaf PREFIX(ep_mul_pre_lwnaf) +#define ep_mul_fix_basic PREFIX(ep_mul_fix_basic) +#define ep_mul_fix_yaowi PREFIX(ep_mul_fix_yaowi) +#define ep_mul_fix_nafwi PREFIX(ep_mul_fix_nafwi) +#define ep_mul_fix_combs PREFIX(ep_mul_fix_combs) +#define ep_mul_fix_combd PREFIX(ep_mul_fix_combd) +#define ep_mul_fix_lwnaf PREFIX(ep_mul_fix_lwnaf) +#define ep_mul_sim_basic PREFIX(ep_mul_sim_basic) +#define ep_mul_sim_trick PREFIX(ep_mul_sim_trick) +#define ep_mul_sim_inter PREFIX(ep_mul_sim_inter) +#define ep_mul_sim_joint PREFIX(ep_mul_sim_joint) +#define ep_mul_sim_gen PREFIX(ep_mul_sim_gen) +#define ep_mul_sim_dig PREFIX(ep_mul_sim_dig) +#define ep_norm PREFIX(ep_norm) +#define ep_norm_sim PREFIX(ep_norm_sim) +#define ep_map PREFIX(ep_map) +#define ep_map_dst PREFIX(ep_map_dst) +#define ep_pck PREFIX(ep_pck) +#define ep_upk PREFIX(ep_upk) + +#undef ed_st +#undef ed_t +#define ed_st PREFIX(ed_st) +#define ed_t PREFIX(ed_t) + +#undef ed_param_set +#undef ed_param_set_any +#undef ed_param_get +#undef ed_curve_get_ord +#undef ed_curve_get_gen +#undef ed_curve_get_tab +#undef ed_curve_get_cof +#undef ed_param_print +#undef ed_param_level +#undef ed_projc_to_extnd +#undef ed_rand +#undef ed_rhs +#undef ed_copy +#undef ed_cmp +#undef ed_set_infty +#undef ed_is_infty +#undef ed_neg_basic +#undef ed_neg_projc +#undef ed_add_basic +#undef ed_add_projc +#undef ed_add_extnd +#undef ed_sub_basic +#undef ed_sub_projc +#undef ed_sub_extnd +#undef ed_dbl_basic +#undef ed_dbl_projc +#undef ed_dbl_extnd +#undef ed_norm +#undef ed_norm_sim +#undef ed_map +#undef ed_curve_init +#undef ed_curve_clean +#undef ed_mul_pre_basic +#undef ed_mul_pre_yaowi +#undef ed_mul_pre_nafwi +#undef ed_mul_pre_combs +#undef ed_mul_pre_combd +#undef ed_mul_pre_lwnaf +#undef ed_mul_fix_basic +#undef ed_mul_fix_yaowi +#undef ed_mul_fix_nafwi +#undef ed_mul_fix_combs +#undef ed_mul_fix_combd +#undef ed_mul_fix_lwnaf +#undef ed_mul_fix_lwnaf_mixed +#undef ed_mul_gen +#undef ed_mul_dig +#undef ed_mul_sim_basic +#undef ed_mul_sim_trick +#undef ed_mul_sim_inter +#undef ed_mul_sim_joint +#undef ed_mul_sim_gen +#undef ed_tab +#undef ed_print +#undef ed_is_valid +#undef ed_size_bin +#undef ed_read_bin +#undef ed_write_bin +#undef ed_mul_basic +#undef ed_mul_slide +#undef ed_mul_monty +#undef ed_mul_lwnaf +#undef ed_mul_lwreg +#undef ed_pck +#undef ed_upk + +#define ed_param_set PREFIX(ed_param_set) +#define ed_param_set_any PREFIX(ed_param_set_any) +#define ed_param_get PREFIX(ed_param_get) +#define ed_curve_get_ord PREFIX(ed_curve_get_ord) +#define ed_curve_get_gen PREFIX(ed_curve_get_gen) +#define ed_curve_get_tab PREFIX(ed_curve_get_tab) +#define ed_curve_get_cof PREFIX(ed_curve_get_cof) +#define ed_param_print PREFIX(ed_param_print) +#define ed_param_level PREFIX(ed_param_level) +#define ed_projc_to_extnd PREFIX(ed_projc_to_extnd) +#define ed_rand PREFIX(ed_rand) +#define ed_rhs PREFIX(ed_rhs) +#define ed_copy PREFIX(ed_copy) +#define ed_cmp PREFIX(ed_cmp) +#define ed_set_infty PREFIX(ed_set_infty) +#define ed_is_infty PREFIX(ed_is_infty) +#define ed_neg_basic PREFIX(ed_neg_basic) +#define ed_neg_projc PREFIX(ed_neg_projc) +#define ed_add_basic PREFIX(ed_add_basic) +#define ed_add_projc PREFIX(ed_add_projc) +#define ed_add_extnd PREFIX(ed_add_extnd) +#define ed_sub_basic PREFIX(ed_sub_basic) +#define ed_sub_projc PREFIX(ed_sub_projc) +#define ed_sub_extnd PREFIX(ed_sub_extnd) +#define ed_dbl_basic PREFIX(ed_dbl_basic) +#define ed_dbl_projc PREFIX(ed_dbl_projc) +#define ed_dbl_extnd PREFIX(ed_dbl_extnd) +#define ed_norm PREFIX(ed_norm) +#define ed_norm_sim PREFIX(ed_norm_sim) +#define ed_map PREFIX(ed_map) +#define ed_curve_init PREFIX(ed_curve_init) +#define ed_curve_clean PREFIX(ed_curve_clean) +#define ed_mul_pre_basic PREFIX(ed_mul_pre_basic) +#define ed_mul_pre_yaowi PREFIX(ed_mul_pre_yaowi) +#define ed_mul_pre_nafwi PREFIX(ed_mul_pre_nafwi) +#define ed_mul_pre_combs PREFIX(ed_mul_pre_combs) +#define ed_mul_pre_combd PREFIX(ed_mul_pre_combd) +#define ed_mul_pre_lwnaf PREFIX(ed_mul_pre_lwnaf) +#define ed_mul_fix_basic PREFIX(ed_mul_fix_basic) +#define ed_mul_fix_yaowi PREFIX(ed_mul_fix_yaowi) +#define ed_mul_fix_nafwi PREFIX(ed_mul_fix_nafwi) +#define ed_mul_fix_combs PREFIX(ed_mul_fix_combs) +#define ed_mul_fix_combd PREFIX(ed_mul_fix_combd) +#define ed_mul_fix_lwnaf PREFIX(ed_mul_fix_lwnaf) +#define ed_mul_fix_lwnaf_mixed PREFIX(ed_mul_fix_lwnaf_mixed) +#define ed_mul_gen PREFIX(ed_mul_gen) +#define ed_mul_dig PREFIX(ed_mul_dig) +#define ed_mul_sim_basic PREFIX(ed_mul_sim_basic) +#define ed_mul_sim_trick PREFIX(ed_mul_sim_trick) +#define ed_mul_sim_inter PREFIX(ed_mul_sim_inter) +#define ed_mul_sim_joint PREFIX(ed_mul_sim_joint) +#define ed_mul_sim_gen PREFIX(ed_mul_sim_gen) +#define ed_tab PREFIX(ed_tab) +#define ed_print PREFIX(ed_print) +#define ed_is_valid PREFIX(ed_is_valid) +#define ed_size_bin PREFIX(ed_size_bin) +#define ed_read_bin PREFIX(ed_read_bin) +#define ed_write_bin PREFIX(ed_write_bin) +#define ed_mul_basic PREFIX(ed_mul_basic) +#define ed_mul_slide PREFIX(ed_mul_slide) +#define ed_mul_monty PREFIX(ed_mul_monty) +#define ed_mul_lwnaf PREFIX(ed_mul_lwnaf) +#define ed_mul_lwreg PREFIX(ed_mul_lwreg) +#define ed_pck PREFIX(ed_pck) +#define ed_upk PREFIX(ed_upk) + +#undef eb_st +#undef eb_t +#define eb_st PREFIX(eb_st) +#define eb_t PREFIX(eb_t) + +#undef eb_curve_init +#undef eb_curve_clean +#undef eb_curve_get_a +#undef eb_curve_get_b +#undef eb_curve_opt_a +#undef eb_curve_opt_b +#undef eb_curve_is_kbltz +#undef eb_curve_get_gen +#undef eb_curve_get_tab +#undef eb_curve_get_ord +#undef eb_curve_get_cof +#undef eb_curve_set +#undef eb_param_set +#undef eb_param_set_any +#undef eb_param_set_any_plain +#undef eb_param_set_any_kbltz +#undef eb_param_get +#undef eb_param_print +#undef eb_param_level +#undef eb_is_infty +#undef eb_set_infty +#undef eb_copy +#undef eb_cmp +#undef eb_rand +#undef eb_rhs +#undef eb_is_valid +#undef eb_tab +#undef eb_print +#undef eb_size_bin +#undef eb_read_bin +#undef eb_write_bin +#undef eb_neg_basic +#undef eb_neg_projc +#undef eb_add_basic +#undef eb_add_projc +#undef eb_sub_basic +#undef eb_sub_projc +#undef eb_dbl_basic +#undef eb_dbl_projc +#undef eb_hlv +#undef eb_frb_basic +#undef eb_frb_projc +#undef eb_mul_basic +#undef eb_mul_lodah +#undef eb_mul_lwnaf +#undef eb_mul_rwnaf +#undef eb_mul_halve +#undef eb_mul_gen +#undef eb_mul_dig +#undef eb_mul_pre_basic +#undef eb_mul_pre_yaowi +#undef eb_mul_pre_nafwi +#undef eb_mul_pre_combs +#undef eb_mul_pre_combd +#undef eb_mul_pre_lwnaf +#undef eb_mul_fix_basic +#undef eb_mul_fix_yaowi +#undef eb_mul_fix_nafwi +#undef eb_mul_fix_combs +#undef eb_mul_fix_combd +#undef eb_mul_fix_lwnaf +#undef eb_mul_sim_basic +#undef eb_mul_sim_trick +#undef eb_mul_sim_inter +#undef eb_mul_sim_joint +#undef eb_mul_sim_gen +#undef eb_norm +#undef eb_norm_sim +#undef eb_map +#undef eb_pck +#undef eb_upk + +#define eb_curve_init PREFIX(eb_curve_init) +#define eb_curve_clean PREFIX(eb_curve_clean) +#define eb_curve_get_a PREFIX(eb_curve_get_a) +#define eb_curve_get_b PREFIX(eb_curve_get_b) +#define eb_curve_opt_a PREFIX(eb_curve_opt_a) +#define eb_curve_opt_b PREFIX(eb_curve_opt_b) +#define eb_curve_is_kbltz PREFIX(eb_curve_is_kbltz) +#define eb_curve_get_gen PREFIX(eb_curve_get_gen) +#define eb_curve_get_tab PREFIX(eb_curve_get_tab) +#define eb_curve_get_ord PREFIX(eb_curve_get_ord) +#define eb_curve_get_cof PREFIX(eb_curve_get_cof) +#define eb_curve_set PREFIX(eb_curve_set) +#define eb_param_set PREFIX(eb_param_set) +#define eb_param_set_any PREFIX(eb_param_set_any) +#define eb_param_set_any_plain PREFIX(eb_param_set_any_plain) +#define eb_param_set_any_kbltz PREFIX(eb_param_set_any_kbltz) +#define eb_param_get PREFIX(eb_param_get) +#define eb_param_print PREFIX(eb_param_print) +#define eb_param_level PREFIX(eb_param_level) +#define eb_is_infty PREFIX(eb_is_infty) +#define eb_set_infty PREFIX(eb_set_infty) +#define eb_copy PREFIX(eb_copy) +#define eb_cmp PREFIX(eb_cmp) +#define eb_rand PREFIX(eb_rand) +#define eb_rhs PREFIX(eb_rhs) +#define eb_is_valid PREFIX(eb_is_valid) +#define eb_tab PREFIX(eb_tab) +#define eb_print PREFIX(eb_print) +#define eb_size_bin PREFIX(eb_size_bin) +#define eb_read_bin PREFIX(eb_read_bin) +#define eb_write_bin PREFIX(eb_write_bin) +#define eb_neg_basic PREFIX(eb_neg_basic) +#define eb_neg_projc PREFIX(eb_neg_projc) +#define eb_add_basic PREFIX(eb_add_basic) +#define eb_add_projc PREFIX(eb_add_projc) +#define eb_sub_basic PREFIX(eb_sub_basic) +#define eb_sub_projc PREFIX(eb_sub_projc) +#define eb_dbl_basic PREFIX(eb_dbl_basic) +#define eb_dbl_projc PREFIX(eb_dbl_projc) +#define eb_hlv PREFIX(eb_hlv) +#define eb_frb_basic PREFIX(eb_frb_basic) +#define eb_frb_projc PREFIX(eb_frb_projc) +#define eb_mul_basic PREFIX(eb_mul_basic) +#define eb_mul_lodah PREFIX(eb_mul_lodah) +#define eb_mul_lwnaf PREFIX(eb_mul_lwnaf) +#define eb_mul_rwnaf PREFIX(eb_mul_rwnaf) +#define eb_mul_halve PREFIX(eb_mul_halve) +#define eb_mul_gen PREFIX(eb_mul_gen) +#define eb_mul_dig PREFIX(eb_mul_dig) +#define eb_mul_pre_basic PREFIX(eb_mul_pre_basic) +#define eb_mul_pre_yaowi PREFIX(eb_mul_pre_yaowi) +#define eb_mul_pre_nafwi PREFIX(eb_mul_pre_nafwi) +#define eb_mul_pre_combs PREFIX(eb_mul_pre_combs) +#define eb_mul_pre_combd PREFIX(eb_mul_pre_combd) +#define eb_mul_pre_lwnaf PREFIX(eb_mul_pre_lwnaf) +#define eb_mul_fix_basic PREFIX(eb_mul_fix_basic) +#define eb_mul_fix_yaowi PREFIX(eb_mul_fix_yaowi) +#define eb_mul_fix_nafwi PREFIX(eb_mul_fix_nafwi) +#define eb_mul_fix_combs PREFIX(eb_mul_fix_combs) +#define eb_mul_fix_combd PREFIX(eb_mul_fix_combd) +#define eb_mul_fix_lwnaf PREFIX(eb_mul_fix_lwnaf) +#define eb_mul_sim_basic PREFIX(eb_mul_sim_basic) +#define eb_mul_sim_trick PREFIX(eb_mul_sim_trick) +#define eb_mul_sim_inter PREFIX(eb_mul_sim_inter) +#define eb_mul_sim_joint PREFIX(eb_mul_sim_joint) +#define eb_mul_sim_gen PREFIX(eb_mul_sim_gen) +#define eb_norm PREFIX(eb_norm) +#define eb_norm_sim PREFIX(eb_norm_sim) +#define eb_map PREFIX(eb_map) +#define eb_pck PREFIX(eb_pck) +#define eb_upk PREFIX(eb_upk) + +#undef ep2_st +#undef ep2_t +#define ep2_st PREFIX(ep2_st) +#define ep2_t PREFIX(ep2_t) + +#undef ep2_curve_init +#undef ep2_curve_clean +#undef ep2_curve_get_a +#undef ep2_curve_get_b +#undef ep2_curve_get_vs +#undef ep2_curve_opt_a +#undef ep2_curve_opt_b +#undef ep2_curve_is_twist +#undef ep2_curve_is_ctmap +#undef ep2_curve_get_gen +#undef ep2_curve_get_tab +#undef ep2_curve_get_ord +#undef ep2_curve_get_cof +#undef ep2_curve_get_iso +#undef ep2_curve_set +#undef ep2_curve_set_twist +#undef ep2_is_infty +#undef ep2_set_infty +#undef ep2_copy +#undef ep2_cmp +#undef ep2_rand +#undef ep2_rhs +#undef ep2_is_valid +#undef ep2_tab +#undef ep2_print +#undef ep2_size_bin +#undef ep2_read_bin +#undef ep2_write_bin +#undef ep2_neg_basic +#undef ep2_neg_projc +#undef ep2_add_basic +#undef ep2_add_slp_basic +#undef ep2_sub_basic +#undef ep2_add_projc +#undef ep2_sub_projc +#undef ep2_dbl_basic +#undef ep2_dbl_slp_basic +#undef ep2_dbl_projc +#undef ep2_mul_basic +#undef ep2_mul_slide +#undef ep2_mul_monty +#undef ep2_mul_lwnaf +#undef ep2_mul_lwreg +#undef ep2_mul_gen +#undef ep2_mul_dig +#undef ep2_mul_pre_basic +#undef ep2_mul_pre_yaowi +#undef ep2_mul_pre_nafwi +#undef ep2_mul_pre_combs +#undef ep2_mul_pre_combd +#undef ep2_mul_pre_lwnaf +#undef ep2_mul_fix_basic +#undef ep2_mul_fix_yaowi +#undef ep2_mul_fix_nafwi +#undef ep2_mul_fix_combs +#undef ep2_mul_fix_combd +#undef ep2_mul_fix_lwnaf +#undef ep2_mul_sim_basic +#undef ep2_mul_sim_trick +#undef ep2_mul_sim_inter +#undef ep2_mul_sim_joint +#undef ep2_mul_sim_gen +#undef ep2_mul_sim_dig +#undef ep2_norm +#undef ep2_norm_sim +#undef ep2_map +#undef ep2_frb +#undef ep2_pck +#undef ep2_upk + +#define ep2_curve_init PREFIX(ep2_curve_init) +#define ep2_curve_clean PREFIX(ep2_curve_clean) +#define ep2_curve_get_a PREFIX(ep2_curve_get_a) +#define ep2_curve_get_b PREFIX(ep2_curve_get_b) +#define ep2_curve_get_vs PREFIX(ep2_curve_get_vs) +#define ep2_curve_opt_a PREFIX(ep2_curve_opt_a) +#define ep2_curve_opt_b PREFIX(ep2_curve_opt_b) +#define ep2_curve_is_twist PREFIX(ep2_curve_is_twist) +#define ep2_curve_is_ctmap PREFIX(ep2_curve_is_ctmap) +#define ep2_curve_get_gen PREFIX(ep2_curve_get_gen) +#define ep2_curve_get_tab PREFIX(ep2_curve_get_tab) +#define ep2_curve_get_ord PREFIX(ep2_curve_get_ord) +#define ep2_curve_get_cof PREFIX(ep2_curve_get_cof) +#define ep2_curve_get_iso PREFIX(ep2_curve_get_iso) +#define ep2_curve_set PREFIX(ep2_curve_set) +#define ep2_curve_set_twist PREFIX(ep2_curve_set_twist) +#define ep2_is_infty PREFIX(ep2_is_infty) +#define ep2_set_infty PREFIX(ep2_set_infty) +#define ep2_copy PREFIX(ep2_copy) +#define ep2_cmp PREFIX(ep2_cmp) +#define ep2_rand PREFIX(ep2_rand) +#define ep2_rhs PREFIX(ep2_rhs) +#define ep2_is_valid PREFIX(ep2_is_valid) +#define ep2_tab PREFIX(ep2_tab) +#define ep2_print PREFIX(ep2_print) +#define ep2_size_bin PREFIX(ep2_size_bin) +#define ep2_read_bin PREFIX(ep2_read_bin) +#define ep2_write_bin PREFIX(ep2_write_bin) +#define ep2_neg_basic PREFIX(ep2_neg_basic) +#define ep2_neg_projc PREFIX(ep2_neg_projc) +#define ep2_add_basic PREFIX(ep2_add_basic) +#define ep2_add_slp_basic PREFIX(ep2_add_slp_basic) +#define ep2_sub_basic PREFIX(ep2_sub_basic) +#define ep2_add_projc PREFIX(ep2_add_projc) +#define ep2_sub_projc PREFIX(ep2_sub_projc) +#define ep2_dbl_basic PREFIX(ep2_dbl_basic) +#define ep2_dbl_slp_basic PREFIX(ep2_dbl_slp_basic) +#define ep2_dbl_projc PREFIX(ep2_dbl_projc) +#define ep2_mul_basic PREFIX(ep2_mul_basic) +#define ep2_mul_slide PREFIX(ep2_mul_slide) +#define ep2_mul_monty PREFIX(ep2_mul_monty) +#define ep2_mul_lwnaf PREFIX(ep2_mul_lwnaf) +#define ep2_mul_lwreg PREFIX(ep2_mul_lwreg) +#define ep2_mul_gen PREFIX(ep2_mul_gen) +#define ep2_mul_dig PREFIX(ep2_mul_dig) +#define ep2_mul_pre_basic PREFIX(ep2_mul_pre_basic) +#define ep2_mul_pre_yaowi PREFIX(ep2_mul_pre_yaowi) +#define ep2_mul_pre_nafwi PREFIX(ep2_mul_pre_nafwi) +#define ep2_mul_pre_combs PREFIX(ep2_mul_pre_combs) +#define ep2_mul_pre_combd PREFIX(ep2_mul_pre_combd) +#define ep2_mul_pre_lwnaf PREFIX(ep2_mul_pre_lwnaf) +#define ep2_mul_fix_basic PREFIX(ep2_mul_fix_basic) +#define ep2_mul_fix_yaowi PREFIX(ep2_mul_fix_yaowi) +#define ep2_mul_fix_nafwi PREFIX(ep2_mul_fix_nafwi) +#define ep2_mul_fix_combs PREFIX(ep2_mul_fix_combs) +#define ep2_mul_fix_combd PREFIX(ep2_mul_fix_combd) +#define ep2_mul_fix_lwnaf PREFIX(ep2_mul_fix_lwnaf) +#define ep2_mul_sim_basic PREFIX(ep2_mul_sim_basic) +#define ep2_mul_sim_trick PREFIX(ep2_mul_sim_trick) +#define ep2_mul_sim_inter PREFIX(ep2_mul_sim_inter) +#define ep2_mul_sim_joint PREFIX(ep2_mul_sim_joint) +#define ep2_mul_sim_gen PREFIX(ep2_mul_sim_gen) +#define ep2_mul_sim_dig PREFIX(ep2_mul_sim_dig) +#define ep2_norm PREFIX(ep2_norm) +#define ep2_norm_sim PREFIX(ep2_norm_sim) +#define ep2_map PREFIX(ep2_map) +#define ep2_frb PREFIX(ep2_frb) +#define ep2_pck PREFIX(ep2_pck) +#define ep2_upk PREFIX(ep2_upk) + +#undef fp2_st +#undef fp2_t +#undef dv2_t +#define fp2_st PREFIX(fp2_st) +#define fp2_t PREFIX(fp2_t) +#define dv2_t PREFIX(dv2_t) +#undef fp3_st +#undef fp3_t +#undef dv3_t +#define fp3_st PREFIX(fp3_st) +#define fp3_t PREFIX(fp3_t) +#define dv3_t PREFIX(dv3_t) +#undef fp6_st +#undef fp6_t +#undef dv6_t +#define fp6_st PREFIX(fp6_st) +#define fp6_t PREFIX(fp6_t) +#define dv6_t PREFIX(dv6_t) +#undef fp9_st +#undef fp8_t +#undef dv8_t +#define fp8_st PREFIX(fp8_st) +#define fp8_t PREFIX(fp8_t) +#define dv8_t PREFIX(dv8_t) +#undef fp9_st +#undef fp9_t +#undef dv9_t +#define fp9_st PREFIX(fp9_st) +#define fp9_t PREFIX(fp9_t) +#define dv9_t PREFIX(dv9_t) +#undef fp12_st +#undef fp12_t +#undef dv12_t +#define fp12_st PREFIX(fp12_st) +#define fp12_t PREFIX(fp12_t) +#define dv12_t PREFIX(dv12_t) +#undef fp18_st +#undef fp18_t +#undef dv18_t +#define fp18_st PREFIX(fp18_st) +#define fp18_t PREFIX(fp18_t) +#define dv18_t PREFIX(dv18_t) +#undef fp24_st +#undef fp24_t +#undef dv24_t +#define fp24_st PREFIX(fp24_st) +#define fp24_t PREFIX(fp24_t) +#define dv24_t PREFIX(dv24_t) +#undef fp48_st +#undef fp48_t +#undef dv48_t +#define fp48_st PREFIX(fp48_st) +#define fp48_t PREFIX(fp48_t) +#define dv48_t PREFIX(dv48_t) +#undef fp54_st +#undef fp54_t +#undef dv54_t +#define fp54_st PREFIX(fp54_st) +#define fp54_t PREFIX(fp54_t) +#define dv54_t PREFIX(dv54_t) + +#undef fp2_field_init +#undef fp2_field_get_qnr +#undef fp2_copy +#undef fp2_zero +#undef fp2_is_zero +#undef fp2_rand +#undef fp2_print +#undef fp2_size_bin +#undef fp2_read_bin +#undef fp2_write_bin +#undef fp2_cmp +#undef fp2_cmp_dig +#undef fp2_set_dig +#undef fp2_add_basic +#undef fp2_add_integ +#undef fp2_add_dig +#undef fp2_sub_basic +#undef fp2_sub_integ +#undef fpt_sub_dig +#undef fp2_neg +#undef fp2_dbl_basic +#undef fp2_dbl_integ +#undef fp2_mul_basic +#undef fp2_mul_integ +#undef fp2_mul_art +#undef fp2_mul_nor_basic +#undef fp2_mul_nor_integ +#undef fp2_mul_frb +#undef fp2_mul_dig +#undef fp2_sqr_basic +#undef fp2_sqr_integ +#undef fp2_inv +#undef fp2_inv_cyc +#undef fp2_inv_sim +#undef fp2_test_cyc +#undef fp2_conv_cyc +#undef fp2_exp +#undef fp2_exp_dig +#undef fp2_exp_cyc +#undef fp2_frb +#undef fp2_srt +#undef fp2_pck +#undef fp2_upk + +#define fp2_field_init PREFIX(fp2_field_init) +#define fp2_field_get_qnr PREFIX(fp2_field_get_qnr) +#define fp2_copy PREFIX(fp2_copy) +#define fp2_zero PREFIX(fp2_zero) +#define fp2_is_zero PREFIX(fp2_is_zero) +#define fp2_rand PREFIX(fp2_rand) +#define fp2_print PREFIX(fp2_print) +#define fp2_size_bin PREFIX(fp2_size_bin) +#define fp2_read_bin PREFIX(fp2_read_bin) +#define fp2_write_bin PREFIX(fp2_write_bin) +#define fp2_cmp PREFIX(fp2_cmp) +#define fp2_cmp_dig PREFIX(fp2_cmp_dig) +#define fp2_set_dig PREFIX(fp2_set_dig) +#define fp2_add_basic PREFIX(fp2_add_basic) +#define fp2_add_integ PREFIX(fp2_add_integ) +#define fp2_add_dig PREFIX(fp2_add_dig) +#define fp2_sub_basic PREFIX(fp2_sub_basic) +#define fp2_sub_integ PREFIX(fp2_sub_integ) +#define fp2_sub_dig PREFIX(fp2_sub_dig) +#define fp2_neg PREFIX(fp2_neg) +#define fp2_dbl_basic PREFIX(fp2_dbl_basic) +#define fp2_dbl_integ PREFIX(fp2_dbl_integ) +#define fp2_mul_basic PREFIX(fp2_mul_basic) +#define fp2_mul_integ PREFIX(fp2_mul_integ) +#define fp2_mul_art PREFIX(fp2_mul_art) +#define fp2_mul_nor_basic PREFIX(fp2_mul_nor_basic) +#define fp2_mul_nor_integ PREFIX(fp2_mul_nor_integ) +#define fp2_mul_frb PREFIX(fp2_mul_frb) +#define fp2_mul_dig PREFIX(fp2_mul_dig) +#define fp2_sqr_basic PREFIX(fp2_sqr_basic) +#define fp2_sqr_integ PREFIX(fp2_sqr_integ) +#define fp2_inv PREFIX(fp2_inv) +#define fp2_inv_cyc PREFIX(fp2_inv_cyc) +#define fp2_inv_sim PREFIX(fp2_inv_sim) +#define fp2_test_cyc PREFIX(fp2_test_cyc) +#define fp2_conv_cyc PREFIX(fp2_conv_cyc) +#define fp2_exp PREFIX(fp2_exp) +#define fp2_exp_dig PREFIX(fp2_exp_dig) +#define fp2_exp_cyc PREFIX(fp2_exp_cyc) +#define fp2_frb PREFIX(fp2_frb) +#define fp2_srt PREFIX(fp2_srt) +#define fp2_pck PREFIX(fp2_pck) +#define fp2_upk PREFIX(fp2_upk) + +#undef fp2_addn_low +#undef fp2_addm_low +#undef fp2_addd_low +#undef fp2_addc_low +#undef fp2_subn_low +#undef fp2_subm_low +#undef fp2_subd_low +#undef fp2_subc_low +#undef fp2_dbln_low +#undef fp2_dblm_low +#undef fp2_norm_low +#undef fp2_norh_low +#undef fp2_nord_low +#undef fp2_muln_low +#undef fp2_mulc_low +#undef fp2_mulm_low +#undef fp2_sqrn_low +#undef fp2_sqrm_low +#undef fp2_rdcn_low + +#define fp2_addn_low PREFIX(fp2_addn_low) +#define fp2_addm_low PREFIX(fp2_addm_low) +#define fp2_addd_low PREFIX(fp2_addd_low) +#define fp2_addc_low PREFIX(fp2_addc_low) +#define fp2_subn_low PREFIX(fp2_subn_low) +#define fp2_subm_low PREFIX(fp2_subm_low) +#define fp2_subd_low PREFIX(fp2_subd_low) +#define fp2_subc_low PREFIX(fp2_subc_low) +#define fp2_dbln_low PREFIX(fp2_dbln_low) +#define fp2_dblm_low PREFIX(fp2_dblm_low) +#define fp2_norm_low PREFIX(fp2_norm_low) +#define fp2_norh_low PREFIX(fp2_norh_low) +#define fp2_nord_low PREFIX(fp2_nord_low) +#define fp2_muln_low PREFIX(fp2_muln_low) +#define fp2_mulc_low PREFIX(fp2_mulc_low) +#define fp2_mulm_low PREFIX(fp2_mulm_low) +#define fp2_sqrn_low PREFIX(fp2_sqrn_low) +#define fp2_sqrm_low PREFIX(fp2_sqrm_low) +#define fp2_rdcn_low PREFIX(fp2_rdcn_low) + +#undef fp3_field_init +#undef fp3_copy +#undef fp3_zero +#undef fp3_is_zero +#undef fp3_rand +#undef fp3_print +#undef fp3_size_bin +#undef fp3_read_bin +#undef fp3_write_bin +#undef fp3_cmp +#undef fp3_cmp_dig +#undef fp3_set_dig +#undef fp3_add_basic +#undef fp3_add_integ +#undef fp3_sub_basic +#undef fp3_sub_integ +#undef fp3_neg +#undef fp3_dbl_basic +#undef fp3_dbl_integ +#undef fp3_mul_basic +#undef fp3_mul_integ +#undef fp3_mul_nor +#undef fp3_mul_frb +#undef fp3_sqr_basic +#undef fp3_sqr_integ +#undef fp3_inv +#undef fp3_inv_sim +#undef fp3_exp +#undef fp3_frb +#undef fp3_srt + +#define fp3_field_init PREFIX(fp3_field_init) +#define fp3_copy PREFIX(fp3_copy) +#define fp3_zero PREFIX(fp3_zero) +#define fp3_is_zero PREFIX(fp3_is_zero) +#define fp3_rand PREFIX(fp3_rand) +#define fp3_print PREFIX(fp3_print) +#define fp3_size_bin PREFIX(fp3_size_bin) +#define fp3_read_bin PREFIX(fp3_read_bin) +#define fp3_write_bin PREFIX(fp3_write_bin) +#define fp3_cmp PREFIX(fp3_cmp) +#define fp3_cmp_dig PREFIX(fp3_cmp_dig) +#define fp3_set_dig PREFIX(fp3_set_dig) +#define fp3_add_basic PREFIX(fp3_add_basic) +#define fp3_add_integ PREFIX(fp3_add_integ) +#define fp3_sub_basic PREFIX(fp3_sub_basic) +#define fp3_sub_integ PREFIX(fp3_sub_integ) +#define fp3_neg PREFIX(fp3_neg) +#define fp3_dbl_basic PREFIX(fp3_dbl_basic) +#define fp3_dbl_integ PREFIX(fp3_dbl_integ) +#define fp3_mul_basic PREFIX(fp3_mul_basic) +#define fp3_mul_integ PREFIX(fp3_mul_integ) +#define fp3_mul_nor PREFIX(fp3_mul_nor) +#define fp3_mul_frb PREFIX(fp3_mul_frb) +#define fp3_sqr_basic PREFIX(fp3_sqr_basic) +#define fp3_sqr_integ PREFIX(fp3_sqr_integ) +#define fp3_inv PREFIX(fp3_inv) +#define fp3_inv_sim PREFIX(fp3_inv_sim) +#define fp3_exp PREFIX(fp3_exp) +#define fp3_frb PREFIX(fp3_frb) +#define fp3_srt PREFIX(fp3_srt) + +#undef fp3_addn_low +#undef fp3_addm_low +#undef fp3_addd_low +#undef fp3_addc_low +#undef fp3_subn_low +#undef fp3_subm_low +#undef fp3_subd_low +#undef fp3_subc_low +#undef fp3_dbln_low +#undef fp3_dblm_low +#undef fp3_nord_low +#undef fp3_muln_low +#undef fp3_mulc_low +#undef fp3_mulm_low +#undef fp3_sqrn_low +#undef fp3_sqrm_low +#undef fp3_rdcn_low + +#define fp3_addn_low PREFIX(fp3_addn_low) +#define fp3_addm_low PREFIX(fp3_addm_low) +#define fp3_addd_low PREFIX(fp3_addd_low) +#define fp3_addc_low PREFIX(fp3_addc_low) +#define fp3_subn_low PREFIX(fp3_subn_low) +#define fp3_subm_low PREFIX(fp3_subm_low) +#define fp3_subd_low PREFIX(fp3_subd_low) +#define fp3_subc_low PREFIX(fp3_subc_low) +#define fp3_dbln_low PREFIX(fp3_dbln_low) +#define fp3_dblm_low PREFIX(fp3_dblm_low) +#define fp3_nord_low PREFIX(fp3_nord_low) +#define fp3_muln_low PREFIX(fp3_muln_low) +#define fp3_mulc_low PREFIX(fp3_mulc_low) +#define fp3_mulm_low PREFIX(fp3_mulm_low) +#define fp3_sqrn_low PREFIX(fp3_sqrn_low) +#define fp3_sqrm_low PREFIX(fp3_sqrm_low) +#define fp3_rdcn_low PREFIX(fp3_rdcn_low) + +#undef fp4_copy +#undef fp4_zero +#undef fp4_is_zero +#undef fp4_rand +#undef fp4_print +#undef fp4_size_bin +#undef fp4_read_bin +#undef fp4_write_bin +#undef fp4_cmp +#undef fp4_cmp_dig +#undef fp4_set_dig +#undef fp4_add +#undef fp4_sub +#undef fp4_neg +#undef fp4_dbl +#undef fp4_mul_unr +#undef fp4_mul_basic +#undef fp4_mul_lazyr +#undef fp4_mul_art +#undef fp4_mul_dxs +#undef fp4_sqr_unr +#undef fp4_sqr_basic +#undef fp4_sqr_lazyr +#undef fp4_inv +#undef fp4_inv_cyc +#undef fp4_exp +#undef fp4_frb + +#define fp4_copy PREFIX(fp4_copy) +#define fp4_zero PREFIX(fp4_zero) +#define fp4_is_zero PREFIX(fp4_is_zero) +#define fp4_rand PREFIX(fp4_rand) +#define fp4_print PREFIX(fp4_print) +#define fp4_size_bin PREFIX(fp4_size_bin) +#define fp4_read_bin PREFIX(fp4_read_bin) +#define fp4_write_bin PREFIX(fp4_write_bin) +#define fp4_cmp PREFIX(fp4_cmp) +#define fp4_cmp_dig PREFIX(fp4_cmp_dig) +#define fp4_set_dig PREFIX(fp4_set_dig) +#define fp4_add PREFIX(fp4_add) +#define fp4_sub PREFIX(fp4_sub) +#define fp4_neg PREFIX(fp4_neg) +#define fp4_dbl PREFIX(fp4_dbl) +#define fp4_mul_unr PREFIX(fp4_mul_unr) +#define fp4_mul_basic PREFIX(fp4_mul_basic) +#define fp4_mul_lazyr PREFIX(fp4_mul_lazyr) +#define fp4_mul_art PREFIX(fp4_mul_art) +#define fp4_mul_dxs PREFIX(fp4_mul_dxs) +#define fp4_sqr_unr PREFIX(fp4_sqr_unr) +#define fp4_sqr_basic PREFIX(fp4_sqr_basic) +#define fp4_sqr_lazyr PREFIX(fp4_sqr_lazyr) +#define fp4_inv PREFIX(fp4_inv) +#define fp4_inv_cyc PREFIX(fp4_inv_cyc) +#define fp4_exp PREFIX(fp4_exp) +#define fp4_frb PREFIX(fp4_frb) + +#undef fp6_copy +#undef fp6_zero +#undef fp6_is_zero +#undef fp6_rand +#undef fp6_print +#undef fp6_size_bin +#undef fp6_read_bin +#undef fp6_write_bin +#undef fp6_cmp +#undef fp6_cmp_dig +#undef fp6_set_dig +#undef fp6_add +#undef fp6_sub +#undef fp6_neg +#undef fp6_dbl +#undef fp6_mul_unr +#undef fp6_mul_basic +#undef fp6_mul_lazyr +#undef fp6_mul_art +#undef fp6_mul_dxs +#undef fp6_sqr_unr +#undef fp6_sqr_basic +#undef fp6_sqr_lazyr +#undef fp6_inv +#undef fp6_exp +#undef fp6_frb + +#define fp6_copy PREFIX(fp6_copy) +#define fp6_zero PREFIX(fp6_zero) +#define fp6_is_zero PREFIX(fp6_is_zero) +#define fp6_rand PREFIX(fp6_rand) +#define fp6_print PREFIX(fp6_print) +#define fp6_size_bin PREFIX(fp6_size_bin) +#define fp6_read_bin PREFIX(fp6_read_bin) +#define fp6_write_bin PREFIX(fp6_write_bin) +#define fp6_cmp PREFIX(fp6_cmp) +#define fp6_cmp_dig PREFIX(fp6_cmp_dig) +#define fp6_set_dig PREFIX(fp6_set_dig) +#define fp6_add PREFIX(fp6_add) +#define fp6_sub PREFIX(fp6_sub) +#define fp6_neg PREFIX(fp6_neg) +#define fp6_dbl PREFIX(fp6_dbl) +#define fp6_mul_unr PREFIX(fp6_mul_unr) +#define fp6_mul_basic PREFIX(fp6_mul_basic) +#define fp6_mul_lazyr PREFIX(fp6_mul_lazyr) +#define fp6_mul_art PREFIX(fp6_mul_art) +#define fp6_mul_dxs PREFIX(fp6_mul_dxs) +#define fp6_sqr_unr PREFIX(fp6_sqr_unr) +#define fp6_sqr_basic PREFIX(fp6_sqr_basic) +#define fp6_sqr_lazyr PREFIX(fp6_sqr_lazyr) +#define fp6_inv PREFIX(fp6_inv) +#define fp6_exp PREFIX(fp6_exp) +#define fp6_frb PREFIX(fp6_frb) + +#undef fp8_copy +#undef fp8_zero +#undef fp8_is_zero +#undef fp8_rand +#undef fp8_print +#undef fp8_size_bin +#undef fp8_read_bin +#undef fp8_write_bin +#undef fp8_cmp +#undef fp8_cmp_dig +#undef fp8_set_dig +#undef fp8_add +#undef fp8_sub +#undef fp8_neg +#undef fp8_dbl +#undef fp8_mul_unr +#undef fp8_mul_basic +#undef fp8_mul_lazyr +#undef fp8_mul_art +#undef fp8_mul_dxs +#undef fp8_sqr_unr +#undef fp8_sqr_basic +#undef fp8_sqr_lazyr +#undef fp8_sqr_cyc +#undef fp8_inv +#undef fp8_inv_cyc +#undef fp8_inv_sim +#undef fp8_test_cyc +#undef fp8_conv_cyc +#undef fp8_exp +#undef fp8_exp_cyc +#undef fp8_frb + +#define fp8_copy PREFIX(fp8_copy) +#define fp8_zero PREFIX(fp8_zero) +#define fp8_is_zero PREFIX(fp8_is_zero) +#define fp8_rand PREFIX(fp8_rand) +#define fp8_print PREFIX(fp8_print) +#define fp8_size_bin PREFIX(fp8_size_bin) +#define fp8_read_bin PREFIX(fp8_read_bin) +#define fp8_write_bin PREFIX(fp8_write_bin) +#define fp8_cmp PREFIX(fp8_cmp) +#define fp8_cmp_dig PREFIX(fp8_cmp_dig) +#define fp8_set_dig PREFIX(fp8_set_dig) +#define fp8_add PREFIX(fp8_add) +#define fp8_sub PREFIX(fp8_sub) +#define fp8_neg PREFIX(fp8_neg) +#define fp8_dbl PREFIX(fp8_dbl) +#define fp8_mul_unr PREFIX(fp8_mul_unr) +#define fp8_mul_basic PREFIX(fp8_mul_basic) +#define fp8_mul_lazyr PREFIX(fp8_mul_lazyr) +#define fp8_mul_art PREFIX(fp8_mul_art) +#define fp8_mul_dxs PREFIX(fp8_mul_dxs) +#define fp8_sqr_unr PREFIX(fp8_sqr_unr) +#define fp8_sqr_basic PREFIX(fp8_sqr_basic) +#define fp8_sqr_lazyr PREFIX(fp8_sqr_lazyr) +#define fp8_sqr_cyc PREFIX(fp8_sqr_cyc) +#define fp8_inv PREFIX(fp8_inv) +#define fp8_inv_cyc PREFIX(fp8_inv_cyc) +#define fp8_inv_sim PREFIX(fp8_inv_sim) +#define fp8_test_cyc PREFIX(fp8_test_cyc) +#define fp8_conv_cyc PREFIX(fp8_conv_cyc) +#define fp8_exp PREFIX(fp8_exp) +#define fp8_exp_cyc PREFIX(fp8_exp_cyc) +#define fp8_frb PREFIX(fp8_frb) + +#undef fp9_copy +#undef fp9_zero +#undef fp9_is_zero +#undef fp9_rand +#undef fp9_print +#undef fp9_size_bin +#undef fp9_read_bin +#undef fp9_write_bin +#undef fp9_cmp +#undef fp9_cmp_dig +#undef fp9_set_dig +#undef fp9_add +#undef fp9_sub +#undef fp9_neg +#undef fp9_dbl +#undef fp9_mul_unr +#undef fp9_mul_basic +#undef fp9_mul_lazyr +#undef fp9_mul_art +#undef fp9_mul_dxs +#undef fp9_sqr_unr +#undef fp9_sqr_basic +#undef fp9_sqr_lazyr +#undef fp9_inv +#undef fp9_inv_sim +#undef fp9_exp +#undef fp9_frb + +#define fp9_copy PREFIX(fp9_copy) +#define fp9_zero PREFIX(fp9_zero) +#define fp9_is_zero PREFIX(fp9_is_zero) +#define fp9_rand PREFIX(fp9_rand) +#define fp9_print PREFIX(fp9_print) +#define fp9_size_bin PREFIX(fp9_size_bin) +#define fp9_read_bin PREFIX(fp9_read_bin) +#define fp9_write_bin PREFIX(fp9_write_bin) +#define fp9_cmp PREFIX(fp9_cmp) +#define fp9_cmp_dig PREFIX(fp9_cmp_dig) +#define fp9_set_dig PREFIX(fp9_set_dig) +#define fp9_add PREFIX(fp9_add) +#define fp9_sub PREFIX(fp9_sub) +#define fp9_neg PREFIX(fp9_neg) +#define fp9_dbl PREFIX(fp9_dbl) +#define fp9_mul_unr PREFIX(fp9_mul_unr) +#define fp9_mul_basic PREFIX(fp9_mul_basic) +#define fp9_mul_lazyr PREFIX(fp9_mul_lazyr) +#define fp9_mul_art PREFIX(fp9_mul_art) +#define fp9_mul_dxs PREFIX(fp9_mul_dxs) +#define fp9_sqr_unr PREFIX(fp9_sqr_unr) +#define fp9_sqr_basic PREFIX(fp9_sqr_basic) +#define fp9_sqr_lazyr PREFIX(fp9_sqr_lazyr) +#define fp9_inv PREFIX(fp9_inv) +#define fp9_inv_sim PREFIX(fp9_inv_sim) +#define fp9_exp PREFIX(fp9_exp) +#define fp9_frb PREFIX(fp9_frb) + +#undef fp12_copy +#undef fp12_zero +#undef fp12_is_zero +#undef fp12_rand +#undef fp12_print +#undef fp12_size_bin +#undef fp12_read_bin +#undef fp12_write_bin +#undef fp12_cmp +#undef fp12_cmp_dig +#undef fp12_set_dig +#undef fp12_add +#undef fp12_sub +#undef fp12_neg +#undef fp12_dbl +#undef fp12_mul_unr +#undef fp12_mul_basic +#undef fp12_mul_lazyr +#undef fp12_mul_art +#undef fp12_mul_dxs_basic +#undef fp12_mul_dxs_lazyr +#undef fp12_sqr_unr +#undef fp12_sqr_basic +#undef fp12_sqr_lazyr +#undef fp12_sqr_cyc_basic +#undef fp12_sqr_cyc_lazyr +#undef fp12_sqr_pck_basic +#undef fp12_sqr_pck_lazyr +#undef fp12_test_cyc +#undef fp12_conv_cyc +#undef fp12_back_cyc +#undef fp12_back_cyc_sim +#undef fp12_inv +#undef fp12_inv_cyc +#undef fp12_frb +#undef fp12_exp +#undef fp12_exp_dig +#undef fp12_exp_cyc +#undef fp12_exp_cyc_sps +#undef fp12_pck +#undef fp12_upk + +#define fp12_copy PREFIX(fp12_copy) +#define fp12_zero PREFIX(fp12_zero) +#define fp12_is_zero PREFIX(fp12_is_zero) +#define fp12_rand PREFIX(fp12_rand) +#define fp12_print PREFIX(fp12_print) +#define fp12_size_bin PREFIX(fp12_size_bin) +#define fp12_read_bin PREFIX(fp12_read_bin) +#define fp12_write_bin PREFIX(fp12_write_bin) +#define fp12_cmp PREFIX(fp12_cmp) +#define fp12_cmp_dig PREFIX(fp12_cmp_dig) +#define fp12_set_dig PREFIX(fp12_set_dig) +#define fp12_add PREFIX(fp12_add) +#define fp12_sub PREFIX(fp12_sub) +#define fp12_neg PREFIX(fp12_neg) +#define fp12_dbl PREFIX(fp12_dbl) +#define fp12_mul_unr PREFIX(fp12_mul_unr) +#define fp12_mul_basic PREFIX(fp12_mul_basic) +#define fp12_mul_lazyr PREFIX(fp12_mul_lazyr) +#define fp12_mul_art PREFIX(fp12_mul_art) +#define fp12_mul_dxs_basic PREFIX(fp12_mul_dxs_basic) +#define fp12_mul_dxs_lazyr PREFIX(fp12_mul_dxs_lazyr) +#define fp12_sqr_unr PREFIX(fp12_sqr_unr) +#define fp12_sqr_basic PREFIX(fp12_sqr_basic) +#define fp12_sqr_lazyr PREFIX(fp12_sqr_lazyr) +#define fp12_sqr_cyc_basic PREFIX(fp12_sqr_cyc_basic) +#define fp12_sqr_cyc_lazyr PREFIX(fp12_sqr_cyc_lazyr) +#define fp12_sqr_pck_basic PREFIX(fp12_sqr_pck_basic) +#define fp12_sqr_pck_lazyr PREFIX(fp12_sqr_pck_lazyr) +#define fp12_test_cyc PREFIX(fp12_test_cyc) +#define fp12_conv_cyc PREFIX(fp12_conv_cyc) +#define fp12_back_cyc PREFIX(fp12_back_cyc) +#define fp12_back_cyc_sim PREFIX(fp12_back_cyc_sim) +#define fp12_inv PREFIX(fp12_inv) +#define fp12_inv_cyc PREFIX(fp12_inv_cyc) +#define fp12_frb PREFIX(fp12_frb) +#define fp12_exp PREFIX(fp12_exp) +#define fp12_exp_dig PREFIX(fp12_exp_dig) +#define fp12_exp_cyc PREFIX(fp12_exp_cyc) +#define fp12_exp_cyc_sps PREFIX(fp12_exp_cyc_sps) +#define fp12_pck PREFIX(fp12_pck) +#define fp12_upk PREFIX(fp12_upk) + +#undef fp18_copy +#undef fp18_zero +#undef fp18_is_zero +#undef fp18_rand +#undef fp18_print +#undef fp18_size_bin +#undef fp18_read_bin +#undef fp18_write_bin +#undef fp18_cmp +#undef fp18_cmp_dig +#undef fp18_set_dig +#undef fp18_add +#undef fp18_sub +#undef fp18_neg +#undef fp18_dbl +#undef fp18_mul_unr +#undef fp18_mul_basic +#undef fp18_mul_lazyr +#undef fp18_mul_art +#undef fp18_mul_dxs_basic +#undef fp18_mul_dxs_lazyr +#undef fp18_sqr_unr +#undef fp18_sqr_basic +#undef fp18_sqr_lazyr +#undef fp18_inv +#undef fp18_inv_cyc +#undef fp18_conv_cyc +#undef fp18_frb +#undef fp18_exp + +#define fp18_copy PREFIX(fp18_copy) +#define fp18_zero PREFIX(fp18_zero) +#define fp18_is_zero PREFIX(fp18_is_zero) +#define fp18_rand PREFIX(fp18_rand) +#define fp18_print PREFIX(fp18_print) +#define fp18_size_bin PREFIX(fp18_size_bin) +#define fp18_read_bin PREFIX(fp18_read_bin) +#define fp18_write_bin PREFIX(fp18_write_bin) +#define fp18_cmp PREFIX(fp18_cmp) +#define fp18_cmp_dig PREFIX(fp18_cmp_dig) +#define fp18_set_dig PREFIX(fp18_set_dig) +#define fp18_add PREFIX(fp18_add) +#define fp18_sub PREFIX(fp18_sub) +#define fp18_neg PREFIX(fp18_neg) +#define fp18_dbl PREFIX(fp18_dbl) +#define fp18_mul_unr PREFIX(fp18_mul_unr) +#define fp18_mul_basic PREFIX(fp18_mul_basic) +#define fp18_mul_lazyr PREFIX(fp18_mul_lazyr) +#define fp18_mul_art PREFIX(fp18_mul_art) +#define fp18_mul_dxs_basic PREFIX(fp18_mul_dxs_basic) +#define fp18_mul_dxs_lazyr PREFIX(fp18_mul_dxs_lazyr) +#define fp18_sqr_unr PREFIX(fp18_sqr_unr) +#define fp18_sqr_basic PREFIX(fp18_sqr_basic) +#define fp18_sqr_lazyr PREFIX(fp18_sqr_lazyr) +#define fp18_inv PREFIX(fp18_inv) +#define fp18_inv_cyc PREFIX(fp18_inv_cyc) +#define fp18_conv_cyc PREFIX(fp18_conv_cyc) +#define fp18_frb PREFIX(fp18_frb) +#define fp18_exp PREFIX(fp18_exp) + +#undef fp24_copy +#undef fp24_zero +#undef fp24_is_zero +#undef fp24_rand +#undef fp24_print +#undef fp24_size_bin +#undef fp24_read_bin +#undef fp24_write_bin +#undef fp24_cmp +#undef fp24_cmp_dig +#undef fp24_set_dig +#undef fp24_add +#undef fp24_sub +#undef fp24_neg +#undef fp24_dbl +#undef fp24_mul_unr +#undef fp24_mul_basic +#undef fp24_mul_lazyr +#undef fp24_mul_art +#undef fp24_mul_dxs +#undef fp24_sqr_unr +#undef fp24_sqr_basic +#undef fp24_sqr_lazyr +#undef fp24_inv +#undef fp24_frb +#undef fp24_exp + +#define fp24_copy PREFIX(fp24_copy) +#define fp24_zero PREFIX(fp24_zero) +#define fp24_is_zero PREFIX(fp24_is_zero) +#define fp24_rand PREFIX(fp24_rand) +#define fp24_print PREFIX(fp24_print) +#define fp24_size_bin PREFIX(fp24_size_bin) +#define fp24_read_bin PREFIX(fp24_read_bin) +#define fp24_write_bin PREFIX(fp24_write_bin) +#define fp24_cmp PREFIX(fp24_cmp) +#define fp24_cmp_dig PREFIX(fp24_cmp_dig) +#define fp24_set_dig PREFIX(fp24_set_dig) +#define fp24_add PREFIX(fp24_add) +#define fp24_sub PREFIX(fp24_sub) +#define fp24_neg PREFIX(fp24_neg) +#define fp24_dbl PREFIX(fp24_dbl) +#define fp24_mul_unr PREFIX(fp24_mul_unr) +#define fp24_mul_basic PREFIX(fp24_mul_basic) +#define fp24_mul_lazyr PREFIX(fp24_mul_lazyr) +#define fp24_mul_art PREFIX(fp24_mul_art) +#define fp24_mul_dxs PREFIX(fp24_mul_dxs) +#define fp24_sqr_unr PREFIX(fp24_sqr_unr) +#define fp24_sqr_basic PREFIX(fp24_sqr_basic) +#define fp24_sqr_lazyr PREFIX(fp24_sqr_lazyr) +#define fp24_inv PREFIX(fp24_inv) +#define fp24_frb PREFIX(fp24_frb) +#define fp24_exp PREFIX(fp24_exp) + +#undef fp48_copy +#undef fp48_zero +#undef fp48_is_zero +#undef fp48_rand +#undef fp48_print +#undef fp48_size_bin +#undef fp48_read_bin +#undef fp48_write_bin +#undef fp48_cmp +#undef fp48_cmp_dig +#undef fp48_set_dig +#undef fp48_add +#undef fp48_sub +#undef fp48_neg +#undef fp48_dbl +#undef fp48_mul_unr +#undef fp48_mul_basic +#undef fp48_mul_lazyr +#undef fp48_mul_art +#undef fp48_mul_dxs +#undef fp48_sqr_unr +#undef fp48_sqr_basic +#undef fp48_sqr_lazyr +#undef fp48_sqr_cyc_basic +#undef fp48_sqr_cyc_lazyr +#undef fp48_sqr_pck_basic +#undef fp48_sqr_pck_lazyr +#undef fp48_test_cyc +#undef fp48_conv_cyc +#undef fp48_back_cyc +#undef fp48_back_cyc_sim +#undef fp48_inv +#undef fp48_inv_cyc +#undef fp48_conv_cyc +#undef fp48_frb +#undef fp48_exp +#undef fp48_exp_dig +#undef fp48_exp_cyc +#undef fp48_exp_cyc_sps +#undef fp48_pck +#undef fp48_upk + +#define fp48_copy PREFIX(fp48_copy) +#define fp48_zero PREFIX(fp48_zero) +#define fp48_is_zero PREFIX(fp48_is_zero) +#define fp48_rand PREFIX(fp48_rand) +#define fp48_print PREFIX(fp48_print) +#define fp48_size_bin PREFIX(fp48_size_bin) +#define fp48_read_bin PREFIX(fp48_read_bin) +#define fp48_write_bin PREFIX(fp48_write_bin) +#define fp48_cmp PREFIX(fp48_cmp) +#define fp48_cmp_dig PREFIX(fp48_cmp_dig) +#define fp48_set_dig PREFIX(fp48_set_dig) +#define fp48_add PREFIX(fp48_add) +#define fp48_sub PREFIX(fp48_sub) +#define fp48_neg PREFIX(fp48_neg) +#define fp48_dbl PREFIX(fp48_dbl) +#define fp48_mul_unr PREFIX(fp48_mul_unr) +#define fp48_mul_basic PREFIX(fp48_mul_basic) +#define fp48_mul_lazyr PREFIX(fp48_mul_lazyr) +#define fp48_mul_art PREFIX(fp48_mul_art) +#define fp48_mul_dxs PREFIX(fp48_mul_dxs) +#define fp48_sqr_unr PREFIX(fp48_sqr_unr) +#define fp48_sqr_basic PREFIX(fp48_sqr_basic) +#define fp48_sqr_lazyr PREFIX(fp48_sqr_lazyr) +#define fp48_sqr_cyc_basic PREFIX(fp48_sqr_cyc_basic) +#define fp48_sqr_cyc_lazyr PREFIX(fp48_sqr_cyc_lazyr) +#define fp48_sqr_pck_basic PREFIX(fp48_sqr_pck_basic) +#define fp48_sqr_pck_lazyr PREFIX(fp48_sqr_pck_lazyr) +#define fp48_test_cyc PREFIX(fp48_test_cyc) +#define fp48_conv_cyc PREFIX(fp48_conv_cyc) +#define fp48_back_cyc PREFIX(fp48_back_cyc) +#define fp48_back_cyc_sim PREFIX(fp48_back_cyc_sim) +#define fp48_inv PREFIX(fp48_inv) +#define fp48_inv_cyc PREFIX(fp48_inv_cyc) +#define fp48_conv_cyc PREFIX(fp48_conv_cyc) +#define fp48_frb PREFIX(fp48_frb) +#define fp48_exp PREFIX(fp48_exp) +#define fp48_exp_dig PREFIX(fp48_exp_dig) +#define fp48_exp_cyc PREFIX(fp48_exp_cyc) +#define fp48_exp_cyc_sps PREFIX(fp48_exp_cyc_sps) +#define fp48_pck PREFIX(fp48_pck) +#define fp48_upk PREFIX(fp48_upk) + +#undef fp54_copy +#undef fp54_zero +#undef fp54_is_zero +#undef fp54_rand +#undef fp54_print +#undef fp54_size_bin +#undef fp54_read_bin +#undef fp54_write_bin +#undef fp54_cmp +#undef fp54_cmp_dig +#undef fp54_set_dig +#undef fp54_add +#undef fp54_sub +#undef fp54_neg +#undef fp54_dbl +#undef fp54_mul_unr +#undef fp54_mul_basic +#undef fp54_mul_lazyr +#undef fp54_mul_art +#undef fp54_mul_dxs +#undef fp54_sqr_unr +#undef fp54_sqr_basic +#undef fp54_sqr_lazyr +#undef fp54_sqr_cyc_basic +#undef fp54_sqr_cyc_lazyr +#undef fp54_sqr_pck_basic +#undef fp54_sqr_pck_lazyr +#undef fp54_test_cyc +#undef fp54_conv_cyc +#undef fp54_back_cyc +#undef fp54_back_cyc_sim +#undef fp54_inv +#undef fp54_inv_cyc +#undef fp54_conv_cyc +#undef fp54_frb +#undef fp54_exp +#undef fp54_exp_dig +#undef fp54_exp_cyc +#undef fp54_exp_cyc_sps +#undef fp54_pck +#undef fp54_upk + +#define fp54_copy PREFIX(fp54_copy) +#define fp54_zero PREFIX(fp54_zero) +#define fp54_is_zero PREFIX(fp54_is_zero) +#define fp54_rand PREFIX(fp54_rand) +#define fp54_print PREFIX(fp54_print) +#define fp54_size_bin PREFIX(fp54_size_bin) +#define fp54_read_bin PREFIX(fp54_read_bin) +#define fp54_write_bin PREFIX(fp54_write_bin) +#define fp54_cmp PREFIX(fp54_cmp) +#define fp54_cmp_dig PREFIX(fp54_cmp_dig) +#define fp54_set_dig PREFIX(fp54_set_dig) +#define fp54_add PREFIX(fp54_add) +#define fp54_sub PREFIX(fp54_sub) +#define fp54_neg PREFIX(fp54_neg) +#define fp54_dbl PREFIX(fp54_dbl) +#define fp54_mul_unr PREFIX(fp54_mul_unr) +#define fp54_mul_basic PREFIX(fp54_mul_basic) +#define fp54_mul_lazyr PREFIX(fp54_mul_lazyr) +#define fp54_mul_art PREFIX(fp54_mul_art) +#define fp54_mul_dxs PREFIX(fp54_mul_dxs) +#define fp54_sqr_unr PREFIX(fp54_sqr_unr) +#define fp54_sqr_basic PREFIX(fp54_sqr_basic) +#define fp54_sqr_lazyr PREFIX(fp54_sqr_lazyr) +#define fp54_sqr_cyc_basic PREFIX(fp54_sqr_cyc_basic) +#define fp54_sqr_cyc_lazyr PREFIX(fp54_sqr_cyc_lazyr) +#define fp54_sqr_pck_basic PREFIX(fp54_sqr_pck_basic) +#define fp54_sqr_pck_lazyr PREFIX(fp54_sqr_pck_lazyr) +#define fp54_test_cyc PREFIX(fp54_test_cyc) +#define fp54_conv_cyc PREFIX(fp54_conv_cyc) +#define fp54_back_cyc PREFIX(fp54_back_cyc) +#define fp54_back_cyc_sim PREFIX(fp54_back_cyc_sim) +#define fp54_inv PREFIX(fp54_inv) +#define fp54_inv_cyc PREFIX(fp54_inv_cyc) +#define fp54_conv_cyc PREFIX(fp54_conv_cyc) +#define fp54_frb PREFIX(fp54_frb) +#define fp54_exp PREFIX(fp54_exp) +#define fp54_exp_dig PREFIX(fp54_exp_dig) +#define fp54_exp_cyc PREFIX(fp54_exp_cyc) +#define fp54_exp_cyc_sps PREFIX(fp54_exp_cyc_sps) +#define fp54_pck PREFIX(fp54_pck) +#define fp54_upk PREFIX(fp54_upk) + +#undef fb2_mul + #undef fb2_mul_nor +#undef fb2_sqr +#undef fb2_slv +#undef fb2_inv + +#define fb2_mul PREFIX(fb2_mul) + #define fb2_mul_nor PREFIX(fb2_mul_nor) +#define fb2_sqr PREFIX(fb2_sqr) +#define fb2_slv PREFIX(fb2_slv) +#define fb2_inv PREFIX(fb2_inv) + + + +#undef pp_map_init +#undef pp_map_clean +#undef pp_add_k2_basic +#undef pp_add_k2_projc_basic +#undef pp_add_k2_projc_lazyr +#undef pp_add_k8_basic +#undef pp_add_k8_projc_basic +#undef pp_add_k8_projc_lazyr +#undef pp_add_k12_basic +#undef pp_add_k12_projc_basic +#undef pp_add_k12_projc_lazyr +#undef pp_add_lit_k12 +#undef pp_add_k48_basic +#undef pp_add_k48_projc +#undef pp_add_k54_basic +#undef pp_add_k54_projc +#undef pp_dbl_k2_basic +#undef pp_dbl_k2_projc_basic +#undef pp_dbl_k2_projc_lazyr +#undef pp_dbl_k8_basic +#undef pp_dbl_k8_projc_basic +#undef pp_dbl_k8_projc_lazyr +#undef pp_dbl_k12_basic +#undef pp_dbl_k12_projc_basic +#undef pp_dbl_k12_projc_lazyr +#undef pp_dbl_k48_basic +#undef pp_dbl_k48_projc +#undef pp_dbl_k54_basic +#undef pp_dbl_k54_projc +#undef pp_dbl_lit_k12 +#undef pp_exp_k2 +#undef pp_exp_k8 +#undef pp_exp_k12 +#undef pp_exp_k48 +#undef pp_exp_k54 +#undef pp_norm_k2 +#undef pp_norm_k8 +#undef pp_norm_k12 +#undef pp_map_tatep_k2 +#undef pp_map_sim_tatep_k2 +#undef pp_map_weilp_k2 +#undef pp_map_oatep_k8 +#undef pp_map_sim_weilp_k2 +#undef pp_map_tatep_k12 +#undef pp_map_sim_tatep_k12 +#undef pp_map_weilp_k12 +#undef pp_map_sim_weilp_k12 +#undef pp_map_oatep_k12 +#undef pp_map_sim_oatep_k12 +#undef pp_map_k48 +#undef pp_map_k54 + +#define pp_map_init PREFIX(pp_map_init) +#define pp_map_clean PREFIX(pp_map_clean) +#define pp_add_k2_basic PREFIX(pp_add_k2_basic) +#define pp_add_k2_projc_basic PREFIX(pp_add_k2_projc_basic) +#define pp_add_k2_projc_lazyr PREFIX(pp_add_k2_projc_lazyr) +#define pp_add_k8_basic PREFIX(pp_add_k8_basic) +#define pp_add_k8_projc_basic PREFIX(pp_add_k8_projc_basic) +#define pp_add_k8_projc_lazyr PREFIX(pp_add_k8_projc_lazyr) +#define pp_add_k12_basic PREFIX(pp_add_k12_basic) +#define pp_add_k12_projc_basic PREFIX(pp_add_k12_projc_basic) +#define pp_add_k12_projc_lazyr PREFIX(pp_add_k12_projc_lazyr) +#define pp_add_lit_k12 PREFIX(pp_add_lit_k12) +#define pp_add_k48_basic PREFIX(pp_add_k48_basic) +#define pp_add_k48_projc PREFIX(pp_add_k48_projc) +#define pp_add_k54_basic PREFIX(pp_add_k54_basic) +#define pp_add_k54_projc PREFIX(pp_add_k54_projc) +#define pp_dbl_k2_basic PREFIX(pp_dbl_k2_basic) +#define pp_dbl_k2_projc_basic PREFIX(pp_dbl_k2_projc_basic) +#define pp_dbl_k2_projc_lazyr PREFIX(pp_dbl_k2_projc_lazyr) +#define pp_dbl_k8_basic PREFIX(pp_dbl_k8_basic) +#define pp_dbl_k8_projc_basic PREFIX(pp_dbl_k8_projc_basic) +#define pp_dbl_k8_projc_lazyr PREFIX(pp_dbl_k8_projc_lazyr) +#define pp_dbl_k12_basic PREFIX(pp_dbl_k12_basic) +#define pp_dbl_k12_projc_basic PREFIX(pp_dbl_k12_projc_basic) +#define pp_dbl_k12_projc_lazyr PREFIX(pp_dbl_k12_projc_lazyr) +#define pp_dbl_k48_basic PREFIX(pp_dbl_k48_basic) +#define pp_dbl_k48_projc PREFIX(pp_dbl_k48_projc) +#define pp_dbl_k54_basic PREFIX(pp_dbl_k54_basic) +#define pp_dbl_k54_projc PREFIX(pp_dbl_k54_projc) +#define pp_dbl_lit_k12 PREFIX(pp_dbl_lit_k12) +#define pp_exp_k2 PREFIX(pp_exp_k2) +#define pp_exp_k8 PREFIX(pp_exp_k8) +#define pp_exp_k12 PREFIX(pp_exp_k12) +#define pp_exp_k48 PREFIX(pp_exp_k48) +#define pp_exp_k54 PREFIX(pp_exp_k54) +#define pp_norm_k2 PREFIX(pp_norm_k2) +#define pp_norm_k8 PREFIX(pp_norm_k8) +#define pp_norm_k12 PREFIX(pp_norm_k12) +#define pp_map_tatep_k2 PREFIX(pp_map_tatep_k2) +#define pp_map_sim_tatep_k2 PREFIX(pp_map_sim_tatep_k2) +#define pp_map_weilp_k2 PREFIX(pp_map_weilp_k2) +#define pp_map_oatep_k8 PREFIX(pp_map_oatep_k8) +#define pp_map_sim_weilp_k2 PREFIX(pp_map_sim_weilp_k2) +#define pp_map_tatep_k12 PREFIX(pp_map_tatep_k12) +#define pp_map_sim_tatep_k12 PREFIX(pp_map_sim_tatep_k12) +#define pp_map_weilp_k12 PREFIX(pp_map_weilp_k12) +#define pp_map_sim_weilp_k12 PREFIX(pp_map_sim_weilp_k12) +#define pp_map_oatep_k12 PREFIX(pp_map_oatep_k12) +#define pp_map_sim_oatep_k12 PREFIX(pp_map_sim_oatep_k12) +#define pp_map_k48 PREFIX(pp_map_k48) +#define pp_map_k54 PREFIX(pp_map_k54) + +#undef rsa_t +#undef rabin_t +#undef bdpe_t +#undef sokaka_t +#define rsa_t PREFIX(rsa_t) +#define rabin_t PREFIX(rabin_t) +#define bdpe_t PREFIX(bdpe_t) +#define sokaka_t PREFIX(sokaka_t) + +#undef cp_rsa_gen_basic +#undef cp_rsa_gen_quick +#undef cp_rsa_enc +#undef cp_rsa_dec_basic +#undef cp_rsa_dec_quick +#undef cp_rsa_sig_basic +#undef cp_rsa_sig_quick +#undef cp_rsa_ver +#undef cp_rabin_gen +#undef cp_rabin_enc +#undef cp_rabin_dec +#undef cp_bdpe_gen +#undef cp_bdpe_enc +#undef cp_bdpe_dec +#undef cp_phpe_gen +#undef cp_phpe_enc +#undef cp_phpe_dec +#undef cp_ecdh_gen +#undef cp_ecdh_key +#undef cp_ecmqv_gen +#undef cp_ecmqv_key +#undef cp_ecies_gen +#undef cp_ecies_enc +#undef cp_ecies_dec +#undef cp_ecdsa_gen +#undef cp_ecdsa_sig +#undef cp_ecdsa_ver +#undef cp_ecss_gen +#undef cp_ecss_sig +#undef cp_ecss_ver +#undef cp_sokaka_gen +#undef cp_sokaka_gen_prv +#undef cp_sokaka_key +#undef cp_bgn_gen +#undef cp_bgn_enc1 +#undef cp_bgn_dec1 +#undef cp_bgn_enc2 +#undef cp_bgn_dec2 +#undef cp_bgn_add +#undef cp_bgn_mul +#undef cp_bgn_dec +#undef cp_ibe_gen +#undef cp_ibe_gen_prv +#undef cp_ibe_enc +#undef cp_ibe_dec +#undef cp_bls_gen +#undef cp_bls_sig +#undef cp_bls_ver +#undef cp_bbs_gen +#undef cp_bbs_sig +#undef cp_bbs_ver +#undef cp_cls_gen +#undef cp_cls_sig +#undef cp_cls_ver +#undef cp_cli_gen +#undef cp_cli_sig +#undef cp_cli_ver +#undef cp_clb_gen +#undef cp_clb_sig +#undef cp_clb_ver +#undef cp_pss_gen +#undef cp_pss_sig +#undef cp_pss_ver +#undef cp_psb_gen +#undef cp_psb_sig +#undef cp_psb_ver +#undef cp_zss_gen +#undef cp_zss_sig +#undef cp_zss_ver +#undef cp_vbnn_gen +#undef cp_vbnn_gen_prv +#undef cp_vbnn_sig +#undef cp_vbnn_ver +#undef cp_cmlhs_init +#undef cp_cmlhs_gen +#undef cp_cmlhs_sig +#undef cp_cmlhs_fun +#undef cp_cmlhs_evl +#undef cp_cmlhs_ver +#undef cp_mklhs_gen +#undef cp_mklhs_sig +#undef cp_mklhs_fun +#undef cp_mklhs_evl +#undef cp_mklhs_ver +#undef cp_mklhs_off +#undef cp_mklhs_onv + +#define cp_rsa_gen_basic PREFIX(cp_rsa_gen_basic) +#define cp_rsa_gen_quick PREFIX(cp_rsa_gen_quick) +#define cp_rsa_enc PREFIX(cp_rsa_enc) +#define cp_rsa_dec_basic PREFIX(cp_rsa_dec_basic) +#define cp_rsa_dec_quick PREFIX(cp_rsa_dec_quick) +#define cp_rsa_sig_basic PREFIX(cp_rsa_sig_basic) +#define cp_rsa_sig_quick PREFIX(cp_rsa_sig_quick) +#define cp_rsa_ver PREFIX(cp_rsa_ver) +#define cp_rabin_gen PREFIX(cp_rabin_gen) +#define cp_rabin_enc PREFIX(cp_rabin_enc) +#define cp_rabin_dec PREFIX(cp_rabin_dec) +#define cp_bdpe_gen PREFIX(cp_bdpe_gen) +#define cp_bdpe_enc PREFIX(cp_bdpe_enc) +#define cp_bdpe_dec PREFIX(cp_bdpe_dec) +#define cp_phpe_gen PREFIX(cp_phpe_gen) +#define cp_phpe_enc PREFIX(cp_phpe_enc) +#define cp_phpe_dec PREFIX(cp_phpe_dec) +#define cp_ecdh_gen PREFIX(cp_ecdh_gen) +#define cp_ecdh_key PREFIX(cp_ecdh_key) +#define cp_ecmqv_gen PREFIX(cp_ecmqv_gen) +#define cp_ecmqv_key PREFIX(cp_ecmqv_key) +#define cp_ecies_gen PREFIX(cp_ecies_gen) +#define cp_ecies_enc PREFIX(cp_ecies_enc) +#define cp_ecies_dec PREFIX(cp_ecies_dec) +#define cp_ecdsa_gen PREFIX(cp_ecdsa_gen) +#define cp_ecdsa_sig PREFIX(cp_ecdsa_sig) +#define cp_ecdsa_ver PREFIX(cp_ecdsa_ver) +#define cp_ecss_gen PREFIX(cp_ecss_gen) +#define cp_ecss_sig PREFIX(cp_ecss_sig) +#define cp_ecss_ver PREFIX(cp_ecss_ver) +#define cp_sokaka_gen PREFIX(cp_sokaka_gen) +#define cp_sokaka_gen_prv PREFIX(cp_sokaka_gen_prv) +#define cp_sokaka_key PREFIX(cp_sokaka_key) +#define cp_bgn_gen PREFIX(cp_bgn_gen) +#define cp_bgn_enc1 PREFIX(cp_bgn_enc1) +#define cp_bgn_dec1 PREFIX(cp_bgn_dec1) +#define cp_bgn_enc2 PREFIX(cp_bgn_enc2) +#define cp_bgn_dec2 PREFIX(cp_bgn_dec2) +#define cp_bgn_add PREFIX(cp_bgn_add) +#define cp_bgn_mul PREFIX(cp_bgn_mul) +#define cp_bgn_dec PREFIX(cp_bgn_dec) +#define cp_ibe_gen PREFIX(cp_ibe_gen) +#define cp_ibe_gen_prv PREFIX(cp_ibe_gen_prv) +#define cp_ibe_enc PREFIX(cp_ibe_enc) +#define cp_ibe_dec PREFIX(cp_ibe_dec) +#define cp_bls_gen PREFIX(cp_bls_gen) +#define cp_bls_sig PREFIX(cp_bls_sig) +#define cp_bls_ver PREFIX(cp_bls_ver) +#define cp_bbs_gen PREFIX(cp_bbs_gen) +#define cp_bbs_sig PREFIX(cp_bbs_sig) +#define cp_bbs_ver PREFIX(cp_bbs_ver) +#define cp_cls_gen PREFIX(cp_cls_gen) +#define cp_cls_sig PREFIX(cp_cls_sig) +#define cp_cls_ver PREFIX(cp_cls_ver) +#define cp_cli_gen PREFIX(cp_cli_gen) +#define cp_cli_sig PREFIX(cp_cli_sig) +#define cp_cli_ver PREFIX(cp_cli_ver) +#define cp_clb_gen PREFIX(cp_clb_gen) +#define cp_clb_sig PREFIX(cp_clb_sig) +#define cp_clb_ver PREFIX(cp_clb_ver) +#define cp_pss_gen PREFIX(cp_pss_gen) +#define cp_pss_sig PREFIX(cp_pss_sig) +#define cp_pss_ver PREFIX(cp_pss_ver) +#define cp_psb_gen PREFIX(cp_psb_gen) +#define cp_psb_sig PREFIX(cp_psb_sig) +#define cp_psb_ver PREFIX(cp_psb_ver) +#define cp_zss_gen PREFIX(cp_zss_gen) +#define cp_zss_sig PREFIX(cp_zss_sig) +#define cp_zss_ver PREFIX(cp_zss_ver) +#define cp_vbnn_gen PREFIX(cp_vbnn_gen) +#define cp_vbnn_gen_prv PREFIX(cp_vbnn_gen_prv) +#define cp_vbnn_sig PREFIX(cp_vbnn_sig) +#define cp_vbnn_ver PREFIX(cp_vbnn_ver) +#define cp_cmlhs_init PREFIX(cp_cmlhs_init) +#define cp_cmlhs_gen PREFIX(cp_cmlhs_gen) +#define cp_cmlhs_sig PREFIX(cp_cmlhs_sig) +#define cp_cmlhs_fun PREFIX(cp_cmlhs_fun) +#define cp_cmlhs_evl PREFIX(cp_cmlhs_evl) +#define cp_cmlhs_ver PREFIX(cp_cmlhs_ver) +#define cp_mklhs_gen PREFIX(cp_mklhs_gen) +#define cp_mklhs_sig PREFIX(cp_mklhs_sig) +#define cp_mklhs_fun PREFIX(cp_mklhs_fun) +#define cp_mklhs_evl PREFIX(cp_mklhs_evl) +#define cp_mklhs_ver PREFIX(cp_mklhs_ver) +#define cp_mklhs_off PREFIX(cp_mklhs_off) +#define cp_mklhs_onv PREFIX(cp_mklhs_onv) + +#undef md_map_sh224 +#undef md_map_sh256 +#undef md_map_sh384 +#undef md_map_sh512 +#undef md_map_b2s160 +#undef md_map_b2s256 +#undef md_kdf +#undef md_mgf +#undef md_hmac +#undef md_xmd_sh224 +#undef md_xmd_sh256 +#undef md_xmd_sh384 +#undef md_xmd_sh512 + +#define md_map_sh224 PREFIX(md_map_sh224) +#define md_map_sh256 PREFIX(md_map_sh256) +#define md_map_sh384 PREFIX(md_map_sh384) +#define md_map_sh512 PREFIX(md_map_sh512) +#define md_map_b2s160 PREFIX(md_map_b2s160) +#define md_map_b2s256 PREFIX(md_map_b2s256) +#define md_kdf PREFIX(md_kdf) +#define md_mgf PREFIX(md_mgf) +#define md_hmac PREFIX(md_hmac) +#define md_xmd_sh224 PREFIX(md_xmd_sh224) +#define md_xmd_sh256 PREFIX(md_xmd_sh256) +#define md_xmd_sh384 PREFIX(md_xmd_sh384) +#define md_xmd_sh512 PREFIX(md_xmd_sh512) + +#endif /* LABEL */ + +#endif /* !RLC_LABEL_H */ diff --git a/bls/contrib/relic/include/relic_md.h b/bls/contrib/relic/include/relic_md.h new file mode 100644 index 00000000..d8d1bce4 --- /dev/null +++ b/bls/contrib/relic/include/relic_md.h @@ -0,0 +1,274 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 . + */ + +/** + * @defgroup md Hash functions + */ + +/** + * @file + * + * Interface of the module for computing hash functions. + * + * @ingroup md + */ + +#ifndef RLC_MD_H +#define RLC_MD_H + +#include "relic_conf.h" +#include "relic_types.h" +#include "relic_label.h" + +/*============================================================================*/ +/* Constant definitions */ +/*============================================================================*/ + +enum { + /** Hash length for SHA-224 function. */ + RLC_MD_LEN_SH224 = 28, + /** Hash length for SHA-256 function. */ + RLC_MD_LEN_SH256 = 32, + /** Hash length for SHA-384 function. */ + RLC_MD_LEN_SH384 = 48, + /** Hash length for SHA-512 function. */ + RLC_MD_LEN_SH512 = 64, + /** Hash length for BLAKE2s-160 function. */ + RLC_MD_LEN_B2S160 = 20, + /** Hash length for BLAKE2s-256 function. */ + RLC_MD_LEN_B2S256 = 32 +}; + +/** + * Length in bytes of default hash function output. + */ +#if MD_MAP == SH224 +#define RLC_MD_LEN RLC_MD_LEN_SH224 +#elif MD_MAP == SH256 +#define RLC_MD_LEN RLC_MD_LEN_SH256 +#elif MD_MAP == SH384 +#define RLC_MD_LEN RLC_MD_LEN_SH384 +#elif MD_MAP == SH512 +#define RLC_MD_LEN RLC_MD_LEN_SH512 +#elif MD_MAP == B2S160 +#define RLC_MD_LEN RLC_MD_LEN_B2S160 +#elif MD_MAP == B2S256 +#define RLC_MD_LEN RLC_MD_LEN_B2S256 +#endif + +/*============================================================================*/ +/* Macro definitions */ +/*============================================================================*/ + +/** + * Maps a byte vector to a fixed-length byte vector using the chosen hash + * function. + * + * @param[out] H - the digest. + * @param[in] M - the message to hash. + * @param[in] L - the message length in bytes. + */ +#if MD_MAP == SH224 +#define md_map(H, M, L) md_map_sh224(H, M, L) +#elif MD_MAP == SH256 +#define md_map(H, M, L) md_map_sh256(H, M, L) +#elif MD_MAP == SH384 +#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 +#define md_map(H, M, L) md_map_b2s160(H, M, L) +#elif MD_MAP == BLAKE2S_256 +#define md_map(H, M, L) md_map_b2s256(H, M, L) +#endif + +/** + * Maps a byte vector and optional domain separation tag to an arbitrary-length + * pseudorandom output using the chosen hash function. + * + * @param[out] B - the output buffer. + * @param[in] BL - the requested size of the output. + * @param[in] I - the message to hash. + * @param[in] IL - the message length in bytes. + * @param[in] D - the domain separation tag. + * @param[in] DL - the domain separation tag length in bytes. + */ +#if MD_MAP == SH224 +#define md_xmd(B, BL, I, IL, D, DL) md_xmd_sh224(B, BL, I, IL, D, DL) +#elif MD_MAP == SH256 +#define md_xmd(B, BL, I, IL, D, DL) md_xmd_sh256(B, BL, I, IL, D, DL) +#elif MD_MAP == SH384 +#define md_xmd(B, BL, I, IL, D, DL) md_xmd_sh384(B, BL, I, IL, D, DL) +#elif MD_MAP == SH512 +#define md_xmd(B, BL, I, IL, D, DL) md_xmd_sh512(B, BL, I, IL, D, DL) +#endif + +/*============================================================================*/ +/* Function prototypes */ +/*============================================================================*/ + +/** + * Computes the SHA-224 hash function. + * + * @param[out] hash - the digest. + * @param[in] msg - the message to hash. + * @param[in] len - the message length in bytes. + */ +void md_map_sh224(uint8_t *hash, const uint8_t *msg, int len); + +/** + * Computes the SHA-256 hash function. + * + * @param[out] hash - the digest. + * @param[in] msg - the message to hash. + * @param[in] len - the message length in bytes. + */ +void md_map_sh256(uint8_t *hash, const uint8_t *msg, int len); + +/** + * Computes the SHA-384 hash function. + * + * @param[out] hash - the digest. + * @param[in] msg - the message to hash. + * @param[in] len - the message length in bytes. + */ +void md_map_sh384(uint8_t *hash, const uint8_t *msg, int len); + +/** + * Computes the SHA-512 hash function. + * + * @param[out] hash - the digest. + * @param[in] msg - the message to hash. + * @param[in] len - the message length in bytes. + */ +void md_map_sh512(uint8_t *hash, const uint8_t *msg, int len); + +/** + * Computes the BLAKE2s-160 hash function. + * + * @param[out] hash - the digest. + * @param[in] msg - the message to hash. + * @param[in] len - the message length in bytes. + */ +void md_map_b2s160(uint8_t *hash, const uint8_t *msg, int len); + +/** + * Computes the BLAKE2s-256 hash function. + * + * @param[out] hash - the digest. + * @param[in] msg - the message to hash. + * @param[in] len - the message length in bytes. + */ +void md_map_b2s256(uint8_t *hash, const uint8_t *msg, int len); + +/** + * Derives a key from shared secret material through the standardized KDF2 + * function. + * + * @param[out] key - the resulting key. + * @param[in] key_len - the intended key length in bytes. + * @param[in] in - the shared secret. + * @param[in] in_len - the length of the shared secret in bytes. + */ +void md_kdf(uint8_t *key, int key_len, const uint8_t *in, int in_len); + +/** + * Derives a mask from shared secret material through the PKCS#1 2.1 MGF1 + * function. This is the same as the standardized KDF1 key derivation function. + * + * @param[out] key - the resulting mask. + * @param[in] key_len - the intended mask length in bytes. + * @param[in] in - the shared secret. + * @param[in] in_len - the length of the shared secret in bytes. + */ +void md_mgf(uint8_t *mask, int mask_len, const uint8_t *in, int in_len); + +/** + * Computes a Message Authentication Code through HMAC. + * + * @param[out] mac - the authentication. + * @param[in] in - the date to authenticate. + * @param[in] in_len - the number of bytes to authenticate. + * @param[in] key - the cryptographic key. + * @param[in] key_len - the size of the key in bytes. + */ +void md_hmac(uint8_t *mac, const uint8_t *in, int in_len, const uint8_t *key, + int key_len); + +/** + * Map a byte vector and optional domain separation tag to an arbitrary-length + * pseudorandom output using the SHA-224 hash function. + * + * @param[out] buf - the output buffer. + * @param[in] buf_len - the requested size of the output. + * @param[in] in - the message to hash. + * @param[in] in_len - the message length in bytes. + * @param[in] dst - the domain separation tag. + * @param[in] dst_len - the domain separation tag length in bytes. + */ +void md_xmd_sh224(uint8_t *buf, int buf_len, const uint8_t *in, int in_len, + const uint8_t *dst, int dst_len); + +/** + * Map a byte vector and optional domain separation tag to an arbitrary-length + * pseudorandom output using the SHA-256 hash function. + * + * @param[out] buf - the output buffer. + * @param[in] buf_len - the requested size of the output. + * @param[in] in - the message to hash. + * @param[in] in_len - the message length in bytes. + * @param[in] dst - the domain separation tag. + * @param[in] dst_len - the domain separation tag length in bytes. + */ +void md_xmd_sh256(uint8_t *buf, int buf_len, const uint8_t *in, int in_len, + const uint8_t *dst, int dst_len); + +/** + * Map a byte vector and optional domain separation tag to an arbitrary-length + * pseudorandom output using the SHA-384 hash function. + * + * @param[out] buf - the output buffer. + * @param[in] buf_len - the requested size of the output. + * @param[in] in - the message to hash. + * @param[in] in_len - the message length in bytes. + * @param[in] dst - the domain separation tag. + * @param[in] dst_len - the domain separation tag length in bytes. + */ +void md_xmd_sh384(uint8_t *buf, int buf_len, const uint8_t *in, int in_len, + const uint8_t *dst, int dst_len); + +/** + * Map a byte vector and optional domain separation tag to an arbitrary-length + * pseudorandom output using the SHA-512 hash function. + * + * @param[out] buf - the output buffer. + * @param[in] buf_len - the requested size of the output. + * @param[in] in - the message to hash. + * @param[in] in_len - the message length in bytes. + * @param[in] dst - the domain separation tag. + * @param[in] dst_len - the domain separation tag length in bytes. + */ +void md_xmd_sh512(uint8_t *buf, int buf_len, const uint8_t *in, int in_len, + const uint8_t *dst, int dst_len); + +#endif /* !RLC_MD_H */ diff --git a/bls/contrib/relic/include/relic_pc.h b/bls/contrib/relic/include/relic_pc.h new file mode 100644 index 00000000..c673aae8 --- /dev/null +++ b/bls/contrib/relic/include/relic_pc.h @@ -0,0 +1,895 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 . + */ + +/** + * @defgroup pc Pairing-based cryptography + */ + +/** + * @file + * + * Abstractions of pairing computation useful to protocol implementors. + * + * @ingroup pc + */ + +#ifndef RLC_PC_H +#define RLC_PC_H + +#include "relic_fbx.h" +#include "relic_ep.h" +#include "relic_eb.h" +#include "relic_pp.h" +#include "relic_bn.h" +#include "relic_util.h" +#include "relic_conf.h" +#include "relic_types.h" + +/*============================================================================*/ +/* Constant definitions */ +/*============================================================================*/ + +/** + * Prefix for function mappings. + */ +/** @{ */ +#if FP_PRIME < 1536 +#define G1_LOWER ep_ +#define G1_UPPER EP +#define G2_LOWER ep2_ +#define G2_UPPER EP +#define GT_LOWER fp12_ +#define PC_LOWER pp_ +#else +#define G1_LOWER ep_ +#define G1_UPPER EP +#define G2_LOWER ep_ +#define G2_UPPER EP +#define GT_LOWER fp2_ +#define PC_LOWER pp_ +#endif +/** @} */ + +/** + * Represents the size in bytes of the order of G_1 and G_2. + */ +#define RLC_PC_BYTES RLC_FP_BYTES + +/** + * Represents a G_1 precomputed table. + */ +#define RLC_G1_TABLE RLC_CAT(RLC_CAT(RLC_, G1_UPPER), _TABLE) + +/** + * Represents a G_2 precomputed table. + */ +#define RLC_G2_TABLE RLC_CAT(RLC_CAT(RLC_, G2_UPPER), _TABLE) + +/*============================================================================*/ +/* Type definitions */ +/*============================================================================*/ + +/** + * Represents a G_1 element. + */ +typedef RLC_CAT(G1_LOWER, t) g1_t; + +/** + * Represents a G_1 element with automatic allocation. + */ +typedef RLC_CAT(G1_LOWER, st) g1_st; + +/** + * Represents a G_2 element. + */ +typedef RLC_CAT(G2_LOWER, t) g2_t; + +/** + * Represents a G_2 element with automatic allocation. + */ +typedef RLC_CAT(G2_LOWER, st) g2_st; + +/** + * Represents a G_T element. + */ +typedef RLC_CAT(GT_LOWER, t) gt_t; + +/*============================================================================*/ +/* Macro definitions */ +/*============================================================================*/ + +/** + * Initializes a G_1 element with a null value. + * + * @param[out] A - the element to initialize. + */ +#define g1_null(A) RLC_CAT(G1_LOWER, null)(A) + +/** + * Initializes a G_2 element with a null value. + * + * @param[out] A - the element to initialize. + */ +#define g2_null(A) RLC_CAT(G2_LOWER, null)(A) + +/** + * Initializes a G_T element with a null value. + * + * @param[out] A - the element to initialize. + */ +#define gt_null(A) RLC_CAT(GT_LOWER, null)(A) + +/** + * Calls a function to allocate a G_1 element. + * + * @param[out] A - the new element. + * @throw ERR_NO_MEMORY - if there is no available memory. + */ +#define g1_new(A) RLC_CAT(G1_LOWER, new)(A) + +/** + * Calls a function to allocate a G_2 element. + * + * @param[out] A - the new element. + * @throw ERR_NO_MEMORY - if there is no available memory. + */ +#define g2_new(A) RLC_CAT(G2_LOWER, new)(A) + +/** + * Calls a function to allocate a G_T element. + * + * @param[out] A - the new element. + * @throw ERR_NO_MEMORY - if there is no available memory. + */ +#define gt_new(A) RLC_CAT(GT_LOWER, new)(A) + +/** + * Calls a function to clean and free a G_1 element. + * + * @param[out] A - the element to clean and free. + */ +#define g1_free(A) RLC_CAT(G1_LOWER, free)(A) + +/** + * Calls a function to clean and free a G_2 element. + * + * @param[out] A - the element to clean and free. + */ +#define g2_free(A) RLC_CAT(G2_LOWER, free)(A) + +/** + * Calls a function to clean and free a G_T element. + * + * @param[out] A - the element to clean and free. + */ +#define gt_free(A) RLC_CAT(GT_LOWER, free)(A) + +/** + * Returns the generator of the group G_1. + * + * @param[out] G - the returned generator. + */ +#define g1_get_gen(G) RLC_CAT(G1_LOWER, curve_get_gen)(G) + +/** + * Returns the generator of the group G_2. + * + * @param[out] G - the returned generator. + */ +#define g2_get_gen(G) RLC_CAT(G2_LOWER, curve_get_gen)(G) + +/** + * Returns the order of the group G_1. + * + * @param[out] N 0 the returned order. + */ +#define g1_get_ord(N) RLC_CAT(G1_LOWER, curve_get_ord)(N) + +/** + * Returns the order of the group G_2. + * + * @param[out] N 0 the returned order. + */ +#define g2_get_ord(N) RLC_CAT(G2_LOWER, curve_get_ord)(N) + +/** + * Returns the order of the group G_T. + * + * @param[out] N 0 the returned order. + */ +#define gt_get_ord(N) RLC_CAT(G1_LOWER, curve_get_ord)(N) + +/** + * Configures some set of curve parameters for the current security level. + */ +#define pc_param_set_any() ep_param_set_any_pairf() + +/** + * Returns the type of the configured pairing. + * + * @{ + */ +#if FP_PRIME < 1536 +#define pc_map_is_type1() (0) +#define pc_map_is_type3() (1) +#else +#define pc_map_is_type1() (1) +#define pc_map_is_type3() (0) +#endif +/** + * @} + */ + +/** + * Prints the current configured binary elliptic curve. + */ +#define pc_param_print() RLC_CAT(G1_LOWER, param_print)() + +/** + * Returns the current security level. + */ +#define pc_param_level() RLC_CAT(G1_LOWER, param_level)() + +/** + * Tests if a G_1 element is the unity. + * + * @param[in] P - the element to test. + * @return 1 if the element it the unity, 0 otherwise. + */ +#define g1_is_infty(P) RLC_CAT(G1_LOWER, is_infty)(P) + +/** + * Tests if a G_2 element is the unity. + * + * @param[in] P - the element to test. + * @return 1 if the element it the unity, 0 otherwise. + */ +#define g2_is_infty(P) RLC_CAT(G2_LOWER, is_infty)(P) + +/** + * Tests if a G_T element is the unity. + * + * @param[in] A - the element to test. + * @return 1 if the element it the unity, 0 otherwise. + */ +#define gt_is_unity(A) (RLC_CAT(GT_LOWER, cmp_dig)(A, 1) == RLC_EQ) + +/** + * Assigns a G_1 element to the unity. + * + * @param[out] P - the element to assign. + */ +#define g1_set_infty(P) RLC_CAT(G1_LOWER, set_infty)(P) + +/** + * Assigns a G_2 element to the unity. + * + * @param[out] P - the element to assign. + */ +#define g2_set_infty(P) RLC_CAT(G2_LOWER, set_infty)(P) + +/** + * Assigns a G_T element to zero. + * + * @param[out] A - the element to assign. + */ +#define gt_zero(A) RLC_CAT(GT_LOWER, zero)(A) + +/** + * Assigns a G_T element to the unity. + * + * @param[out] A - the element to assign. + */ +#define gt_set_unity(A) RLC_CAT(GT_LOWER, set_dig)(A, 1) + +/** + * Copies the second argument to the first argument. + * + * @param[out] R - the result. + * @param[in] P - the element to copy. + */ +#define g1_copy(R, P) RLC_CAT(G1_LOWER, copy)(R, P) + +/** + * Copies the second argument to the first argument. + * + * @param[out] R - the result. + * @param[in] P - the element to copy. + */ +#define g2_copy(R, P) RLC_CAT(G2_LOWER, copy)(R, P) + +/** + * Copies the second argument to the first argument. + * + * @param[out] C - the result. + * @param[in] A - the element to copy. + */ +#define gt_copy(C, A) RLC_CAT(GT_LOWER, copy)(C, A) + +/** + * Compares two elements from G_1. + * + * @param[in] P - the first element. + * @param[in] Q - the second element. + * @return RLC_EQ if P == Q and RLC_NE if P != Q. + */ +#define g1_cmp(P, Q) RLC_CAT(G1_LOWER, cmp)(P, Q) + +/** + * Compares two elements from G_2. + * + * @param[in] P - the first element. + * @param[in] Q - the second element. + * @return RLC_EQ if P == Q and RLC_NE if P != Q. + */ +#define g2_cmp(P, Q) RLC_CAT(G2_LOWER, cmp)(P, Q) + +/** + * Compares two elements from G_T. + * + * @param[in] A - the first element. + * @param[in] B - the second element. + * @return RLC_EQ if A == B and RLC_NE if P != Q. + */ +#define gt_cmp(A, B) RLC_CAT(GT_LOWER, cmp)(A, B) + +/** + * Compares a G_T element with a digit. + * + * @param[in] A - the G_T element. + * @param[in] D - the digit. + * @return RLC_EQ if A == D and RLC_NE if A != D. + */ +#define gt_cmp_dig(A, D) RLC_CAT(GT_LOWER, cmp_dig)(A, D) + +/** + * Assigns a random value to a G_1 element. + * + * @param[out] P - the element to assign. + */ +#define g1_rand(P) RLC_CAT(G1_LOWER, rand)(P) + +/** + * Assigns a random value to a G_2 element. + * + * @param[out] P - the element to assign. + */ +#define g2_rand(P) RLC_CAT(G2_LOWER, rand)(P) + +/** + * Prints a G_1 element. + * + * @param[in] P - the element to print. + */ +#define g1_print(P) RLC_CAT(G1_LOWER, print)(P) + +/** + * Prints a G_2 element. + * + * @param[in] P - the element to print. + */ +#define g2_print(P) RLC_CAT(G2_LOWER, print)(P) + +/** + * Prints a G_T element. + * + * @param[in] A - the element to print. + */ +#define gt_print(A) RLC_CAT(GT_LOWER, print)(A) + +/** + * Returns the number of bytes necessary to store a G_1 element. + * + * @param[in] P - the element of G_1. + * @param[in] C - the flag to indicate point compression. + */ +#define g1_size_bin(P, C) RLC_CAT(G1_LOWER, size_bin)(P, C) + +/** + * Returns the number of bytes necessary to store a G_2 element. + * + * @param[in] P - the element of G_2. + * @param[in] C - the flag to indicate point compression. + */ +#define g2_size_bin(P, C) RLC_CAT(G2_LOWER, size_bin)(P, C) + +/** + * Returns the number of bytes necessary to store a G_T element. + * + * @param[in] A - the element of G_T. + * @param[in] C - the flag to indicate compression. + */ +#define gt_size_bin(A, C) RLC_CAT(GT_LOWER, size_bin)(A, C) + +/** + * Reads a G_1 element from a byte vector in big-endian format. + * + * @param[out] P - the result. + * @param[in] B - the byte vector. + * @param[in] L - the buffer capacity. + * @throw ERR_NO_BUFFER - if the buffer capacity is not sufficient. + */ +#define g1_read_bin(P, B, L) RLC_CAT(G1_LOWER, read_bin)(P, B, L) + +/** + * Reads a G_2 element from a byte vector in big-endian format. + * + * @param[out] P - the result. + * @param[in] B - the byte vector. + * @param[in] L - the buffer capacity. + * @throw ERR_NO_BUFFER - if the buffer capacity is not sufficient. + */ +#define g2_read_bin(P, B, L) RLC_CAT(G2_LOWER, read_bin)(P, B, L) + +/** + * Reads a G_T element from a byte vector in big-endian format. + * + * @param[out] A - the result. + * @param[in] B - the byte vector. + * @param[in] L - the buffer capacity. + * @throw ERR_NO_BUFFER - if the buffer capacity is not sufficient. + */ +#define gt_read_bin(A, B, L) RLC_CAT(GT_LOWER, read_bin)(A, B, L) + +/** + * Writes an optionally compressed G_1 element to a byte vector in big-endian + * format. + * + * @param[out] B - the byte vector. + * @param[in] L - the buffer capacity. + * @param[in] P - the G_1 element to write. + * @param[in] C - the flag to indicate point compression. + * @throw ERR_NO_BUFFER - if the buffer capacity is not enough. + */ +#define g1_write_bin(B, L, P, C) RLC_CAT(G1_LOWER, write_bin)(B, L, P, C) + +/** + * Writes an optionally compressed G_2 element to a byte vector in big-endian + * format. + * + * @param[out] B - the byte vector. + * @param[in] L - the buffer capacity. + * @param[in] P - the G_2 element to write. + * @param[in] C - the flag to indicate point compression. + * @throw ERR_NO_BUFFER - if the buffer capacity is not enough. + */ +#define g2_write_bin(B, L, P, C) RLC_CAT(G2_LOWER, write_bin)(B, L, P, C) + +/** + * Writes an optionally compresseds G_T element to a byte vector in big-endian + * format. + * + * @param[out] B - the byte vector. + * @param[in] L - the buffer capacity. + * @param[in] A - the G_T element to write. + * @param[in] C - the flag to indicate point compression. + * @throw ERR_NO_BUFFER - if the buffer capacity is not sufficient. + */ +#define gt_write_bin(B, L, A, C) RLC_CAT(GT_LOWER, write_bin)(B, L, A, C) + +/** + * Negates a element from G_1. Computes R = -P. + * + * @param[out] R - the result. + * @param[in] P - the element to negate. + */ +#define g1_neg(R, P) RLC_CAT(G1_LOWER, neg)(R, P) + +/** + * Negates a element from G_2. Computes R = -P. + * + * @param[out] R - the result. + * @param[in] P - the element to negate. + */ +#define g2_neg(R, P) RLC_CAT(G2_LOWER, neg)(R, P) + +/** + * Inverts a element from G_T. Computes C = 1/A. + * + * @param[out] C - the result. + * @param[in] A - the element to invert. + */ +#define gt_inv(C, A) RLC_CAT(GT_LOWER, inv_cyc)(C, A) + +/** + * Adds two elliptic elements from G_1. Computes R = P + Q. + * + * @param[out] R - the result. + * @param[in] P - the first element to add. + * @param[in] Q - the second element to add. + */ +#define g1_add(R, P, Q) RLC_CAT(G1_LOWER, add)(R, P, Q) + +/** + * Adds two elliptic elements from G_2. Computes R = P + Q. + * + * @param[out] R - the result. + * @param[in] P - the first element to add. + * @param[in] Q - the second element to add. + */ +#define g2_add(R, P, Q) RLC_CAT(G2_LOWER, add)(R, P, Q) + +/** + * Multiplies two elliptic elements from G_T. Computes C = A * B. + * + * @param[out] C - the result. + * @param[in] A - the first element to multiply. + * @param[in] B - the second element to multiply. + */ +#define gt_mul(C, A, B) RLC_CAT(GT_LOWER, mul)(C, A, B) + +/** + * Subtracts a G_1 element from another. Computes R = P - Q. + * + * @param[out] R - the result. + * @param[in] P - the first element. + * @param[in] Q - the second element. + */ +#define g1_sub(R, P, Q) RLC_CAT(G1_LOWER, sub)(R, P, Q) + +/** + * Subtracts a G_2 element from another. Computes R = P - Q. + * + * @param[out] R - the result. + * @param[in] P - the first element. + * @param[in] Q - the second element. + */ +#define g2_sub(R, P, Q) RLC_CAT(G2_LOWER, sub)(R, P, Q) + +/** + * Doubles a G_1 element. Computes R = 2P. + * + * @param[out] R - the result. + * @param[in] P - the element to double. + */ +#define g1_dbl(R, P) RLC_CAT(G1_LOWER, dbl)(R, P) + +/** + * Doubles a G_2 element. Computes R = 2P. + * + * @param[out] R - the result. + * @param[in] P - the element to double. + */ +#define g2_dbl(R, P) RLC_CAT(G2_LOWER, dbl)(R, P) + +/** + * Squares a G_T element. Computes C = A^2. + * + * @param[out] C - the result. + * @param[in] A - the element to square. + */ +#define gt_sqr(C, A) RLC_CAT(GT_LOWER, sqr)(C, A) + +/** + * Normalizes an element of G_1. + * + * @param[out] R - the result. + * @param[in] P - the element to normalize. + */ +#define g1_norm(R, P) RLC_CAT(G1_LOWER, norm)(R, P) + +/** + * Normalizes a vector of G_1 elements. + * + * @param[out] R - the result. + * @param[in] P - the elements to normalize. + * @param[in] N - the number of elements to normalize. + */ +#define g1_norm_sim(R, P, N) RLC_CAT(G1_LOWER, norm_sim)(R, P, N) + +/** + * Normalizes an element of G_2. + * + * @param[out] R - the result. + * @param[in] P - the element to normalize. + */ +#define g2_norm(R, P) RLC_CAT(G2_LOWER, norm)(R, P) + +/** + * Normalizes a vector of G_2 elements. + * + * @param[out] R - the result. + * @param[in] P - the elements to normalize. + * @param[in] N - the number of elements to normalize. + */ +#define g2_norm_sim(R, P, N) RLC_CAT(G2_LOWER, norm_sim)(R, P, N) + +/** + * Multiplies an element from G_1 by a secret scalar. Computes R = kP. + * + * @param[out] R - the result. + * @param[in] P - the element to multiply. + * @param[in] K - the secret scalar. + */ +#define g1_mul_key(R, P, K) RLC_CAT(G1_LOWER, mul_lwreg)(R, P, K) + +/** + * Multiplies an element from G_1 by a small integer. Computes R = kP. + * + * @param[out] R - the result. + * @param[in] P - the element to multiply. + * @param[in] K - the small integer. + */ +#define g1_mul_dig(R, P, K) RLC_CAT(G1_LOWER, mul_dig)(R, P, K) + +/** + * Multiplies an element from G_2 by a small integer. Computes R = kP. + * + * @param[out] R - the result. + * @param[in] P - the element to multiply. + * @param[in] K - the small integer. + */ +#define g2_mul_dig(R, P, K) RLC_CAT(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(GT_LOWER, exp_dig)(C, A, B) + +/** + * Multiplies the generator of G_1 by an integer. + * + * @param[out] R - the result. + * @param[in] K - the integer. + */ +#define g1_mul_gen(R, K) RLC_CAT(G1_LOWER, mul_gen)(R, K) + +/** + * Multiplies the generator of G_2 by an integer. + * + * @param[out] R - the result. + * @param[in] K - the integer. + */ +#define g2_mul_gen(R, K) RLC_CAT(G2_LOWER, mul_gen)(R, K) + +/** + * Builds a precomputation table for multiplying an element from G_1. + * + * @param[out] T - the precomputation table. + * @param[in] P - the element to multiply. + */ +#define g1_mul_pre(T, P) RLC_CAT(G1_LOWER, mul_pre)(T, P) + +/** + * Builds a precomputation table for multiplying an element from G_2. + * + * @param[out] T - the precomputation table. + * @param[in] P - the element to multiply. + */ +#define g2_mul_pre(T, P) RLC_CAT(G2_LOWER, mul_pre)(T, P) + +/** + * Multiplies an element from G_1 using a precomputation table. + * Computes R = kP. + * + * @param[out] R - the result. + * @param[in] T - the precomputation table. + * @param[in] K - the integer. + */ +#define g1_mul_fix(R, T, K) RLC_CAT(G1_LOWER, mul_fix)(R, T, K) + +/** + * Multiplies an element from G_2 using a precomputation table. + * Computes R = kP. + * + * @param[out] R - the result. + * @param[in] T - the precomputation table. + * @param[in] K - the integer. + */ +#define g2_mul_fix(R, T, K) RLC_CAT(G2_LOWER, mul_fix)(R, T, K) + +/** + * Multiplies simultaneously two elements from G_1. Computes R = kP + lQ. + * + * @param[out] R - the result. + * @param[out] P - the first G_1 element to multiply. + * @param[out] K - the first integer scalar. + * @param[out] L - the second G_1 element to multiply. + * @param[out] Q - the second integer scalar. + */ +#define g1_mul_sim(R, P, K, Q, L) RLC_CAT(G1_LOWER, mul_sim)(R, P, K, Q, L) + +/** + * Multiplies elements from G_1 by small scalars. Computes R = \sum k_iP_i. + * + * @param[out] R - the result. + * @param[in] P - the elements to multiply. + * @param[in] K - the small scalars. + * @param[in] L - the number of points to multiply. + */ +#define g1_mul_sim_dig(R, P, K, L) RLC_CAT(G1_LOWER, mul_sim_dig)(R, P, K, L) + +/** + * Multiplies simultaneously two elements from G_2. Computes R = kP + lQ. + * + * @param[out] R - the result. + * @param[out] P - the first G_2 element to multiply. + * @param[out] K - the first integer scalar. + * @param[out] L - the second G_2 element to multiply. + * @param[out] Q - the second integer scalar. + */ +#define g2_mul_sim(R, P, K, Q, L) RLC_CAT(G2_LOWER, mul_sim)(R, P, K, Q, L) + +/** + * Multiplies elements from G_2 by small scalars. Computes R = \sum k_iP_i. + * + * @param[out] R - the result. + * @param[in] P - the elements to multiply. + * @param[in] K - the small scalars. + * @param[in] L - the number of points to multiply. + */ +#define g2_mul_sim_dig(R, P, K, L) RLC_CAT(G2_LOWER, mul_sim_dig)(R, P, K, L) + +/** + * Multiplies simultaneously two elements from G_1, where one of the is the + * generator. Computes R = kG + lQ. + * + * @param[out] R - the result. + * @param[out] K - the first integer scalar. + * @param[out] L - the second G_1 element to multiply. + * @param[out] Q - the second integer scalar. + */ +#define g1_mul_sim_gen(R, K, Q, L) RLC_CAT(G1_LOWER, mul_sim_gen)(R, K, Q, L) + +/** + * Multiplies simultaneously two elements from G_1, where one of the is the + * generator. Computes R = kG + lQ. + * + * @param[out] R - the result. + * @param[out] K - the first integer scalar. + * @param[out] L - the second G_1 element to multiply. + * @param[out] Q - the second integer scalar. + */ +#define g2_mul_sim_gen(R, K, Q, L) RLC_CAT(G2_LOWER, mul_sim_gen)(R, K, Q, L) + +/** + * Maps a byte array to an element in G_1. + * + * @param[out] P - the result. + * @param[in] M - the byte array to map. + * @param[in] L - the array length in bytes. + */ +#define g1_map(P, M, L); RLC_CAT(G1_LOWER, map)(P, M, L) + +/** + * Maps a byte array to an element in G_2. + * + * @param[out] P - the result. + * @param[in] M - the byte array to map. + * @param[in] L - the array length in bytes. + * @param[in] H - whether to hash internally. + */ +#define g2_map(P, M, L, H); RLC_CAT(G2_LOWER, map)(P, M, L, H) + +/** + * Computes the bilinear pairing of a G_1 element and a G_2 element. Computes + * R = e(P, Q). + * + * @param[out] R - the result. + * @param[in] P - the first element. + * @param[in] Q - the second element. + */ +#if FP_PRIME < 1536 +#define pc_map(R, P, Q); RLC_CAT(PC_LOWER, map_k12)(R, P, Q) +#else +#define pc_map(R, P, Q); RLC_CAT(PC_LOWER, map_k2)(R, P, Q) +#endif + +/** + * Computes the multi-pairing of G_1 elements and G_2 elements. Computes + * R = \prod e(P_i, Q_i). + * + * @param[out] R - the result. + * @param[in] P - the first pairing arguments. + * @param[in] Q - the second pairing arguments. + * @param[in] M - the number of pairing arguments. + */ +#if FP_PRIME < 1536 +#define pc_map_sim(R, P, Q, M); RLC_CAT(PC_LOWER, map_sim_k12)(R, P, Q, M) +#else +#define pc_map_sim(R, P, Q, M); RLC_CAT(PC_LOWER, map_sim_k2)(R, P, Q, M) +#endif + +/** + * Computes the final exponentiation of the pairing. + * + * @param[out] C - the result. + * @param[in] A - the field element to exponentiate. + */ +#if FP_PRIME < 1536 +#define pc_exp(C, A); RLC_CAT(PC_LOWER, exp_k12)(C, A) +#else +#define pc_exp(C, A); RLC_CAT(PC_LOWER, exp_k2)(C, A) +#endif + +/*============================================================================*/ +/* Function prototypes */ +/*============================================================================*/ + +/** + * Assigns a random value to an element from G_T. + * + * @param[out] a - the element to assign. + */ +void gt_rand(gt_t a); + +/** + * Multiplies an element from G_1 by an integer. Computes R = kP. + * + * @param[out] r - the result. + * @param[in] p - the element to multiply. + * @param[in] k - the integer. + */ +void g1_mul(g1_t r, g1_t p, bn_t k); + +/** + * Multiplies an element from G_2 by an integer. Computes R = kP. + * + * @param[out] r - the result. + * @param[in] p - the element to multiply. + * @param[in] k - the integer. + */ +void g2_mul(g2_t r, g2_t p, bn_t k); + +/** + * Exponentiates an element from G_T by an 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(gt_t c, gt_t a, bn_t b); + + /** + * Returns the generator for the group G_T. + * + * @param[out] g - the returned generator. + */ +void gt_get_gen(gt_t g); + +/** + * Checks if an element from G_1 is valid (has the right order). + * + * @param[in] a - the element to check. + */ +int g1_is_valid(g1_t a); + +/** + * Checks if an element form G_2 is valid (has the right order). + * + * @param[in] a - the element to check. + */ +int g2_is_valid(g2_t a); + +/** + * Checks if an element form G_T is valid (has the right order). + * + * @param[in] a - the element to check. + */ +int gt_is_valid(gt_t a); + +#endif /* !RLC_PC_H */ diff --git a/bls/contrib/relic/include/relic_pp.h b/bls/contrib/relic/include/relic_pp.h new file mode 100644 index 00000000..15502c14 --- /dev/null +++ b/bls/contrib/relic/include/relic_pp.h @@ -0,0 +1,911 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 . + */ + +/** + * @defgroup pp Bilinear pairings over prime elliptic curves. + */ + +/** + * @file + * + * Interface of the module for computing bilinear pairings over prime elliptic + * curves. + * + * @ingroup pp + */ + +#ifndef RLC_PP_H +#define RLC_PP_H + +#include "relic_fpx.h" +#include "relic_epx.h" +#include "relic_types.h" + +/*============================================================================*/ +/* Macro definitions */ +/*============================================================================*/ + +/** + * Adds two points and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 2. + * + * @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 EP_ADD == BASIC +#define pp_add_k2(L, R, P, Q) pp_add_k2_basic(L, R, P, Q) +#elif EP_ADD == PROJC +#define pp_add_k2(L, R, P, Q) pp_add_k2_projc(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 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) +#elif PP_EXT == LAZYR +#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 8. + * + * @param[out] L - the result of the evaluation. + * @param[in, out] R - the resulting point and first point to add. + * @param[in] Q - the second point to add. + * @param[in] P - the affine point to evaluate the line function. + */ +#if EP_ADD == BASIC +#define pp_add_k8(L, R, Q, P) pp_add_k8_basic(L, R, Q, P) +#elif EP_ADD == PROJC +#define pp_add_k8(L, R, Q, P) pp_add_k8_projc(L, R, Q, P) +#endif + +/** + * Adds two points and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 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] Q - the second point to add. + * @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) +#elif PP_EXT == LAZYR +#define pp_add_k8_projc(L, R, Q, P) pp_add_k8_projc_lazyr(L, R, Q, P) +#endif + +/** + * Adds two points and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 12. + * + * @param[out] L - the result of the evaluation. + * @param[in, out] R - the resulting point and first point to add. + * @param[in] Q - the second point to add. + * @param[in] P - the affine point to evaluate the line function. + */ +#if EP_ADD == BASIC +#define pp_add_k12(L, R, Q, P) pp_add_k12_basic(L, R, Q, P) +#elif EP_ADD == PROJC +#define pp_add_k12(L, R, Q, P) pp_add_k12_projc(L, R, Q, P) +#endif + +/** + * Adds two points and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 12 using projective + * coordinates. + * + * @param[out] L - the result of the evaluation. + * @param[in, out] R - the resulting point and first point to add. + * @param[in] Q - the second point to add. + * @param[in] P - the affine point to evaluate the line function. + */ +#if PP_EXT == BASIC +#define pp_add_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) +#endif + +/** + * Adds two points and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 48. + * + * @param[out] L - the result of the evaluation. + * @param[in, out] R - the resulting point and first point to add. + * @param[in] Q - the second point to add. + * @param[in] P - the affine point to evaluate the line function. + */ +#if EP_ADD == BASIC +#define pp_add_k48(L, RX, RY, RZ, QX, QY, P) pp_add_k48_basic(L, RX, RY, QX, QY, P) +#elif EP_ADD == PROJC +#define pp_add_k48(L, RX, RY, RZ, QX, QY, P) pp_add_k48_projc(L, RX, RY, RZ, QX, QY, P) +#endif + +/** + * Adds two points and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 54. + * + * @param[out] L - the result of the evaluation. + * @param[in, out] R - the resulting point and first point to add. + * @param[in] Q - the second point to add. + * @param[in] P - the affine point to evaluate the line function. + */ +#if EP_ADD == BASIC +#define pp_add_k54(L, RX, RY, RZ, QX, QY, P) pp_add_k54_basic(L, RX, RY, QX, QY, P) +#elif EP_ADD == PROJC +#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. + * + * @param[out] L - the result of the evaluation. + * @param[out] R - the resulting point. + * @param[in] P - the point to double. + * @param[in] Q - the affine point to evaluate the line function. + */ +#if EP_ADD == BASIC +#define pp_dbl_k2(L, R, P, Q) pp_dbl_k2_basic(L, R, P, Q) +#elif EP_ADD == PROJC +#define pp_dbl_k2(L, R, P, Q) pp_dbl_k2_projc(L, R, P, Q) +#endif + +/** + * Doubles a point and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 8. + * + * @param[out] L - the result of the evaluation. + * @param[out] R - the resulting point. + * @param[in] Q - the point to double. + * @param[in] P - the affine point to evaluate the line function. + */ +#if EP_ADD == BASIC +#define pp_dbl_k8(L, R, Q, P) pp_dbl_k8_basic(L, R, Q, P) +#elif EP_ADD == PROJC +#define pp_dbl_k8(L, R, Q, P) pp_dbl_k8_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. + * + * @param[out] L - the result of the evaluation. + * @param[out] R - the resulting point. + * @param[in] Q - the point to double. + * @param[in] P - the affine point to evaluate the line function. + */ +#if EP_ADD == BASIC +#define pp_dbl_k12(L, R, Q, P) pp_dbl_k12_basic(L, R, Q, P) +#elif EP_ADD == PROJC +#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. + * + * @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_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 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 12 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_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) +#endif + +/** + * Doubles a point and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 48. + * + * @param[out] L - the result of the evaluation. + * @param[out] R - the resulting point. + * @param[in] Q - the point to double. + * @param[in] P - the affine point to evaluate the line function. + */ +#if EP_ADD == BASIC +#define pp_dbl_k48(L, RX, RY, RZ, P) pp_dbl_k48_basic(L, RX, RY, P) +#elif EP_ADD == PROJC +#define pp_dbl_k48(L, RX, RY, RZ, P) pp_dbl_k48_projc(L, RX, RY, RZ, P) +#endif + +/** + * Doubles a point and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 54. + * + * @param[out] L - the result of the evaluation. + * @param[out] R - the resulting point. + * @param[in] Q - the point to double. + * @param[in] P - the affine point to evaluate the line function. + */ +#if EP_ADD == BASIC +#define pp_dbl_k54(L, RX, RY, RZ, P) pp_dbl_k54_basic(L, RX, RY, P) +#elif EP_ADD == PROJC +#define pp_dbl_k54(L, RX, RY, RZ, P) pp_dbl_k54_projc(L, RX, RY, RZ, P) +#endif + +/** + * Computes a pairing of two prime elliptic curve points defined on an elliptic + * curves of embedding degree 2. Computes e(P, Q). + * + * @param[out] R - the result. + * @param[in] P - the first elliptic curve point. + * @param[in] Q - the second elliptic curve point. + */ +#if PP_MAP == TATEP +#define pp_map_k2(R, P, Q) pp_map_tatep_k2(R, P, Q) +#elif PP_MAP == WEILP +#define pp_map_k2(R, P, Q) pp_map_weilp_k2(R, P, Q) +#elif PP_MAP == OATEP +#define pp_map_k2(R, P, Q) pp_map_tatep_k2(R, P, Q) +#endif + +/** + * Computes a pairing of two prime elliptic curve points defined on an elliptic + * curve of embedding degree 12. Computes e(P, Q). + * + * @param[out] R - the result. + * @param[in] P - the first elliptic curve point. + * @param[in] Q - the second elliptic curve point. + */ +#if PP_MAP == TATEP +#define pp_map_k12(R, P, Q) pp_map_tatep_k12(R, P, Q) +#elif PP_MAP == WEILP +#define pp_map_k12(R, P, Q) pp_map_weilp_k12(R, P, Q) +#elif PP_MAP == OATEP +#define pp_map_k12(R, P, Q) pp_map_oatep_k12(R, P, Q) +#endif + +/** + * Computes a multi-pairing of elliptic curve points defined on an elliptic + * curve of embedding degree 2. Computes \prod e(P_i, Q_i). + * + * @param[out] R - the result. + * @param[in] P - the first pairing arguments. + * @param[in] Q - the second pairing arguments. + * @param[in] M - the number of pairings to evaluate. + */ +#if PP_MAP == WEILP +#define pp_map_sim_k2(R, P, Q, M) pp_map_sim_weilp_k2(R, P, Q, M) +#elif PP_MAP == TATEP || PP_MAP == OATEP +#define pp_map_sim_k2(R, P, Q, M) pp_map_sim_tatep_k2(R, P, Q, M) +#endif + + +/** + * Computes a multi-pairing of elliptic curve points defined on an elliptic + * curve of embedding degree 12. Computes \prod e(P_i, Q_i). + * + * @param[out] R - the result. + * @param[in] P - the first pairing arguments. + * @param[in] Q - the second pairing arguments. + * @param[in] M - the number of pairings to evaluate. + */ +#if PP_MAP == TATEP +#define pp_map_sim_k12(R, P, Q, M) pp_map_sim_tatep_k12(R, P, Q, M) +#elif PP_MAP == WEILP +#define pp_map_sim_k12(R, P, Q, M) pp_map_sim_weilp_k12(R, P, Q, M) +#elif PP_MAP == OATEP +#define pp_map_sim_k12(R, P, Q, M) pp_map_sim_oatep_k12(R, P, Q, M) +#endif + +/*============================================================================*/ +/* Function prototypes */ +/*============================================================================*/ + +/** + * Initializes the pairing over prime fields. + */ +void pp_map_init(void); + +/** + * Finalizes the pairing over prime fields. + */ +void pp_map_clean(void); + +/** + * Adds two points and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 2 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] p - the second point to add. + * @param[in] q - the affine point to evaluate the line function. + */ +void pp_add_k2_basic(fp2_t l, ep_t r, ep_t p, ep_t q); + +/** + * Adds two points and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 12 using projective + * coordinates. + * + * @param[out] l - the result of the evaluation. + * @param[in, out] r - the resulting point and first point to add. + * @param[in] p - the second point to add. + * @param[in] q - the affine point to evaluate the line function. + */ +void pp_add_k2_projc_basic(fp2_t l, ep_t r, ep_t p, ep_t q); + +/** + * Adds two points and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 12 using projective + * coordinates and lazy reduction. + * + * @param[out] l - the result of the evaluation. + * @param[in, out] r - the resulting point and first point to add. + * @param[in] p - the second point to add. + * @param[in] q - the affine point to evaluate the line function. + */ +void pp_add_k2_projc_lazyr(fp2_t l, ep_t r, ep_t p, ep_t q); + +/** + * Adds two points and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 8 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_k8_basic(fp8_t l, ep2_t r, ep2_t q, ep_t p); + +/** + * Adds two points and evaluates the corresponding line function at another + * 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] q - the second point to add. + * @param[in] p - the affine point to evaluate the line function. + */ +void pp_add_k8_projc_basic(fp8_t l, ep2_t r, ep2_t q, ep_t p); + +/** + * Adds two points and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 8 using projective + * coordinates and lazy reduction. + * + * @param[out] l - the result of the evaluation. + * @param[in, out] r - the resulting point and first point to add. + * @param[in] q - the second point to add. + * @param[in] p - the affine point to evaluate the line function. + */ +void pp_add_k8_projc_lazyr(fp8_t l, ep2_t r, ep2_t q, ep_t p); + +/** + * Adds two points and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 12 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_k12_basic(fp12_t l, ep2_t r, ep2_t q, ep_t p); + +/** + * Adds two points and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 12 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_k12_projc_basic(fp12_t l, ep2_t r, ep2_t q, ep_t p); + +/** + * Adds two points and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 12 using projective + * coordinates and lazy reduction. + * + * @param[out] l - the result of the evaluation. + * @param[in, out] r - the resulting point and first point to add. + * @param[in] q - the second point to add. + * @param[in] p - the affine point to evaluate the line function. + */ +void pp_add_k12_projc_lazyr(fp12_t l, ep2_t r, ep2_t q, ep_t p); + +/** + * Adds two points and evaluates the corresponding line function at another + * point on an elliptic curve twist with embedding degree 12 using projective + * coordinates. + * + * @param[out] l - the result of the evaluation. + * @param[in, out] r - the resulting point and first point to add. + * @param[in] p - the second point to add. + * @param[in] q - the affine point to evaluate the line function. + */ +void pp_add_lit_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 48 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_k48_basic(fp48_t l, fp8_t rx, fp8_t ry, fp8_t qx, fp8_t qy, ep_t p); + +/** + * Adds two points and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 48 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_k48_projc(fp48_t l, fp8_t rx, fp8_t ry, fp8_t rz, fp8_t qx, fp8_t qy, ep_t p); + +/** + * Adds two points and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 54 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_k54_basic(fp54_t l, fp9_t rx, fp9_t ry, fp9_t qx, fp9_t qy, ep_t p); + +/** + * Adds two points and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 54 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_k54_projc(fp54_t l, fp9_t rx, fp9_t ry, fp9_t rz, fp9_t qx, fp9_t qy, ep_t p); + +/** + * Doubles a point and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 2 using affine + * coordinates. + * + * @param[out] l - the result of the evaluation. + * @param[in, out] r - the resulting point. + * @param[in] p - the point to double. + * @param[in] q - the affine point to evaluate the line function. + */ +void pp_dbl_k2_basic(fp2_t l, ep_t r, ep_t p, ep_t q); + +/** + * Doubles a point and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 12 using projective + * coordinates. + * + * @param[out] l - the result of the evaluation. + * @param[in, out] r - the resulting point. + * @param[in] p - the point to double. + * @param[in] q - the affine point to evaluate the line function. + */ +void pp_dbl_k2_projc_basic(fp2_t l, ep_t r, ep_t p, ep_t q); + +/** + * Doubles a point and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 12 using projective + * coordinates and lazy reduction. + * + * @param[out] l - the result of the evaluation. + * @param[in, out] r - the resulting point. + * @param[in] p - the point to double. + * @param[in] q - the affine point to evaluate the line function. + */ +void pp_dbl_k2_projc_lazyr(fp2_t l, ep_t r, ep_t p, ep_t q); + +/** + * Doubles a point and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 8 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_k8_basic(fp8_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 8 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_k8_projc_basic(fp8_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 8 using projective + * coordinates and lazy reduction. + * + * @param[out] l - the result of the evaluation. + * @param[in, out] r - the resulting point. + * @param[in] q - the point to double. + * @param[in] p - the affine point to evaluate the line function. + */ +void pp_dbl_k8_projc_lazyr(fp8_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 12 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_k12_basic(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 12 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_k12_projc_basic(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 12 using projective + * coordinates and lazy reduction. + * + * @param[out] l - the result of the evaluation. + * @param[in, out] r - the resulting point. + * @param[in] q - the point to double. + * @param[in] p - the affine point to evaluate the line function. + */ +void pp_dbl_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 48 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_k48_basic(fp48_t l, fp8_t rx, fp8_t ry, ep_t p); + +/** + * Doubles a point and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 48 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_k48_projc(fp48_t l, fp8_t rx, fp8_t ry, fp8_t rz, ep_t p); + +/** + * Doubles a point and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 54 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_k54_basic(fp54_t l, fp9_t rx, fp9_t ry, ep_t p); + +/** + * Doubles a point and evaluates the corresponding line function at another + * point on an elliptic curve with embedding degree 54 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_k54_projc(fp54_t l, fp9_t rx, fp9_t ry, fp9_t rz, ep_t p); + +/** + * Doubles a point and evaluates the corresponding line function at another + * point on an elliptic curve twist with embedding degree 12 using projective + * coordinates. + * + * @param[out] l - the result of the evaluation. + * @param[in, out] r - the resulting point. + * @param[in] p - the point to double. + * @param[in] q - the affine point to evaluate the line function. + */ +void pp_dbl_lit_k12(fp12_t l, ep_t r, ep_t p, ep2_t q); + +/** + * Computes the final exponentiation for a pairing defined over curves of + * embedding degree 2. Computes c = a^(p^2 - 1)/r. + * + * @param[out] c - the result. + * @param[in] a - the extension field element to exponentiate. + */ +void pp_exp_k2(fp2_t c, fp2_t a); + +/** + * Computes the final exponentiation for a pairing defined over curves of + * embedding degree 8. Computes c = a^(p^8 - 1)/r. + * + * @param[out] c - the result. + * @param[in] a - the extension field element to exponentiate. + */ +void pp_exp_k8(fp8_t c, fp8_t a); + +/** + * Computes the final exponentiation for a pairing defined over curves of + * embedding degree 12. Computes c = a^(p^12 - 1)/r. + * + * @param[out] c - the result. + * @param[in] a - the extension field element to exponentiate. + */ +void pp_exp_k12(fp12_t c, fp12_t a); + +/** + * Computes the final exponentiation for a pairing defined over curves of + * embedding degree 48. Computes c = a^(p^48 - 1)/r. + * + * @param[out] c - the result. + * @param[in] a - the extension field element to exponentiate. + */ +void pp_exp_k48(fp48_t c, fp48_t a); + +/** + * Computes the final exponentiation for a pairing defined over curves of + * embedding degree 54. Computes c = a^(p^54 - 1)/r. + * + * @param[out] c - the result. + * @param[in] a - the extension field element to exponentiate. + */ +void pp_exp_k54(fp54_t c, fp54_t a); + +/** + * Normalizes the accumulator point used inside pairing computation defined + * over curves of embedding degree 2. + * + * @param[out] r - the resulting point. + * @param[in] p - the point to normalize. + */ +void pp_norm_k2(ep_t c, ep_t a); + +/** + * Normalizes the accumulator point used inside pairing computation defined + * over curves of embedding degree 8. + * + * @param[out] r - the resulting point. + * @param[in] p - the point to normalize. + */ +void pp_norm_k8(ep2_t c, ep2_t a); + +/** + * Normalizes the accumulator point used inside pairing computation defined + * over curves of embedding degree 12. + * + * @param[out] r - the resulting point. + * @param[in] p - the point to normalize. + */ +void pp_norm_k12(ep2_t c, ep2_t a); + +/** + * Computes the Tate pairing of two points in a parameterized elliptic curve + * with embedding degree 12. + * + * @param[out] r - the result. + * @param[in] q - the first elliptic curve point. + * @param[in] p - the second elliptic curve point. + */ +void pp_map_tatep_k2(fp2_t r, ep_t p, ep_t q); + +/** + * Computes the Tate multi-pairing of in a parameterized elliptic curve with + * embedding degree 2. + * + * @param[out] r - the result. + * @param[in] q - the first pairing arguments. + * @param[in] p - the second pairing arguments. + * @param[in] m - the number of pairings to evaluate. + */ +void pp_map_sim_tatep_k2(fp2_t r, ep_t *p, ep_t *q, int m); + +/** + * Computes the Weil pairing of two points in a parameterized elliptic curve + * with embedding degree 2. + * + * @param[out] r - the result. + * @param[in] q - the first elliptic curve point. + * @param[in] p - the second elliptic curve point. + */ +void pp_map_weilp_k2(fp2_t r, ep_t p, ep_t q); + +/** + * Computes the optimal ate pairing of two points in a parameterized elliptic + * curve with embedding degree 8. + * + * @param[out] r - the result. + * @param[in] q - the first elliptic curve point. + * @param[in] p - the second elliptic curve point. + */ +void pp_map_oatep_k8(fp8_t r, ep_t p, ep2_t q); + +/** + * Computes the Weil multi-pairing of in a parameterized elliptic curve with + * embedding degree 2. + * + * @param[out] r - the result. + * @param[in] q - the first pairing arguments. + * @param[in] p - the second pairing arguments. + * @param[in] m - the number of pairings to evaluate. + */ +void pp_map_sim_weilp_k2(fp2_t r, ep_t *p, ep_t *q, int m); + +/** + * Computes the Tate pairing of two points in a parameterized elliptic curve + * with embedding degree 12. + * + * @param[out] r - the result. + * @param[in] q - the first elliptic curve point. + * @param[in] p - the second elliptic curve point. + */ +void pp_map_tatep_k12(fp12_t r, ep_t p, ep2_t q); + +/** + * Computes the Tate multi-pairing of in a parameterized elliptic curve with + * embedding degree 12. + * + * @param[out] r - the result. + * @param[in] q - the first pairing arguments. + * @param[in] p - the second pairing arguments. + * @param[in] m - the number of pairings to evaluate. + */ +void pp_map_sim_tatep_k12(fp12_t r, ep_t *p, ep2_t *q, int m); + +/** + * Computes the Weil pairing of two points in a parameterized elliptic curve + * with embedding degree 12. + * + * @param[out] r - the result. + * @param[in] q - the first elliptic curve point. + * @param[in] p - the second elliptic curve point. + */ +void pp_map_weilp_k12(fp12_t r, ep_t p, ep2_t q); + +/** + * Computes the Weil multi-pairing of in a parameterized elliptic curve with + * embedding degree 12. + * + * @param[out] r - the result. + * @param[in] q - the first pairing arguments. + * @param[in] p - the second pairing arguments. + * @param[in] m - the number of pairings to evaluate. + */ +void pp_map_sim_weilp_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 12. + * + * @param[out] r - the result. + * @param[in] q - the first elliptic curve point. + * @param[in] p - the second elliptic curve point. + */ +void pp_map_oatep_k12(fp12_t r, ep_t p, ep2_t q); + +/** + * Computes the optimal ate multi-pairing of in a parameterized elliptic + * curve with embedding degree 12. + * + * @param[out] r - the result. + * @param[in] q - the first pairing arguments. + * @param[in] p - the second pairing arguments. + * @param[in] m - the number of pairings to evaluate. + */ +void pp_map_sim_oatep_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 48. + * + * @param[out] r - the result. + * @param[in] q - the first elliptic curve point. + * @param[in] p - the second elliptic curve point. + */ +void pp_map_k48(fp48_t r, ep_t p, fp8_t qx, fp8_t qy); + +/** + * Computes the Optimal Ate pairing of two points in a parameterized elliptic + * curve with embedding degree 54. + * + * @param[out] r - the result. + * @param[in] q - the first elliptic curve point. + * @param[in] p - the second elliptic curve point. + */ +void pp_map_k54(fp54_t r, ep_t p, fp9_t qx, fp9_t qy); + +#endif /* !RLC_PP_H */ diff --git a/bls/contrib/relic/include/relic_rand.h b/bls/contrib/relic/include/relic_rand.h new file mode 100644 index 00000000..9f828af5 --- /dev/null +++ b/bls/contrib/relic/include/relic_rand.h @@ -0,0 +1,118 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 . + */ + +/** + * @defgroup rand Pseudo-random number generators. + */ + +/** + * @file + * + * Interface of the module for pseudo-random number generation. + * + * @ingroup rand + */ + +#ifndef RLC_RAND_H +#define RLC_RAND_H + +#include "relic_rand.h" + +/*============================================================================*/ +/* Constant definitions */ +/*============================================================================*/ + +/** + * Size of the PRNG internal state in bytes. + */ +#if RAND == HASHD + +#if MD_MAP == SH224 || MD_MAP == SH256 || MD_MAP == BLAKE2S_160 || MD_MAP == BLAKE2S_256 +#define RAND_SIZE (1 + 2*440/8) +#elif MD_MAP == SH384 || MD_MAP == SH512 +#define RAND_SIZE (1 + 2*888/8) +#endif + +#elif RAND == UDEV +#define RAND_SIZE (sizeof(int)) +#elif RAND == CALL +#define RAND_SIZE (sizeof(void (*)(uint8_t *, int))) +#elif RAND == RDRND +#define RAND_SIZE 0 +#endif + +/** + * Minimum size of the PRNG seed. + */ +#define SEED_SIZE 64 + +/*============================================================================*/ +/* Function prototypes */ +/*============================================================================*/ + +/** + * Initializes the pseudo-random number generator. + */ +void rand_init(void); + +/** + * Finishes the pseudo-random number generator. + */ +void rand_clean(void); + +#if RAND != CALL + +/** + * Sets the initial state of the pseudo-random number generator. + * + * @param[in] buf - the buffer that represents the initial state. + * @param[in] size - the number of bytes. + * @throw ERR_NO_VALID - if the entropy length is too small or too large. + */ +void rand_seed(uint8_t *buf, int size); + +#else + +/** + * Sets the initial state of the pseudo-random number generator as a function + * pointer. + * + * @param[in] callback - the callback to call. + * @param[in] arg - the argument for the callback. + */ +void rand_seed(void (*callback)(uint8_t *, int, void *), void *arg); + +#endif + +/** + * Gathers pseudo-random bytes from the pseudo-random number generator. + * + * @param[out] buf - the buffer to write. + * @param[in] size - the number of bytes to gather. + * @throw ERR_NO_VALID - if the required length is too large. + * @throw ERR_NO_READ - it the pseudo-random number generator cannot + * generate the specified number of bytes. + */ +void rand_bytes(uint8_t *buf, int size); + +#endif /* !RLC_RAND_H */ diff --git a/bls/contrib/relic/include/relic_test.h b/bls/contrib/relic/include/relic_test.h new file mode 100644 index 00000000..9039dbc1 --- /dev/null +++ b/bls/contrib/relic/include/relic_test.h @@ -0,0 +1,104 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 . + */ + +/** + * @defgroup tests Automated tests + */ + +/** + * @file + * + * Interface of useful routines for testing. + * + * @ingroup test + */ + +#ifndef RLC_TEST_H +#define RLC_TEST_H + +#include + +#include "relic_conf.h" +#include "relic_label.h" +#include "relic_util.h" + +/*============================================================================*/ +/* Macro definitions */ +/*============================================================================*/ + +/** + * Runs a new benchmark once. + * + * @param[in] P - the property description. + */ +#define TEST_ONCE(P) \ + util_print("Testing if " P "...%*c", (64 - strlen(P)), ' '); \ + +/** + * Tests a sequence of commands to see if they respect some property. + * + * @param[in] P - the property description. + */ +#define TEST_BEGIN(P) \ + util_print("Testing if " P "...%*c", (64 - strlen(P)), ' '); \ + for (int i = 0; i < TESTS; i++) \ + +/** + * Asserts a condition. + * + * If the condition is not satisfied, a unconditional jump is made to the passed + * label. + * + * @param[in] C - the condition to assert. + * @param[in] LABEL - the label to jump if the condition is no satisfied. + */ +#define TEST_ASSERT(C, LABEL) \ + if (!(C)) { \ + test_fail(); \ + util_print("(at "); \ + util_print(__FILE__); \ + util_print(":%d)\n", __LINE__); \ + ERROR(LABEL); \ + } \ + +/** + * Finalizes a test printing the test result. + */ +#define TEST_END \ + test_pass() \ + +/*============================================================================*/ +/* Function prototypes */ +/*============================================================================*/ + +/** + * Prints a string indicating that the test failed. + */ +void test_fail(void); + +/** + * Prints a string indicating that the test passed. + */ +void test_pass(void); + +#endif /* !RLC_TEST_H */ diff --git a/bls/contrib/relic/include/relic_types.h b/bls/contrib/relic/include/relic_types.h new file mode 100644 index 00000000..acc7125f --- /dev/null +++ b/bls/contrib/relic/include/relic_types.h @@ -0,0 +1,166 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 + * + * Elementary types. + * + * @ingroup relic + */ + +#ifndef RLC_TYPES_H +#define RLC_TYPES_H + +#include + +#include "relic_conf.h" + +#if defined GMP && ARITH == GMP +#include +#endif + +/*============================================================================*/ +/* Constant definitions */ +/*============================================================================*/ + +/** + * Size in bits of a digit. + */ +#define RLC_DIG (WSIZE) + +/** + * Logarithm of the digit size in bits in base two. + */ +#if RLC_DIG == 8 +#define RLC_DIG_LOG 3 +#elif RLC_DIG == 16 +#define RLC_DIG_LOG 4 +#elif RLC_DIG == 32 +#define RLC_DIG_LOG 5 +#elif RLC_DIG == 64 +#define RLC_DIG_LOG 6 +#endif + +/*============================================================================*/ +/* Type definitions */ +/*============================================================================*/ + +/** + * Represents a digit from a multiple precision integer. + * + * Each digit is represented as an unsigned long to use the biggest native + * type that potentially supports native instructions. + */ +#if ARITH == GMP +typedef mp_limb_t dig_t; +#elif WSIZE == 8 +typedef uint8_t dig_t; +#elif WSIZE == 16 +typedef uint16_t dig_t; +#elif WSIZE == 32 +typedef uint32_t dig_t; +#elif WSIZE == 64 +typedef uint64_t dig_t; +#endif + +/** + * Represents a signed digit. + */ +#if WSIZE == 8 +typedef int8_t dis_t; +#elif WSIZE == 16 +typedef int16_t dis_t; +#elif WSIZE == 32 +typedef int32_t dis_t; +#elif WSIZE == 64 +typedef int64_t dis_t; +#endif + +/** + * Represents a double-precision integer from a multiple precision integer. + * + * This is useful to store a result from a multiplication of two digits. + */ +#if WSIZE == 8 +typedef uint16_t dbl_t; +#elif WSIZE == 16 +typedef uint32_t dbl_t; +#elif WSIZE == 32 +typedef uint64_t dbl_t; +#elif WSIZE == 64 +#if defined(__GNUC__) && !defined(__INTEL_COMPILER) +typedef __uint128_t dbl_t; +#elif ARITH == EASY +#error "Easy backend in 64-bit mode supported only in GCC compiler." +#else +#endif +#endif + +/* + * Represents the unsigned integer with maximum precision. + */ +typedef unsigned long long ull_t; + +/*============================================================================*/ +/* Macro definitions */ +/*============================================================================*/ + +/** + * Specification for aligned variables. + */ +#if ALIGN > 1 +#define rlc_align __attribute__ ((aligned (ALIGN))) +#else +#define rlc_align /* empty*/ +#endif + +/** + * Size of padding to be added so that digit vectors are aligned. + */ +#if ALIGN > 1 +#define RLC_PAD(A) ((A) % ALIGN == 0 ? 0 : ALIGN - ((A) % ALIGN)) +#else +#define RLC_PAD(A) (0) +#endif + +/** + * Align digit vector pointer to specified byte-boundary. + * + * @param[in,out] A - the pointer to align. + */ +#if ALIGN > 1 +#if ARCH == AVR || ARCH == MSP || ARCH == X86 || ARCH == ARM +#define RLC_ALIGN(A) \ + ((unsigned int)(A) + RLC_PAD((unsigned int)(A))); \ + +#elif ARCH == X64 +#define RLC_ALIGN(A) \ + ((unsigned long)(A) + RLC_PAD((unsigned long)(A))); \ + +#endif +#else +#define RLC_ALIGN(A) (A) +#endif + +#endif /* !RLC_TYPES_H */ diff --git a/bls/contrib/relic/include/relic_util.h b/bls/contrib/relic/include/relic_util.h new file mode 100644 index 00000000..f90f1533 --- /dev/null +++ b/bls/contrib/relic/include/relic_util.h @@ -0,0 +1,248 @@ +/* + * RELIC is an Efficient LIbrary for Cryptography + * Copyright (C) 2007-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 . + */ + +/** + * @defgroup util Misc utilities + */ + +/** + * @file + * + * Interface of misc utilitles. + * + * @ingroup util + */ + +#ifndef RLC_UTIL_H +#define RLC_UTIL_H + +#include "relic_arch.h" +#include "relic_types.h" +#include "relic_label.h" + +/*============================================================================*/ +/* Macro definitions */ +/*============================================================================*/ + +/** + * Returns the minimum between two numbers. + * + * @param[in] A - the first number. + * @param[in] B - the second number. + */ +#define RLC_MIN(A, B) ((A) < (B) ? (A) : (B)) + +/** + * Returns the maximum between two numbers. + * + * @param[in] A - the first number. + * @param[in] B - the second number. + */ +#define RLC_MAX(A, B) ((A) > (B) ? (A) : (B)) + +/** + * Splits a bit count in a digit count and an updated bit count. + * + * @param[out] B - the resulting bit count. + * @param[out] D - the resulting digit count. + * @param[out] V - the bit count. + */ +#define RLC_RIP(B, D, V) \ + D = (V) >> (RLC_DIG_LOG); B = (V) - ((D) * (1 << RLC_DIG_LOG)); + +/** + * Computes the ceiling function of an integer division. + * + * @param[in] A - the dividend. + * @param[in] B - the divisor. + */ +#define RLC_CEIL(A, B) (((A) - 1) / (B) + 1) + +/** + * Returns a bit mask to isolate the lowest part of a digit. + * + * @param[in] B - the number of bits to isolate. + */ +#define RLC_MASK(B) \ + ((-(dig_t)((B) >= WSIZE)) | (((dig_t)1 << ((B) % WSIZE)) - 1)) + +/** + * Returns a bit mask to isolate the lowest half of a digit. + */ +#define RLC_LMASK (RLC_MASK(RLC_DIG >> 1)) + +/** + * Returns a bit mask to isolate the highest half of a digit. + */ +#define RLC_HMASK (RLC_LMASK << (RLC_DIG >> 1)) + +/** + * Bit mask used to return an entire digit. + */ +#define RLC_DMASK (RLC_HMASK | RLC_LMASK) + +/** + * Returns the lowest half of a digit. + * + * @param[in] D - the digit. + */ +#define RLC_LOW(D) (D & RLC_LMASK) + +/** + * Returns the highest half of a digit. + * + * @param[in] D - the digit. + */ +#define RLC_HIGH(D) (D >> (RLC_DIG >> 1)) + +/** + * Selects between two values based on the value of a given flag. + * + * @param[in] A - the first argument. + * @param[in] B - the second argument. + * @param[in] C - the selection flag. + */ +#define RLC_SEL(A, B, C) ((-(C) & ((A) ^ (B))) ^ (A)) + +/** + * Swaps two values. + * + * @param[in] A - the first argument. + * @param[in] B - the second argument. + */ +#define RLC_SWAP(A, B) ((A) ^= (B), (B) ^= (A), (A) ^= (B)) + +/** + * Returns the given character in upper case. + * + * @param[in] C - the character. + */ +#define RLC_UPP(C) ((C) - 0x20 * (((C) >= 'a') && ((C) <= 'z'))) + +/** + * Indirection to help some compilers expand symbols. + */ +#define RLC_ECHO(A) A + +/** + * Concatenates two tokens. + */ +/** @{ */ +#define RLC_CAT(A, B) _RLC_CAT(A, B) +#define _RLC_CAT(A, B) A ## B +/** @} */ + +/** + * Selects a basic or advanced version of a function by checking if an + * additional argument was passed. + */ +/** @{ */ +#define RLC_OPT(...) _OPT(__VA_ARGS__, _imp, _basic, _error) +#define _OPT(...) RLC_ECHO(__OPT(__VA_ARGS__)) +#define __OPT(_1, _2, N, ...) N +/** @} */ + +/** + * Selects a real or dummy printing function depending on library flags. + * + * @param[in] F - the format string. + */ +#ifndef QUIET +#define util_print(F, ...) util_printf(RLC_STR(F), ##__VA_ARGS__) +#else +#define util_print(F, ...) /* empty */ +#endif + +/** + * Prints a standard label. + * + * @param[in] L - the label of the banner. + * @param[in] I - if the banner is inside an hierarchy. + */ +#define util_banner(L, I) \ + if (!I) { \ + util_print("\n-- " L "\n"); \ + } else { \ + util_print("\n** " L "\n\n"); \ + } \ + +/*============================================================================*/ +/* Function prototypes */ +/*============================================================================*/ + +/** + * Toggle endianess of a digit. + */ +uint32_t util_conv_endian(uint32_t i); + +/** + * Convert a digit to big-endian. + */ +uint32_t util_conv_big(uint32_t i); + +/** + * Convert a digit to little-endian. + */ +uint32_t util_conv_little(uint32_t i); + +/** + * Converts a small digit to a character. + */ +char util_conv_char(dig_t i); + +/** + * Returns the highest bit set on a digit. + * + * @param[in] a - the digit. + * @return the position of the highest bit set. + */ +int util_bits_dig(dig_t a); + +/** + * Compares two buffers in constant time. + * + * @param[in] a - the first buffer. + * @param[in] b - the second buffer. + * @param[in] n - the length in bytes of the buffers. + * @return RLC_EQ if they are equal and RLC_NE otherwise. + */ +int util_cmp_const(const void *a, const void *b, int n); + +/** + * Formats and prints data following a printf-like syntax. + * + * @param[in] format - the format. + * @param[in] ... - the list of arguments matching the format. + */ +void util_printf(const char *format, ...); + +/** + * Prints a digit. + * + * @param[in] a - the digit to print. + * @param[in] pad - the flag to indicate if the digit must be padded + * with zeroes. + */ +void util_print_dig(dig_t a, int pad); + +#endif /* !RLC_UTIL_H */ diff --git a/bls/src/CMakeLists.txt b/bls/src/CMakeLists.txt new file mode 100644 index 00000000..01d499f7 --- /dev/null +++ b/bls/src/CMakeLists.txt @@ -0,0 +1,76 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 3.1.0 FATAL_ERROR) +set (CMAKE_CXX_STANDARD 11) + +file(GLOB HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/*.hpp) +source_group("SrcHeaders" FILES ${HEADERS}) + +include_directories( + ${INCLUDE_DIRECTORIES} + ${CMAKE_CURRENT_SOURCE_DIR}/../contrib/relic/include + ${CMAKE_BINARY_DIR}/contrib/relic/include + ${CMAKE_CURRENT_SOURCE_DIR}/../contrib/catch + ) + +set(C_LIB ${CMAKE_BINARY_DIR}/libbls.a) + +add_library(bls ${CMAKE_CURRENT_SOURCE_DIR}/chaincode.cpp) + +add_library(blstmp ${HEADERS} + ${CMAKE_CURRENT_SOURCE_DIR}/extendedpublickey.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/extendedprivatekey.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/chaincode.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/signature.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/publickey.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/privatekey.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/bls.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/aggregationinfo.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/threshold.cpp +) + +set(OPREFIX object_) +find_library(GMP_NAME NAMES libgmp.a gmp) +find_library(SODIUM_NAME NAMES libsodium.a sodium) + +set(LIBRARIES_TO_COMBINE + COMMAND mkdir ${OPREFIX}$ || true && cd ${OPREFIX}$ && ${CMAKE_AR} -x $ + COMMAND mkdir ${OPREFIX}$ || true && cd ${OPREFIX}$ && ${CMAKE_AR} -x $ +) + +if (GMP_FOUND) + list(APPEND LIBRARIES_TO_COMBINE COMMAND mkdir ${OPREFIX}gmp || true && cd ${OPREFIX}gmp && ${CMAKE_AR} -x ${GMP_NAME}) +endif() +if (SODIUM_FOUND) + list(APPEND LIBRARIES_TO_COMBINE COMMAND mkdir ${OPREFIX}sodium || true && cd ${OPREFIX}sodium && ${CMAKE_AR} -x ${SODIUM_NAME}) +endif() + +add_custom_target(combined_custom + ${LIBRARIES_TO_COMBINE} + COMMAND ${CMAKE_AR} -rs ${C_LIB} ${OPREFIX}*/*${CMAKE_C_OUTPUT_EXTENSION} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + DEPENDS blstmp relic_s + ) + +add_library(combined STATIC IMPORTED GLOBAL) +add_dependencies(combined combined_custom) + +target_link_libraries(bls combined) + +set_target_properties(combined + PROPERTIES + IMPORTED_LOCATION ${C_LIB} + ) + +file(GLOB includes "${CMAKE_CURRENT_SOURCE_DIR}/*.hpp") +install(FILES ${includes} DESTINATION include/chiabls) +install(FILES ${C_LIB} DESTINATION lib) + +add_executable(runtest test.cpp) +add_executable(runbench test-bench.cpp) + +if (SODIUM_FOUND) + target_link_libraries(runtest blstmp relic_s sodium) + target_link_libraries(runbench blstmp relic_s sodium) +else() + target_link_libraries(runtest blstmp relic_s) + target_link_libraries(runbench blstmp relic_s) +endif() diff --git a/bls/src/aggregationinfo.cpp b/bls/src/aggregationinfo.cpp new file mode 100644 index 00000000..74bf5e4b --- /dev/null +++ b/bls/src/aggregationinfo.cpp @@ -0,0 +1,410 @@ +// Copyright 2018 Chia Network Inc + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include +#include "aggregationinfo.hpp" +#include "bls.hpp" +namespace bls { + +// Creates a new object, copying the messageHash and pk +AggregationInfo AggregationInfo::FromMsgHash(const PublicKey &pk, + const uint8_t *messageHash) { + uint8_t* mapKey = new uint8_t[BLS::MESSAGE_HASH_LEN + + PublicKey::PUBLIC_KEY_SIZE]; + + std::memcpy(mapKey, messageHash, BLS::MESSAGE_HASH_LEN); + pk.Serialize(mapKey + BLS::MESSAGE_HASH_LEN); + AggregationInfo::AggregationTree tree; + bn_t *one = new bn_t[1]; + bn_new(*one); + bn_zero(*one); + bn_set_dig(*one, 1); + tree.insert(std::make_pair(mapKey, one)); + + std::vector hashes = {mapKey}; + std::vector pks = {pk}; + + return AggregationInfo(tree, hashes, pks); +} + +AggregationInfo AggregationInfo::FromMsg(const PublicKey &pk, + const uint8_t *message, + size_t len) { + uint8_t hash[BLS::MESSAGE_HASH_LEN]; + Util::Hash256(hash, message, len); + return FromMsgHash(pk, hash); +} + +AggregationInfo AggregationInfo::FromVectors( + std::vector const &pubKeys, + std::vector const &messageHashes, + std::vector const &exponents) { + if (pubKeys.size() != messageHashes.size() || messageHashes.size() != + exponents.size()) { + throw std::length_error("Invalid input, all std::vectors must have the same length"); + } + AggregationInfo::AggregationTree tree; + for (size_t i = 0; i < pubKeys.size(); i++) { + uint8_t * mapKey = new uint8_t[BLS::MESSAGE_HASH_LEN + + PublicKey::PUBLIC_KEY_SIZE]; + std::memcpy(mapKey, messageHashes[i], BLS::MESSAGE_HASH_LEN); + pubKeys[i].Serialize(mapKey + BLS::MESSAGE_HASH_LEN); + bn_t *mapValue = new bn_t[1]; + bn_new(*mapValue) + bn_copy(*mapValue, *exponents[i]); + tree.insert(std::make_pair(mapKey, mapValue)); + } + std::vector sortedPubKeys; + std::vector sortedMessageHashes; + SortIntoVectors(sortedMessageHashes, sortedPubKeys, tree); + return AggregationInfo(tree, sortedMessageHashes, sortedPubKeys); +} + +// Merges multiple AggregationInfo objects together. +AggregationInfo AggregationInfo::MergeInfos(std::vector + const &infos) { + // Find messages that are in multiple infos + std::set messages; + std::set collidingMessages; + for (const AggregationInfo &info : infos) { + std::set messagesLocal; + for (auto &mapEntry : info.tree) { + auto lookupEntry = messages.find(mapEntry.first); + auto lookupEntryLocal = messagesLocal.find(mapEntry.first); + if (lookupEntryLocal == messagesLocal.end() && + lookupEntry != messages.end()) { + collidingMessages.insert(mapEntry.first); + } + messages.insert(mapEntry.first); + messagesLocal.insert(mapEntry.first); + } + } + if (collidingMessages.empty()) { + // If there are no colliding messages, combine without exponentiation + return SimpleMergeInfos(infos); + } else { + // Otherwise, figure out with infos collide + std::vector collidingInfos; + std::vector nonCollidingInfos; + for (const AggregationInfo &info : infos) { + bool infoCollides = false; + for (auto &mapEntry : info.tree) { + auto lookupEntry = collidingMessages.find(mapEntry.first); + if (lookupEntry != collidingMessages.end()) { + infoCollides = true; + collidingInfos.push_back(info); + break; + } + } + if (!infoCollides) { + nonCollidingInfos.push_back(info); + } + } + // Combine the infos that collide securely (with exponentiation) + AggregationInfo combined = SecureMergeInfos(collidingInfos); + nonCollidingInfos.push_back(combined); + + // Do a simple combination of the rest (no exponentiation) + return SimpleMergeInfos(nonCollidingInfos); + } +} + +AggregationInfo::AggregationInfo(const AggregationInfo& info) { + InsertIntoTree(tree, info); + SortIntoVectors(sortedMessageHashes, sortedPubKeys, tree); +} + +void AggregationInfo::RemoveEntries(std::vector const &messages, + std::vector const &pubKeys) { + if (messages.size() != pubKeys.size()) { + throw std::length_error("Invalid entries"); + } + // Erase the keys from the tree + for (size_t i = 0; i < messages.size(); i++) { + uint8_t entry[BLS::MESSAGE_HASH_LEN + PublicKey::PUBLIC_KEY_SIZE]; + std::memcpy(entry, messages[i], BLS::MESSAGE_HASH_LEN); + pubKeys[i].Serialize(entry + BLS::MESSAGE_HASH_LEN); + auto kv = tree.find(entry); + const uint8_t* first = kv->first; + const bn_t* second = kv->second; + delete[] second; + tree.erase(entry); + delete[] first; + } + // Remove all elements from vectors, and regenerate them + sortedMessageHashes.clear(); + sortedPubKeys.clear(); + SortIntoVectors(sortedMessageHashes, sortedPubKeys, tree); +} + +void AggregationInfo::GetExponent(bn_t *result, const uint8_t* messageHash, + const PublicKey &pubKey) const { + uint8_t mapKey[BLS::MESSAGE_HASH_LEN + + PublicKey::PUBLIC_KEY_SIZE]; + std::memcpy(mapKey, messageHash, BLS::MESSAGE_HASH_LEN); + pubKey.Serialize(mapKey + BLS::MESSAGE_HASH_LEN); + bn_copy(*result, *tree.at(mapKey)); +} + +std::vector AggregationInfo::GetPubKeys() const { + return sortedPubKeys; +} + +std::vector AggregationInfo::GetMessageHashes() const { + return sortedMessageHashes; +} + +bool AggregationInfo::Empty() const { + return tree.empty(); +} + +// Compares two aggregation infos by the following process: +// (A.msgHash || A.pk || A.exponent) < (B.msgHash || B.pk || B.exponent) +// for each element in their sorted trees. +bool operator<(AggregationInfo const&a, AggregationInfo const&b) { + if (a.Empty() && b.Empty()) { + return false; + } + bool lessThan = false; + for (size_t i=0; i < a.sortedMessageHashes.size() + || i < b.sortedMessageHashes.size(); i++) { + // If we run out of elements, return + if (a.sortedMessageHashes.size() == i) { + lessThan = true; + break; + } else if (b.sortedMessageHashes.size() == i) { + lessThan = false; + break; + } + // Otherwise, generate the msgHash || pk element, and compare + uint8_t bufferA[BLS::MESSAGE_HASH_LEN + PublicKey::PUBLIC_KEY_SIZE]; + uint8_t bufferB[BLS::MESSAGE_HASH_LEN + PublicKey::PUBLIC_KEY_SIZE]; + std::memcpy(bufferA, a.sortedMessageHashes[i], BLS::MESSAGE_HASH_LEN); + std::memcpy(bufferB, b.sortedMessageHashes[i], BLS::MESSAGE_HASH_LEN); + a.sortedPubKeys[i].Serialize(bufferA + BLS::MESSAGE_HASH_LEN); + b.sortedPubKeys[i].Serialize(bufferB + BLS::MESSAGE_HASH_LEN); + if (std::memcmp(bufferA, bufferB, BLS::MESSAGE_HASH_LEN + + PublicKey::PUBLIC_KEY_SIZE) < 0) { + lessThan = true; + break; + } else if (std::memcmp(bufferA, bufferB, BLS::MESSAGE_HASH_LEN + + PublicKey::PUBLIC_KEY_SIZE) > 0) { + lessThan = false; + break; + } + // If they are equal, compare the exponents + auto aExp = a.tree.find(bufferA); + auto bExp = b.tree.find(bufferB); + int cmpRes = bn_cmp(*aExp->second, *bExp->second); + if (cmpRes == RLC_LT) { + lessThan = true; + break; + } else if (cmpRes == RLC_GT) { + lessThan = false; + break; + } + } + // If all comparisons are equal, false is returned. + return lessThan; +} + +bool operator==(AggregationInfo const&a, AggregationInfo const&b) { + return !(a < b) && !(b < a); +} + +bool operator!=(AggregationInfo const&a, AggregationInfo const&b) { + return (a < b) || (b < a); +} + +std::ostream &operator<<(std::ostream &os, AggregationInfo const &a) { + for (auto &kv : a.tree) { + os << Util::HexStr(kv.first, 80) << ".." << ":" << std::endl; + uint8_t str[RLC_BN_SIZE * 3 + 1]; + bn_write_bin(str, sizeof(str), *kv.second); + os << Util::HexStr(str + RLC_BN_SIZE * 3 + 1 - 5, 5) + << std::endl; + } + return os; +} + +AggregationInfo& AggregationInfo::operator=(const AggregationInfo &rhs) { + Clear(); + InsertIntoTree(tree, rhs); + SortIntoVectors(sortedMessageHashes, sortedPubKeys, tree); + return *this; +} + +void AggregationInfo::InsertIntoTree(AggregationInfo::AggregationTree &tree, + const AggregationInfo& info) { + for (auto &mapEntry : info.tree) { + uint8_t* messageCopy = new uint8_t[BLS::MESSAGE_HASH_LEN + + PublicKey::PUBLIC_KEY_SIZE]; + std::memcpy(messageCopy, mapEntry.first, BLS::MESSAGE_HASH_LEN + + PublicKey::PUBLIC_KEY_SIZE); + bn_t * exponent = new bn_t[1]; + bn_new(*exponent); + bn_copy(*exponent, *mapEntry.second); + bn_t ord; + g1_get_ord(ord); + bn_mod(*exponent, *exponent, ord); + tree.insert(std::make_pair(messageCopy, exponent)); + } +} + +// This method is used to keep an alternate copy of the tree +// keys (hashes and pks) in sorted order, for easy access. +// Note: these are sorted in mh + pk order. +void AggregationInfo::SortIntoVectors(std::vector &ms, + std::vector &pks, + const AggregationInfo::AggregationTree &tree) { + for (auto &kv : tree) { + ms.push_back(kv.first); + } + sort(begin(ms), end(ms), + Util::BytesCompare80()); + for (auto &m : ms) { + pks.push_back(PublicKey::FromBytes(m + BLS::MESSAGE_HASH_LEN)); + } +} + +// Simple merging, no exponentiation is performed +AggregationInfo AggregationInfo::SimpleMergeInfos( + std::vector const &infos) { + std::set pubKeysDedup; + + AggregationTree newTree; + for (const AggregationInfo &info : infos) { + InsertIntoTree(newTree, info); + } + std::vector pks; + std::vector messageHashes; + SortIntoVectors(messageHashes, pks, newTree); + + return AggregationInfo(newTree, messageHashes, pks); +} + +AggregationInfo AggregationInfo::SecureMergeInfos( + std::vector const &collidingInfosArg) { + // Sort colliding Infos + std::vector sortedCollidingInfos(collidingInfosArg.size()); + size_t pkCount = 0; + for (size_t i = 0; i < sortedCollidingInfos.size(); i++) { + sortedCollidingInfos[i] = i; + pkCount += collidingInfosArg[i].tree.size(); + } + // Groups are sorted by message then pk then exponent + // Each info object (and all of it's exponents) will be + // exponentiated by one of the Ts + std::sort(sortedCollidingInfos.begin(), sortedCollidingInfos.end(), [&collidingInfosArg](size_t a, size_t b) { + return collidingInfosArg[a] < collidingInfosArg[b]; + }); + + std::vector msgAndPks; + std::vector serPks; + std::vector sortedKeys; + msgAndPks.reserve(pkCount); + serPks.reserve(pkCount); + sortedKeys.reserve(pkCount); + for (size_t i = 0; i < sortedCollidingInfos.size(); i++) { + for (auto &mapEntry : collidingInfosArg[sortedCollidingInfos[i]].tree) { + uint8_t *serPk = new uint8_t[PublicKey::PUBLIC_KEY_SIZE]; + memcpy(serPk, mapEntry.first + BLS::MESSAGE_HASH_LEN, PublicKey::PUBLIC_KEY_SIZE); + + msgAndPks.emplace_back(mapEntry.first); + serPks.emplace_back(serPk); + sortedKeys.emplace_back(sortedKeys.size()); + } + } + // Pks are sorted by message then pk + std::sort(sortedKeys.begin(), sortedKeys.end(), [&msgAndPks](size_t a, size_t b) { + return memcmp(msgAndPks[a], msgAndPks[b], BLS::MESSAGE_HASH_LEN + PublicKey::PUBLIC_KEY_SIZE) < 0; + }); + + // Calculate Ts + // Each T is multiplied with an exponent in one of the collidingInfos + bn_t* computedTs = new bn_t[sortedCollidingInfos.size()]; + for (size_t i = 0; i < sortedCollidingInfos.size(); i++) { + bn_new(computedTs[i]); + } + BLS::HashPubKeys(computedTs, sortedCollidingInfos.size(), serPks, sortedKeys); + + bn_t ord; + g1_get_ord(ord); + + // Merge the trees, multiplying by the Ts, and then adding + // to total + AggregationTree newTree; + for (size_t i = 0; i < sortedCollidingInfos.size(); i++) { + const AggregationInfo info = collidingInfosArg[sortedCollidingInfos[i]]; + for (auto &mapEntry : info.tree) { + auto newMapEntry = newTree.find(mapEntry.first); + if (newMapEntry == newTree.end()) { + // This message & pk has not been included yet + uint8_t* mapKeyCopy = new uint8_t[BLS::MESSAGE_HASH_LEN + + PublicKey::PUBLIC_KEY_SIZE]; + std::memcpy(mapKeyCopy, mapEntry.first, BLS::MESSAGE_HASH_LEN + + PublicKey::PUBLIC_KEY_SIZE); + + bn_t * exponent = new bn_t[1]; + bn_new(*exponent); + bn_copy(*exponent, *mapEntry.second); + bn_mul(*exponent, *exponent, computedTs[i]); + bn_mod(*exponent, *exponent, ord); + newTree.insert(std::make_pair(mapKeyCopy, exponent)); + } else { + // This message & pk is already included. Multiply. + bn_t tmp; + bn_new(tmp); + bn_copy(tmp, *mapEntry.second); + bn_mul(tmp, tmp, computedTs[i]); + bn_add(*newMapEntry->second, *newMapEntry->second, tmp); + bn_mod(*newMapEntry->second, *newMapEntry->second, ord); + } + } + } + delete[] computedTs; + std::vector pks; + std::vector messageHashes; + SortIntoVectors(messageHashes, pks, newTree); + + for (auto p : serPks) { + delete[] p; + } + + return AggregationInfo(newTree, messageHashes, pks); +} + +// Frees all memory +void AggregationInfo::Clear() { + sortedMessageHashes.clear(); + sortedPubKeys.clear(); + if (!(tree.empty())) { + for (auto &mapEntry : tree) { + delete[] mapEntry.first; + delete[] mapEntry.second; + } + tree.clear(); + } +} + +AggregationInfo::AggregationInfo() {} + +AggregationInfo::~AggregationInfo() { + Clear(); +} +} // end namespace bls diff --git a/bls/src/aggregationinfo.hpp b/bls/src/aggregationinfo.hpp new file mode 100644 index 00000000..1eb6ff74 --- /dev/null +++ b/bls/src/aggregationinfo.hpp @@ -0,0 +1,109 @@ +// Copyright 2018 Chia Network Inc + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_AGGREGATIONINFO_HPP_ +#define SRC_AGGREGATIONINFO_HPP_ + +#include +#include +#include "publickey.hpp" +#include "util.hpp" +namespace bls { +/** + * Represents information about how aggregation was performed, + * or how a signature was generated (pks, messageHashes, etc). + * The AggregationTree is a map from messageHash, pk -> exponent. + * The exponent is the number that the public key needs to be + * raised to, and the messageHash is the message that was signed, + * and it's signature raised to that exponent. The flat + * representation allows for simple and efficient lookup of a + * given public key when verifying an aggregate signature. + * + * Invariant: always maintains sortedMessageHashes and sortedPubKeys + * for efficiency. This data is equivalent to the keys in tree. + */ +class AggregationInfo { + public: + // Creates a base aggregation info object. + static AggregationInfo FromMsgHash(const PublicKey &pk, + const uint8_t* messageHash); + + static AggregationInfo FromMsg(const PublicKey &pk, + const uint8_t* message, + size_t len); + + static AggregationInfo FromVectors( + std::vector const &pubKeys, + std::vector const &messageHashes, + std::vector const &exponents); + + // Merge two AggregationInfo objects into one. + static AggregationInfo MergeInfos(std::vector + const &infos); + + // Copy constructor, deep copies data. + AggregationInfo(const AggregationInfo& info); + + // Removes the messages and pubkeys from the tree + void RemoveEntries(std::vector const &messages, + std::vector const &pubKeys); + + // Public accessors + void GetExponent(bn_t *result, const uint8_t* messageHash, + const PublicKey &pubkey) const; + std::vector GetPubKeys() const; + std::vector GetMessageHashes() const; + bool Empty() const; + + // Overloaded operators. + friend bool operator<(AggregationInfo const &a, AggregationInfo const &b); + friend bool operator==(AggregationInfo const &a, AggregationInfo const &b); + friend bool operator!=(AggregationInfo const &a, AggregationInfo const &b); + friend std::ostream &operator<<(std::ostream &os, AggregationInfo const &a); + AggregationInfo& operator=(const AggregationInfo& rhs); + + AggregationInfo(); + ~AggregationInfo(); + + private: + // This is the data structure that maps messages (32) and + // public keys (48) to exponents (bn_t*). + typedef std::map AggregationTree; + + explicit AggregationInfo(const AggregationTree& tr, + std::vector ms, + std::vector pks) + : tree(tr), + sortedMessageHashes(ms), + sortedPubKeys(pks) {} + + static void InsertIntoTree(AggregationTree &tree, + const AggregationInfo& info); + static void SortIntoVectors(std::vector &ms, + std::vector &pks, + const AggregationTree &tree); + static AggregationInfo SimpleMergeInfos( + std::vector const &infos); + static AggregationInfo SecureMergeInfos( + std::vector const &infos); + void Clear(); + + AggregationTree tree; + std::vector sortedMessageHashes; + std::vector sortedPubKeys; +}; +} // end namespace bls + +#endif // SRC_AGGREGATIONINFO_HPP_ diff --git a/bls/src/bls.cpp b/bls/src/bls.cpp new file mode 100644 index 00000000..6e8d5e05 --- /dev/null +++ b/bls/src/bls.cpp @@ -0,0 +1,135 @@ +// Copyright 2018 Chia Network Inc + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include + +#include "bls.hpp" +namespace bls { + +const char BLS::GROUP_ORDER[] = + "73EDA753299D7D483339D80809A1D80553BDA402FFFE5BFEFFFFFFFF00000001"; + +bool BLSInitResult = BLS::Init(); + +Util::SecureAllocCallback Util::secureAllocCallback; +Util::SecureFreeCallback Util::secureFreeCallback; + +static void relic_core_initializer(void* ptr) { + core_init(); + if (err_get_code() != RLC_OK) { + std::cout << "core_init() failed"; + // this will most likely crash the application...but there isn't much we can do + throw std::string("core_init() failed"); + } + + const int r = ep_param_set_any_pairf(); + if (r != RLC_OK) { + std::cout << "ep_param_set_any_pairf() failed"; + // this will most likely crash the application...but there isn't much we can do + throw std::string("ep_param_set_any_pairf() failed"); + } +} + +bool BLS::Init() { + if (ALLOC != AUTO) { + std::cout << "Must have ALLOC == AUTO"; + throw std::string("Must have ALLOC == AUTO"); + } +#if BLSALLOC_SODIUM + if (sodium_init() < 0) { + std::cout << "libsodium init failed"; + throw std::string("libsodium init failed"); + } + SetSecureAllocator(libsodium::sodium_malloc, libsodium::sodium_free); +#else + SetSecureAllocator(malloc, free); +#endif + + core_set_thread_initializer(relic_core_initializer, nullptr); + + return true; +} + +void BLS::SetSecureAllocator(Util::SecureAllocCallback allocCb, Util::SecureFreeCallback freeCb) { + Util::secureAllocCallback = allocCb; + Util::secureFreeCallback = freeCb; +} + +void BLS::HashPubKeys(bn_t* output, size_t numOutputs, + std::vector const &serPubKeys, + std::vector const& sortedIndices) { + bn_t order; + + bn_new(order); + g2_get_ord(order); + + uint8_t *pkBuffer = new uint8_t[serPubKeys.size() * PublicKey::PUBLIC_KEY_SIZE]; + + for (size_t i = 0; i < serPubKeys.size(); i++) { + memcpy(pkBuffer + i * PublicKey::PUBLIC_KEY_SIZE, serPubKeys[sortedIndices[i]], PublicKey::PUBLIC_KEY_SIZE); + } + + uint8_t pkHash[32]; + Util::Hash256(pkHash, pkBuffer, serPubKeys.size() * PublicKey::PUBLIC_KEY_SIZE); + for (size_t i = 0; i < numOutputs; i++) { + uint8_t hash[32]; + uint8_t buffer[4 + 32]; + memset(buffer, 0, 4); + // Set first 4 bytes to index, to generate different ts + Util::IntToFourBytes(buffer, i); + // Set next 32 bytes as the hash of all the public keys + std::memcpy(buffer + 4, pkHash, 32); + Util::Hash256(hash, buffer, 4 + 32); + + bn_read_bin(output[i], hash, 32); + bn_mod_basic(output[i], output[i], order); + } + + delete[] pkBuffer; + + CheckRelicErrors(); +} + +PublicKey BLS::DHKeyExchange(const PrivateKey& privKey, const PublicKey& pubKey) { + if (!privKey.keydata) { + throw std::string("keydata not initialized"); + } + PublicKey ret = pubKey.Exp(*privKey.keydata); + CheckRelicErrors(); + return ret; +} + +void BLS::CheckRelicErrors() { + if (!core_get()) { + throw std::string("Library not initialized properly. Call BLS::Init()"); + } + if (core_get()->code != RLC_OK) { + core_get()->code = RLC_OK; + throw std::string("Relic library error"); + } +} + +void BLS::CheckRelicErrorsInvalidArgument() { + if (!core_get()) { + throw std::string("Library not initialized properly. Call BLS::Init()"); + } + if (core_get()->code != RLC_OK) { + core_get()->code = RLC_OK; + throw std::invalid_argument("Relic library error"); + } +} +} // end namespace bls diff --git a/bls/src/bls.hpp b/bls/src/bls.hpp new file mode 100644 index 00000000..5f64a166 --- /dev/null +++ b/bls/src/bls.hpp @@ -0,0 +1,70 @@ +// Copyright 2018 Chia Network Inc + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_BLS_HPP_ +#define SRC_BLS_HPP_ + +#include +#include +#include +#include + +#include "relic_conf.h" + +#if defined GMP && ARITH == GMP +#include +#endif + +#include "publickey.hpp" +#include "privatekey.hpp" +#include "signature.hpp" +#include "extendedprivatekey.hpp" +#include "aggregationinfo.hpp" +#include "threshold.hpp" + +#include "relic.h" +#include "relic_test.h" + +namespace bls { + +/* + * Principal class for verification and signature aggregation. + * Include this file to use the library. + */ +class BLS { + public: + // Order of g1, g2, and gt. Private keys are in {0, GROUP_ORDER}. + static const char GROUP_ORDER[]; + static const size_t MESSAGE_HASH_LEN = 32; + + // Initializes the BLS library (called automatically) + static bool Init(); + + static void SetSecureAllocator(Util::SecureAllocCallback allocCb, Util::SecureFreeCallback freeCb); + + // Used for secure aggregation + static void HashPubKeys( + bn_t* output, + size_t numOutputs, + std::vector const &serPubKeys, + std::vector const &sortedIndices); + + static PublicKey DHKeyExchange(const PrivateKey& privKey, const PublicKey& pubKey); + + static void CheckRelicErrors(); + static void CheckRelicErrorsInvalidArgument(); +}; +} // end namespace bls + +#endif // SRC_BLS_HPP_ diff --git a/bls/src/chaincode.cpp b/bls/src/chaincode.cpp new file mode 100644 index 00000000..791e6b7d --- /dev/null +++ b/bls/src/chaincode.cpp @@ -0,0 +1,57 @@ +// Copyright 2018 Chia Network Inc + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "chaincode.hpp" +#include "bls.hpp" +namespace bls { + +ChainCode ChainCode::FromBytes(const uint8_t* bytes) { + ChainCode c = ChainCode(); + bn_new(c.chainCode); + bn_read_bin(c.chainCode, bytes, ChainCode::CHAIN_CODE_SIZE); + return c; +} + +ChainCode::ChainCode(const ChainCode &cc) { + uint8_t bytes[ChainCode::CHAIN_CODE_SIZE]; + cc.Serialize(bytes); + bn_new(chainCode); + bn_read_bin(chainCode, bytes, ChainCode::CHAIN_CODE_SIZE); +} + +// Comparator implementation. +bool operator==(ChainCode const &a, ChainCode const &b) { + return bn_cmp(a.chainCode, b.chainCode) == RLC_EQ; +} + +bool operator!=(ChainCode const &a, ChainCode const &b) { + return !(a == b); +} + +std::ostream &operator<<(std::ostream &os, ChainCode const &s) { + uint8_t buffer[ChainCode::CHAIN_CODE_SIZE]; + s.Serialize(buffer); + return os << Util::HexStr(buffer, ChainCode::CHAIN_CODE_SIZE); +} + +void ChainCode::Serialize(uint8_t *buffer) const { + bn_write_bin(buffer, ChainCode::CHAIN_CODE_SIZE, chainCode); +} + +std::vector ChainCode::Serialize() const { + std::vector data(CHAIN_CODE_SIZE); + Serialize(data.data()); + return data; +} +} // end namespace bls diff --git a/bls/src/chaincode.hpp b/bls/src/chaincode.hpp new file mode 100644 index 00000000..9b19cd18 --- /dev/null +++ b/bls/src/chaincode.hpp @@ -0,0 +1,58 @@ +// Copyright 2018 Chia Network Inc + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_CHAINCODE_HPP_ +#define SRC_CHAINCODE_HPP_ + +#include +#include + +#include "relic_conf.h" + +#if defined GMP && ARITH == GMP +#include +#endif + + +#include "relic.h" +#include "relic_test.h" + +#include "util.hpp" +namespace bls { +class ChainCode { + public: + static const size_t CHAIN_CODE_SIZE = 32; + + static ChainCode FromBytes(const uint8_t* bytes); + + ChainCode(const ChainCode &cc); + + // Comparator implementation. + friend bool operator==(ChainCode const &a, ChainCode const &b); + friend bool operator!=(ChainCode const &a, ChainCode const &b); + friend std::ostream &operator<<(std::ostream &os, ChainCode const &s); + + void Serialize(uint8_t *buffer) const; + std::vector Serialize() const; + + private: + // Prevent direct construction, use static constructor + ChainCode() {} + + bn_t chainCode; +}; +} // end namespace bls + +#endif // SRC_CHAINCODE_HPP_ + diff --git a/bls/src/extendedprivatekey.cpp b/bls/src/extendedprivatekey.cpp new file mode 100644 index 00000000..352ffb16 --- /dev/null +++ b/bls/src/extendedprivatekey.cpp @@ -0,0 +1,203 @@ +// Copyright 2018 Chia Network Inc + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include "extendedprivatekey.hpp" +#include "util.hpp" +#include "bls.hpp" +namespace bls { + +ExtendedPrivateKey ExtendedPrivateKey::FromSeed(const uint8_t* seed, + size_t seedLen) { + // "BLS HD seed" in ascii + const uint8_t prefix[] = {66, 76, 83, 32, 72, 68, 32, 115, 101, 101, 100}; + + uint8_t* hashInput = Util::SecAlloc(seedLen + 1); + std::memcpy(hashInput, seed, seedLen); + + // 32 bytes for secret key, and 32 bytes for chaincode + uint8_t* ILeft = Util::SecAlloc( + PrivateKey::PRIVATE_KEY_SIZE); + uint8_t IRight[ChainCode::CHAIN_CODE_SIZE]; + + // Hash the seed into 64 bytes, half will be sk, half will be cc + hashInput[seedLen] = 0; + md_hmac(ILeft, hashInput, seedLen + 1, prefix, sizeof(prefix)); + + hashInput[seedLen] = 1; + md_hmac(IRight, hashInput, seedLen + 1, prefix, sizeof(prefix)); + + // Make sure private key is less than the curve order + bn_t* skBn = Util::SecAlloc(1); + bn_t order; + bn_new(order); + g1_get_ord(order); + + bn_new(*skBn); + bn_read_bin(*skBn, ILeft, PrivateKey::PRIVATE_KEY_SIZE); + bn_mod_basic(*skBn, *skBn, order); + bn_write_bin(ILeft, PrivateKey::PRIVATE_KEY_SIZE, *skBn); + + ExtendedPrivateKey esk(ExtendedPublicKey::VERSION, 0, 0, 0, + ChainCode::FromBytes(IRight), + PrivateKey::FromBytes(ILeft)); + + Util::SecFree(skBn); + Util::SecFree(ILeft); + Util::SecFree(hashInput); + return esk; +} + +ExtendedPrivateKey ExtendedPrivateKey::FromBytes(const uint8_t* serialized) { + uint32_t version = Util::FourBytesToInt(serialized); + uint32_t depth = serialized[4]; + uint32_t parentFingerprint = Util::FourBytesToInt(serialized + 5); + uint32_t childNumber = Util::FourBytesToInt(serialized + 9); + const uint8_t* ccPointer = serialized + 13; + const uint8_t* skPointer = ccPointer + ChainCode::CHAIN_CODE_SIZE; + + ExtendedPrivateKey esk(version, depth, parentFingerprint, childNumber, + ChainCode::FromBytes(ccPointer), + PrivateKey::FromBytes(skPointer)); + return esk; +} + +ExtendedPrivateKey ExtendedPrivateKey::PrivateChild(uint32_t i) const { + if (depth >= 255) { + throw std::logic_error("Cannot go further than 255 levels"); + } + // Hardened keys have i >= 2^31. Non-hardened have i < 2^31 + uint32_t cmp = (1 << 31); + bool hardened = i >= cmp; + + uint8_t* ILeft = Util::SecAlloc( + PrivateKey::PRIVATE_KEY_SIZE); + uint8_t IRight[ChainCode::CHAIN_CODE_SIZE]; + + // Chain code is used as hmac key + uint8_t hmacKey[ChainCode::CHAIN_CODE_SIZE]; + chainCode.Serialize(hmacKey); + + size_t inputLen = hardened ? PrivateKey::PRIVATE_KEY_SIZE + 4 + 1 + : PublicKey::PUBLIC_KEY_SIZE + 4 + 1; + // Hmac input includes sk or pk, int i, and byte with 0 or 1 + uint8_t* hmacInput = Util::SecAlloc(inputLen); + + // Fill the input with the required data + if (hardened) { + sk.Serialize(hmacInput); + Util::IntToFourBytes(hmacInput + PrivateKey::PRIVATE_KEY_SIZE, i); + } else { + sk.GetPublicKey().Serialize(hmacInput); + Util::IntToFourBytes(hmacInput + PublicKey::PUBLIC_KEY_SIZE, i); + } + hmacInput[inputLen - 1] = 0; + + md_hmac(ILeft, hmacInput, inputLen, + hmacKey, ChainCode::CHAIN_CODE_SIZE); + + // Change 1 byte to generate a different sequence for chaincode + hmacInput[inputLen - 1] = 1; + + md_hmac(IRight, hmacInput, inputLen, + hmacKey, ChainCode::CHAIN_CODE_SIZE); + + PrivateKey newSk = PrivateKey::FromBytes(ILeft, true); + newSk = PrivateKey::AggregateInsecure({sk, newSk}); + + ExtendedPrivateKey esk(version, depth + 1, + sk.GetPublicKey().GetFingerprint(), i, + ChainCode::FromBytes(IRight), + newSk); + + Util::SecFree(ILeft); + Util::SecFree(hmacInput); + + return esk; +} + +uint32_t ExtendedPrivateKey::GetVersion() const { + return version; +} + +uint8_t ExtendedPrivateKey::GetDepth() const { + return depth; +} + +uint32_t ExtendedPrivateKey::GetParentFingerprint() const { + return parentFingerprint; +} + +uint32_t ExtendedPrivateKey::GetChildNumber() const { + return childNumber; +} + +ExtendedPublicKey ExtendedPrivateKey::PublicChild(uint32_t i) const { + return PrivateChild(i).GetExtendedPublicKey(); +} + +PrivateKey ExtendedPrivateKey::GetPrivateKey() const { + return sk; +} + +PublicKey ExtendedPrivateKey::GetPublicKey() const { + return sk.GetPublicKey(); +} + +ChainCode ExtendedPrivateKey::GetChainCode() const { + return chainCode; +} + +ExtendedPublicKey ExtendedPrivateKey::GetExtendedPublicKey() const { + uint8_t buffer[ExtendedPublicKey::EXTENDED_PUBLIC_KEY_SIZE]; + Util::IntToFourBytes(buffer, version); + buffer[4] = depth; + Util::IntToFourBytes(buffer + 5, parentFingerprint); + Util::IntToFourBytes(buffer + 9, childNumber); + + chainCode.Serialize(buffer + 13); + sk.GetPublicKey().Serialize(buffer + 13 + ChainCode::CHAIN_CODE_SIZE); + + return ExtendedPublicKey::FromBytes(buffer); +} + +// Comparator implementation. +bool operator==(ExtendedPrivateKey const &a, ExtendedPrivateKey const &b) { + return (a.GetPrivateKey() == b.GetPrivateKey() && + a.GetChainCode() == b.GetChainCode()); +} + +bool operator!=(ExtendedPrivateKey const&a, ExtendedPrivateKey const&b) { + return !(a == b); +} + +void ExtendedPrivateKey::Serialize(uint8_t *buffer) const { + Util::IntToFourBytes(buffer, version); + buffer[4] = depth; + Util::IntToFourBytes(buffer + 5, parentFingerprint); + Util::IntToFourBytes(buffer + 9, childNumber); + chainCode.Serialize(buffer + 13); + sk.Serialize(buffer + 13 + ChainCode::CHAIN_CODE_SIZE); +} + +std::vector ExtendedPrivateKey::Serialize() const { + std::vector data(EXTENDED_PRIVATE_KEY_SIZE); + Serialize(data.data()); + return data; +} + +// Destructors in PrivateKey and ChainCode handle cleaning of memory +ExtendedPrivateKey::~ExtendedPrivateKey() {} +} // end namespace bls diff --git a/bls/src/extendedprivatekey.hpp b/bls/src/extendedprivatekey.hpp new file mode 100644 index 00000000..52093df3 --- /dev/null +++ b/bls/src/extendedprivatekey.hpp @@ -0,0 +1,109 @@ +// Copyright 2018 Chia Network Inc + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_EXTENDEDPRIVATEKEY_HPP_ +#define SRC_EXTENDEDPRIVATEKEY_HPP_ + +#include "relic_conf.h" + +#include + +#if defined GMP && ARITH == GMP +#include +#endif + +#include "privatekey.hpp" +#include "publickey.hpp" +#include "chaincode.hpp" +#include "extendedpublickey.hpp" + + +#include "relic.h" +#include "relic_test.h" + +namespace bls { +/* +Defines a BIP-32 style node, which is composed of a private key and a +chain code. This follows the spec from BIP-0032, with a few changes: + * The master secret key is generated mod n from the master seed, + since not all 32 byte sequences are valid BLS private keys + * Instead of SHA512(input), do SHA256(input || 00000000) || + SHA256(input || 00000001) + * Mod n for the output of key derivation. + * ID of a key is SHA256(pk) instead of HASH160(pk) + * Serialization of extended public key is 93 bytes +*/ +class ExtendedPrivateKey { + public: + // version(4) depth(1) parent fingerprint(4) child#(4) cc(32) sk(32) + static const uint32_t EXTENDED_PRIVATE_KEY_SIZE = 77; + + // Generates a master private key and chain code from a seed + static ExtendedPrivateKey FromSeed( + const uint8_t* seed, size_t seedLen); + + // Parse private key and chain code from bytes + static ExtendedPrivateKey FromBytes(const uint8_t* serialized); + + // Derive a child extEnded private key, hardened if i >= 2^31 + ExtendedPrivateKey PrivateChild(uint32_t i) const; + + // Derive a child extended public key, hardened if i >= 2^31 + ExtendedPublicKey PublicChild(uint32_t i) const; + + uint32_t GetVersion() const; + uint8_t GetDepth() const; + uint32_t GetParentFingerprint() const; + uint32_t GetChildNumber() const; + + ChainCode GetChainCode() const; + PrivateKey GetPrivateKey() const; + + PublicKey GetPublicKey() const; + ExtendedPublicKey GetExtendedPublicKey() const; + + // Compare to different private key + friend bool operator==(const ExtendedPrivateKey& a, + const ExtendedPrivateKey& b); + friend bool operator!=(const ExtendedPrivateKey& a, + const ExtendedPrivateKey& b); + + void Serialize(uint8_t* buffer) const; + std::vector Serialize() const; + + ~ExtendedPrivateKey(); + + private: + // Private constructor, force use of static methods + explicit ExtendedPrivateKey(const uint32_t v, const uint8_t d, + const uint32_t pfp, const uint32_t cn, + const ChainCode code, const PrivateKey key) + : version(v), + depth(d), + parentFingerprint(pfp), + childNumber(cn), + chainCode(code), + sk(key) {} + + const uint32_t version; + const uint8_t depth; + const uint32_t parentFingerprint; + const uint32_t childNumber; + + const ChainCode chainCode; + const PrivateKey sk; +}; +} // end namespace bls + +#endif // SRC_EXTENDEDPRIVATEKEY_HPP_ diff --git a/bls/src/extendedpublickey.cpp b/bls/src/extendedpublickey.cpp new file mode 100644 index 00000000..d6c93f52 --- /dev/null +++ b/bls/src/extendedpublickey.cpp @@ -0,0 +1,136 @@ +// Copyright 2018 Chia Network Inc + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include "extendedpublickey.hpp" +#include "extendedprivatekey.hpp" +#include "util.hpp" +#include "bls.hpp" +namespace bls { + +ExtendedPublicKey ExtendedPublicKey::FromBytes( + const uint8_t* serialized) { + uint32_t version = Util::FourBytesToInt(serialized); + uint32_t depth = serialized[4]; + uint32_t parentFingerprint = Util::FourBytesToInt(serialized + 5); + uint32_t childNumber = Util::FourBytesToInt(serialized + 9); + const uint8_t* ccPointer = serialized + 13; + const uint8_t* pkPointer = ccPointer + ChainCode::CHAIN_CODE_SIZE; + + ExtendedPublicKey epk(version, depth, parentFingerprint, childNumber, + ChainCode::FromBytes(ccPointer), + PublicKey::FromBytes(pkPointer)); + return epk; +} + +ExtendedPublicKey ExtendedPublicKey::PublicChild(uint32_t i) const { + // Hardened children have i >= 2^31. Non-hardened have i < 2^31 + uint32_t cmp = (1 << 31); + if (i >= cmp) { + throw std::invalid_argument("Cannot derive hardened children from public key"); + } + if (depth >= 255) { + throw std::logic_error("Cannot go further than 255 levels"); + } + uint8_t ILeft[PrivateKey::PRIVATE_KEY_SIZE]; + uint8_t IRight[ChainCode::CHAIN_CODE_SIZE]; + + // Chain code is used as hmac key + uint8_t hmacKey[ChainCode::CHAIN_CODE_SIZE]; + chainCode.Serialize(hmacKey); + + // Public key serialization, i serialization, and one 0 or 1 byte + size_t inputLen = PublicKey::PUBLIC_KEY_SIZE + 4 + 1; + + // Hmac input includes sk or pk, int i, and byte with 0 or 1 + uint8_t hmacInput[PublicKey::PUBLIC_KEY_SIZE + 4 + 1]; + + // Fill the input with the required data + pk.Serialize(hmacInput); + hmacInput[inputLen - 1] = 0; + Util::IntToFourBytes(hmacInput + PublicKey::PUBLIC_KEY_SIZE, i); + + md_hmac(ILeft, hmacInput, inputLen, + hmacKey, ChainCode::CHAIN_CODE_SIZE); + + // Change 1 byte to generate a different sequence for chaincode + hmacInput[inputLen - 1] = 1; + + md_hmac(IRight, hmacInput, inputLen, + hmacKey, ChainCode::CHAIN_CODE_SIZE); + + PrivateKey leftSk = PrivateKey::FromBytes(ILeft, true); + PublicKey newPk = PublicKey::AggregateInsecure({pk, leftSk.GetPublicKey()}); + + ExtendedPublicKey epk(version, depth + 1, + GetPublicKey().GetFingerprint(), i, + ChainCode::FromBytes(IRight), + newPk); + + return epk; +} + +uint32_t ExtendedPublicKey::GetVersion() const { + return version; +} + +uint8_t ExtendedPublicKey::GetDepth() const { + return depth; +} + +uint32_t ExtendedPublicKey::GetParentFingerprint() const { + return parentFingerprint; +} + +uint32_t ExtendedPublicKey::GetChildNumber() const { + return childNumber; +} + +ChainCode ExtendedPublicKey::GetChainCode() const { + return chainCode; +} + +PublicKey ExtendedPublicKey::GetPublicKey() const { + return pk; +} + +// Comparator implementation. +bool operator==(ExtendedPublicKey const &a, ExtendedPublicKey const &b) { + return (a.GetPublicKey() == b.GetPublicKey() && + a.GetChainCode() == b.GetChainCode()); +} + +bool operator!=(ExtendedPublicKey const&a, ExtendedPublicKey const&b) { + return !(a == b); +} + +std::ostream &operator<<(std::ostream &os, ExtendedPublicKey const &a) { + return os << a.GetPublicKey() << a.GetChainCode(); +} + +void ExtendedPublicKey::Serialize(uint8_t *buffer) const { + Util::IntToFourBytes(buffer, version); + buffer[4] = depth; + Util::IntToFourBytes(buffer + 5, parentFingerprint); + Util::IntToFourBytes(buffer + 9, childNumber); + chainCode.Serialize(buffer + 13); + pk.Serialize(buffer + 13 + ChainCode::CHAIN_CODE_SIZE); +} + +std::vector ExtendedPublicKey::Serialize() const { + std::vector data(EXTENDED_PUBLIC_KEY_SIZE); + Serialize(data.data()); + return data; +} +} // end namespace bls diff --git a/bls/src/extendedpublickey.hpp b/bls/src/extendedpublickey.hpp new file mode 100644 index 00000000..c69a2430 --- /dev/null +++ b/bls/src/extendedpublickey.hpp @@ -0,0 +1,100 @@ +// Copyright 2018 Chia Network Inc + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_EXTENDEDPUBLICKEY_HPP_ +#define SRC_EXTENDEDPUBLICKEY_HPP_ + +#include "relic_conf.h" + +#include + +#if defined GMP && ARITH == GMP +#include +#endif + +#include "publickey.hpp" +#include "chaincode.hpp" + + +#include "relic.h" +#include "relic_test.h" + +namespace bls { + +/* +Defines a BIP-32 style node, which is composed of a private key and a +chain code. This follows the spec from BIP-0032, with a few changes: + * The master secret key is generated mod n from the master seed, + since not all 32 byte sequences are valid BLS private keys + * Instead of SHA512(input), do SHA256(input || 00000000) || + SHA256(input || 00000001) + * Mod n for the output of key derivation. + * ID of a key is SHA256(pk) instead of HASH160(pk) + * Serialization of extended public key is 93 bytes +*/ +class ExtendedPublicKey { + public: + static const uint32_t VERSION = 1; + + // version(4) depth(1) parent fingerprint(4) child#(4) cc(32) pk(48) + static const uint32_t EXTENDED_PUBLIC_KEY_SIZE = 93; + + // Parse public key and chain code from bytes + static ExtendedPublicKey FromBytes(const uint8_t* serialized); + + // Derive a child extended public key, cannot be hardened + ExtendedPublicKey PublicChild(uint32_t i) const; + + uint32_t GetVersion() const; + uint8_t GetDepth() const; + uint32_t GetParentFingerprint() const; + uint32_t GetChildNumber() const; + + ChainCode GetChainCode() const; + PublicKey GetPublicKey() const; + + // Comparator implementation. + friend bool operator==(ExtendedPublicKey const &a, + ExtendedPublicKey const &b); + friend bool operator!=(ExtendedPublicKey const &a, + ExtendedPublicKey const &b); + friend std::ostream &operator<<(std::ostream &os, + ExtendedPublicKey const &s); + + void Serialize(uint8_t *buffer) const; + std::vector Serialize() const; + + private: + // private constructor, force use of static methods + explicit ExtendedPublicKey(const uint32_t v, const uint8_t d, + const uint32_t pfp, const uint32_t cn, + const ChainCode code, const PublicKey key) + : version(v), + depth(d), + parentFingerprint(pfp), + childNumber(cn), + chainCode(code), + pk(key) {} + + const uint32_t version; + const uint8_t depth; + const uint32_t parentFingerprint; + const uint32_t childNumber; + + const ChainCode chainCode; + const PublicKey pk; +}; +} // end namespace bls + +#endif // SRC_EXTENDEDPUBLICKEY_HPP_ diff --git a/bls/src/privatekey.cpp b/bls/src/privatekey.cpp new file mode 100644 index 00000000..d9ce43d4 --- /dev/null +++ b/bls/src/privatekey.cpp @@ -0,0 +1,261 @@ +// Copyright 2018 Chia Network Inc + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include + +#include "bls.hpp" +#include "util.hpp" +#include "privatekey.hpp" + +namespace bls { +PrivateKey PrivateKey::FromSeed(const uint8_t* seed, size_t seedLen) { + // "BLS private key seed" in ascii + const uint8_t hmacKey[] = {66, 76, 83, 32, 112, 114, 105, 118, 97, 116, 101, + 32, 107, 101, 121, 32, 115, 101, 101, 100}; + + uint8_t* hash = Util::SecAlloc( + PrivateKey::PRIVATE_KEY_SIZE); + + // Hash the seed into sk + md_hmac(hash, seed, seedLen, hmacKey, sizeof(hmacKey)); + + bn_t order; + bn_new(order); + g1_get_ord(order); + bn_free(order); + + // Make sure private key is less than the curve order + bn_t* skBn = Util::SecAlloc(1); + bn_new(*skBn); + bn_read_bin(*skBn, hash, PrivateKey::PRIVATE_KEY_SIZE); + bn_mod_basic(*skBn, *skBn, order); + + PrivateKey k; + k.AllocateKeyData(); + bn_copy(*k.keydata, *skBn); + + Util::SecFree(skBn); + Util::SecFree(hash); + + return k; +} + +// Construct a private key from a bytearray. +PrivateKey PrivateKey::FromBytes(const uint8_t* bytes, bool modOrder) { + PrivateKey k; + k.AllocateKeyData(); + bn_read_bin(*k.keydata, bytes, PrivateKey::PRIVATE_KEY_SIZE); + bn_t ord; + bn_new(ord); + g1_get_ord(ord); + if (modOrder) { + bn_mod_basic(*k.keydata, *k.keydata, ord); + } else { + if (bn_cmp(*k.keydata, ord) > 0) { + throw std::invalid_argument("Key data too large, must be smaller than group order"); + } + } + return k; +} + +PrivateKey PrivateKey::FromBN(bn_t sk) { + PrivateKey k; + k.AllocateKeyData(); + bn_copy(*k.keydata, sk); + return k; +} + +// Construct a private key from another private key. +PrivateKey::PrivateKey(const PrivateKey &privateKey) { + AllocateKeyData(); + bn_copy(*keydata, *privateKey.keydata); +} + +PrivateKey::PrivateKey(PrivateKey&& k) { + std::swap(keydata, k.keydata); +} + +PrivateKey::~PrivateKey() { + Util::SecFree(keydata); +} + +PublicKey PrivateKey::GetPublicKey() const { + g1_t *q = Util::SecAlloc(1); + g1_mul_gen(*q, *keydata); + + const PublicKey ret = PublicKey::FromG1(q); + Util::SecFree(*q); + return ret; +} + +PrivateKey PrivateKey::AggregateInsecure(std::vector const& privateKeys) { + if (privateKeys.empty()) { + throw std::length_error("Number of private keys must be at least 1"); + } + + bn_t order; + bn_new(order); + g1_get_ord(order); + + PrivateKey ret(privateKeys[0]); + for (size_t i = 1; i < privateKeys.size(); i++) { + bn_add(*ret.keydata, *ret.keydata, *privateKeys[i].keydata); + bn_mod_basic(*ret.keydata, *ret.keydata, order); + } + return ret; +} + +PrivateKey PrivateKey::Aggregate(std::vector const& privateKeys, + std::vector const& pubKeys) { + if (pubKeys.size() != privateKeys.size()) { + throw std::length_error("Number of public keys must equal number of private keys"); + } + if (privateKeys.empty()) { + throw std::length_error("Number of keys must be at least 1"); + } + + std::vector serPubKeys(pubKeys.size()); + for (size_t i = 0; i < pubKeys.size(); i++) { + serPubKeys[i] = new uint8_t[PublicKey::PUBLIC_KEY_SIZE]; + pubKeys[i].Serialize(serPubKeys[i]); + } + + // Sort the public keys and private keys by public key + std::vector keysSorted(privateKeys.size()); + for (size_t i = 0; i < privateKeys.size(); i++) { + keysSorted[i] = i; + } + + std::sort(keysSorted.begin(), keysSorted.end(), [&serPubKeys](size_t a, size_t b) { + return memcmp(serPubKeys[a], serPubKeys[b], PublicKey::PUBLIC_KEY_SIZE) < 0; + }); + + + bn_t *computedTs = new bn_t[keysSorted.size()]; + for (size_t i = 0; i < keysSorted.size(); i++) { + bn_new(computedTs[i]); + } + BLS::HashPubKeys(computedTs, keysSorted.size(), serPubKeys, keysSorted); + + // Raise all keys to power of the corresponding t's and aggregate the results into aggKey + std::vector expKeys; + expKeys.reserve(keysSorted.size()); + for (size_t i = 0; i < keysSorted.size(); i++) { + auto& k = privateKeys[keysSorted[i]]; + expKeys.emplace_back(k.Mul(computedTs[i])); + } + PrivateKey aggKey = PrivateKey::AggregateInsecure(expKeys); + + for (auto p : serPubKeys) { + delete[] p; + } + delete[] computedTs; + + BLS::CheckRelicErrors(); + return aggKey; +} + +PrivateKey PrivateKey::Mul(const bn_t n) const { + bn_t order; + bn_new(order); + g2_get_ord(order); + + PrivateKey ret; + ret.AllocateKeyData(); + bn_mul_comba(*ret.keydata, *keydata, n); + bn_mod_basic(*ret.keydata, *ret.keydata, order); + return ret; +} + +bool operator==(const PrivateKey& a, const PrivateKey& b) { + return bn_cmp(*a.keydata, *b.keydata) == RLC_EQ; +} + +bool operator!=(const PrivateKey& a, const PrivateKey& b) { + return !(a == b); +} + +PrivateKey& PrivateKey::operator=(const PrivateKey &rhs) { + Util::SecFree(keydata); + AllocateKeyData(); + bn_copy(*keydata, *rhs.keydata); + return *this; +} + +void PrivateKey::Serialize(uint8_t* buffer) const { + bn_write_bin(buffer, PrivateKey::PRIVATE_KEY_SIZE, *keydata); +} + +std::vector PrivateKey::Serialize() const { + std::vector data(PRIVATE_KEY_SIZE); + Serialize(data.data()); + return data; +} + +InsecureSignature PrivateKey::SignInsecure(const uint8_t *msg, size_t len) const { + uint8_t messageHash[BLS::MESSAGE_HASH_LEN]; + Util::Hash256(messageHash, msg, len); + return SignInsecurePrehashed(messageHash); +} + +InsecureSignature PrivateKey::SignInsecurePrehashed(const uint8_t *messageHash) const { + g2_t sig, point; + + g2_map(point, messageHash, BLS::MESSAGE_HASH_LEN, 0); + g2_mul(sig, point, *keydata); + + return InsecureSignature::FromG2(&sig); +} + +Signature PrivateKey::Sign(const uint8_t *msg, size_t len) const { + uint8_t messageHash[BLS::MESSAGE_HASH_LEN]; + Util::Hash256(messageHash, msg, len); + return SignPrehashed(messageHash); +} + +Signature PrivateKey::SignPrehashed(const uint8_t *messageHash) const { + InsecureSignature insecureSig = SignInsecurePrehashed(messageHash); + Signature ret = Signature::FromInsecureSig(insecureSig); + + ret.SetAggregationInfo(AggregationInfo::FromMsgHash(GetPublicKey(), + messageHash)); + + return ret; +} + +PrependSignature PrivateKey::SignPrepend(const uint8_t *msg, size_t len) const { + uint8_t messageHash[BLS::MESSAGE_HASH_LEN]; + Util::Hash256(messageHash, msg, len); + return SignPrependPrehashed(messageHash); +} + +PrependSignature PrivateKey::SignPrependPrehashed(const uint8_t *messageHash) const { + uint8_t finalMessage[PublicKey::PUBLIC_KEY_SIZE + BLS::MESSAGE_HASH_LEN]; + GetPublicKey().Serialize(finalMessage); + memcpy(finalMessage + PublicKey::PUBLIC_KEY_SIZE, messageHash, BLS::MESSAGE_HASH_LEN); + + uint8_t finalMessageHash[BLS::MESSAGE_HASH_LEN]; + Util::Hash256(finalMessageHash, finalMessage, PublicKey::PUBLIC_KEY_SIZE + BLS::MESSAGE_HASH_LEN); + + return PrependSignature::FromInsecureSig(SignInsecurePrehashed(finalMessageHash)); +} + +void PrivateKey::AllocateKeyData() { + keydata = Util::SecAlloc(1); + bn_new(*keydata); // Freed in destructor + bn_zero(*keydata); +} +} // end namespace bls diff --git a/bls/src/privatekey.hpp b/bls/src/privatekey.hpp new file mode 100644 index 00000000..1ba62576 --- /dev/null +++ b/bls/src/privatekey.hpp @@ -0,0 +1,103 @@ +// Copyright 2018 Chia Network Inc + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_BLSPRIVATEKEY_HPP_ +#define SRC_BLSPRIVATEKEY_HPP_ + +#include "relic_conf.h" + +#if defined GMP && ARITH == GMP +#include +#endif + +#include "publickey.hpp" +#include "signature.hpp" +namespace bls { +class PrivateKey { +friend class BLS; +friend class Threshold; + public: + // Private keys are represented as 32 byte field elements. Note that + // not all 32 byte integers are valid keys, the private key must be + // less than the group order (which is in bls.hpp). + static const size_t PRIVATE_KEY_SIZE = 32; + + // Generates a private key from a seed, similar to HD key generation + // (hashes the seed), and reduces it mod the group order. + static PrivateKey FromSeed( + const uint8_t* seed, size_t seedLen); + + // Construct a private key from a bytearray. + static PrivateKey FromBytes(const uint8_t* bytes, bool modOrder = false); + + // Construct a private key from a native bn element. + static PrivateKey FromBN(bn_t sk); + + // Construct a private key from another private key. Allocates memory in + // secure heap, and copies keydata. + PrivateKey(const PrivateKey& k); + PrivateKey(PrivateKey&& k); + + ~PrivateKey(); + + PublicKey GetPublicKey() const; + + // Insecurely aggregate multiple private keys into one + static PrivateKey AggregateInsecure(std::vector const& privateKeys); + + // Securely aggregate multiple private keys into one by exponentiating the keys with the pubKey hashes first + static PrivateKey Aggregate(std::vector const& privateKeys, + std::vector const& pubKeys); + + // Compare to different private key + friend bool operator==(const PrivateKey& a, const PrivateKey& b); + friend bool operator!=(const PrivateKey& a, const PrivateKey& b); + PrivateKey& operator=(const PrivateKey& rhs); + + // Serialize the key into bytes + void Serialize(uint8_t* buffer) const; + std::vector Serialize() const; + + // Sign a message without setting aggreagation info. + InsecureSignature SignInsecure(const uint8_t *msg, size_t len) const; + InsecureSignature SignInsecurePrehashed(const uint8_t *hash) const; + + // The secure Signing variants, which also set and return appropriate aggregation info. + Signature Sign(const uint8_t *msg, size_t len) const; + Signature SignPrehashed(const uint8_t *hash) const; + + // Helper methods to prepend the public key to the message, allowing secure + // aggregation by proof of posession of public key. These must be verified using + // VerifyPrepend. These signatures are identical to Insecure signatures, but are generated + // and verified by prepending the pulic keys: Sign(H(pk + H(m))). + PrependSignature SignPrepend(const uint8_t *msg, size_t len) const; + PrependSignature SignPrependPrehashed(const uint8_t *msg) const; + + private: + // Don't allow public construction, force static methods + PrivateKey() {} + + // Multiply private key with n + PrivateKey Mul(const bn_t n) const; + + // Allocate memory for private key + void AllocateKeyData(); + + private: + // The actual byte data + bn_t *keydata{nullptr}; +}; +} // end namespace bls + +#endif // SRC_BLSPRIVATEKEY_HPP_ diff --git a/bls/src/publickey.cpp b/bls/src/publickey.cpp new file mode 100644 index 00000000..742c699f --- /dev/null +++ b/bls/src/publickey.cpp @@ -0,0 +1,158 @@ +// Copyright 2018 Chia Network Inc + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include + +#include "publickey.hpp" +#include "util.hpp" +#include "bls.hpp" + +namespace bls { +PublicKey PublicKey::FromBytes(const uint8_t * key) { + PublicKey pk = PublicKey(); + uint8_t uncompressed[PUBLIC_KEY_SIZE + 1]; + std::memcpy(uncompressed + 1, key, PUBLIC_KEY_SIZE); + if (key[0] & 0x80) { + uncompressed[0] = 0x03; // Insert extra byte for Y=1 + uncompressed[1] &= 0x7f; // Remove initial Y bit + } else { + uncompressed[0] = 0x02; // Insert extra byte for Y=0 + } + g1_read_bin(pk.q, uncompressed, PUBLIC_KEY_SIZE + 1); + BLS::CheckRelicErrorsInvalidArgument(); + return pk; +} + +PublicKey PublicKey::FromG1(const g1_t* pubKey) { + PublicKey pk = PublicKey(); + g1_copy(pk.q, *pubKey); + return pk; +} + +PublicKey::PublicKey() { + g1_set_infty(q); +} + +PublicKey::PublicKey(const PublicKey &pubKey) { + g1_copy(q, pubKey.q); +} + +PublicKey PublicKey::AggregateInsecure(std::vector const& pubKeys) { + if (pubKeys.empty()) { + throw std::length_error("Number of public keys must be at least 1"); + } + + PublicKey ret = pubKeys[0]; + for (size_t i = 1; i < pubKeys.size(); i++) { + g1_add(ret.q, ret.q, pubKeys[i].q); + } + return ret; +} + +PublicKey PublicKey::Aggregate(std::vector const& pubKeys) { + if (pubKeys.size() < 1) { + throw std::length_error("Number of public keys must be at least 1"); + } + + std::vector serPubKeys(pubKeys.size()); + for (size_t i = 0; i < pubKeys.size(); i++) { + serPubKeys[i] = new uint8_t[PublicKey::PUBLIC_KEY_SIZE]; + pubKeys[i].Serialize(serPubKeys[i]); + } + + // Sort the public keys by public key + std::vector pubKeysSorted(pubKeys.size()); + for (size_t i = 0; i < pubKeysSorted.size(); i++) { + pubKeysSorted[i] = i; + } + + std::sort(pubKeysSorted.begin(), pubKeysSorted.end(), [&serPubKeys](size_t a, size_t b) { + return memcmp(serPubKeys[a], serPubKeys[b], PublicKey::PUBLIC_KEY_SIZE) < 0; + }); + + bn_t *computedTs = new bn_t[pubKeysSorted.size()]; + for (size_t i = 0; i < pubKeysSorted.size(); i++) { + bn_new(computedTs[i]); + } + BLS::HashPubKeys(computedTs, pubKeysSorted.size(), serPubKeys, pubKeysSorted); + + // Raise all keys to power of the corresponding t's and aggregate the results into aggKey + std::vector expKeys; + expKeys.reserve(pubKeysSorted.size()); + for (size_t i = 0; i < pubKeysSorted.size(); i++) { + const PublicKey& pk = pubKeys[pubKeysSorted[i]]; + expKeys.emplace_back(pk.Exp(computedTs[i])); + } + PublicKey aggKey = PublicKey::AggregateInsecure(expKeys); + + for (auto p : serPubKeys) { + delete[] p; + } + delete[] computedTs; + + BLS::CheckRelicErrors(); + return aggKey; +} + +PublicKey PublicKey::Exp(bn_t const n) const { + PublicKey ret; + g1_mul(ret.q, const_cast(q), const_cast(n)); + return ret; +} + +void PublicKey::Serialize(uint8_t *buffer) const { + CompressPoint(buffer, &q); +} + +std::vector PublicKey::Serialize() const { + std::vector data(PUBLIC_KEY_SIZE); + Serialize(data.data()); + return data; +} + +// Comparator implementation. +bool operator==(PublicKey const &a, PublicKey const &b) { + return g1_cmp(a.q, b.q) == RLC_EQ; +} + +bool operator!=(PublicKey const&a, PublicKey const&b) { + return !(a == b); +} + +std::ostream &operator<<(std::ostream &os, PublicKey const &pk) { + uint8_t data[PublicKey::PUBLIC_KEY_SIZE]; + pk.Serialize(data); + return os << Util::HexStr(data, PublicKey::PUBLIC_KEY_SIZE); +} + +uint32_t PublicKey::GetFingerprint() const { + uint8_t buffer[PublicKey::PUBLIC_KEY_SIZE]; + uint8_t hash[32]; + Serialize(buffer); + Util::Hash256(hash, buffer, PublicKey::PUBLIC_KEY_SIZE); + return Util::FourBytesToInt(hash); +} + +void PublicKey::CompressPoint(uint8_t* result, const g1_t* point) { + uint8_t buffer[PublicKey::PUBLIC_KEY_SIZE + 1]; + g1_write_bin(buffer, PublicKey::PUBLIC_KEY_SIZE + 1, *point, 1); + + if (buffer[0] == 0x03) { + buffer[1] |= 0x80; + } + std::memcpy(result, buffer + 1, PUBLIC_KEY_SIZE); +} +} // end namespace bls diff --git a/bls/src/publickey.hpp b/bls/src/publickey.hpp new file mode 100644 index 00000000..938d57c5 --- /dev/null +++ b/bls/src/publickey.hpp @@ -0,0 +1,80 @@ +// Copyright 2018 Chia Network Inc + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_BLSPUBLICKEY_HPP_ +#define SRC_BLSPUBLICKEY_HPP_ + +#include +#include + +#include "relic_conf.h" + +#if defined GMP && ARITH == GMP +#include +#endif + +#include "util.hpp" +namespace bls { +/** An encapsulated public key. */ +class PublicKey { + friend class InsecureSignature; + friend class Signature; + friend class ExtendedPublicKey; + friend class Threshold; + friend class BLS; + public: + static const size_t PUBLIC_KEY_SIZE = 48; + + // Construct a public key from a byte vector. + static PublicKey FromBytes(const uint8_t* key); + + // Construct a public key from a native g1 element. + static PublicKey FromG1(const g1_t* key); + + // Construct a public key from another public key. + PublicKey(const PublicKey &pubKey); + + // Insecurely aggregate multiple public keys into one + static PublicKey AggregateInsecure(std::vector const& pubKeys); + + // Securely aggregate multiple public keys into one by exponentiating the keys with the pubKey hashes first + static PublicKey Aggregate(std::vector const& pubKeys); + + // Comparator implementation. + friend bool operator==(PublicKey const &a, PublicKey const &b); + friend bool operator!=(PublicKey const &a, PublicKey const &b); + friend std::ostream &operator<<(std::ostream &os, PublicKey const &s); + + void Serialize(uint8_t *buffer) const; + std::vector Serialize() const; + + // Returns the first 4 bytes of the serialized pk + uint32_t GetFingerprint() const; + + private: + // Don't allow public construction, force static methods + PublicKey(); + + // Exponentiate public key with n + PublicKey Exp(const bn_t n) const; + + static void CompressPoint(uint8_t* result, const g1_t* point); + + private: + // Public key group element + g1_t q; +}; + +} // end namespace bls +#endif // SRC_BLSPUBLICKEY_HPP_ diff --git a/bls/src/signature.cpp b/bls/src/signature.cpp new file mode 100644 index 00000000..abff50b4 --- /dev/null +++ b/bls/src/signature.cpp @@ -0,0 +1,773 @@ +// Copyright 2018 Chia Network Inc + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include + +#include "signature.hpp" +#include "bls.hpp" + +using std::string; +namespace bls { +InsecureSignature InsecureSignature::FromBytes(const uint8_t *data) { + InsecureSignature sigObj = InsecureSignature(); + uint8_t uncompressed[SIGNATURE_SIZE + 1]; + std::memcpy(uncompressed + 1, data, SIGNATURE_SIZE); + if (data[0] & 0x80) { + uncompressed[0] = 0x03; // Insert extra byte for Y=1 + uncompressed[1] &= 0x7f; // Remove initial Y bit + } else { + uncompressed[0] = 0x02; // Insert extra byte for Y=0 + } + g2_read_bin(sigObj.sig, uncompressed, SIGNATURE_SIZE + 1); + BLS::CheckRelicErrorsInvalidArgument(); + return sigObj; +} + +InsecureSignature InsecureSignature::FromG2(const g2_t* element) { + InsecureSignature sigObj = InsecureSignature(); + g2_copy(sigObj.sig, *(g2_t*)element); + return sigObj; +} + +InsecureSignature::InsecureSignature() { + g2_set_infty(sig); +} + +InsecureSignature::InsecureSignature(const InsecureSignature &signature) { + g2_copy(sig, *(g2_t*)&signature.sig); +} + +bool InsecureSignature::Verify(const std::vector& hashes, + const std::vector& pubKeys) const { + if (hashes.size() != pubKeys.size() || hashes.empty()) { + throw std::invalid_argument("hashes and pubKeys vectors must be of same size and non-empty"); + } + + g1_t *pubKeysNative = new g1_t[hashes.size() + 1]; + g2_t *mappedHashes = new g2_t[hashes.size() + 1]; + + g2_copy(mappedHashes[0], *(g2_t *) &sig); + g1_get_gen(pubKeysNative[0]); + bn_t ordMinus1; + bn_new(ordMinus1); + g1_get_ord(ordMinus1); + bn_sub_dig(ordMinus1, ordMinus1, 1); + g1_mul(pubKeysNative[0], pubKeysNative[0], ordMinus1); + + for (size_t i = 0; i < hashes.size(); i++) { g2_map(mappedHashes[i + 1], hashes[i], BLS::MESSAGE_HASH_LEN, 0); + g1_copy(pubKeysNative[i + 1], pubKeys[i].q); + } + + bool result = VerifyNative(pubKeysNative, mappedHashes, hashes.size() + 1); + + delete[] pubKeysNative; + delete[] mappedHashes; + + return result; +} + +bool InsecureSignature::VerifyNative( + g1_t* pubKeys, + g2_t* mappedHashes, + size_t len) { + gt_t target, candidate; + + // Target = 1 + fp12_zero(target); + fp_set_dig(target[0][0][0], 1); + + // prod e(pubkey[i], hash[i]) * e(-1 * g1, aggSig) + // Performs pubKeys.size() pairings + pc_map_sim(candidate, pubKeys, mappedHashes, len); + + // 1 =? prod e(pubkey[i], hash[i]) * e(g1, aggSig) + if (gt_cmp(target, candidate) != RLC_EQ || + core_get()->code != RLC_OK) { + core_get()->code = RLC_OK; + return false; + } + BLS::CheckRelicErrors(); + return true; +} + +InsecureSignature InsecureSignature::Aggregate(const std::vector& sigs) { + if (sigs.empty()) { + throw std::length_error("sigs must not be empty"); + } + InsecureSignature result = sigs[0]; + for (size_t i = 1; i < sigs.size(); i++) { + g2_add(result.sig, result.sig, *(g2_t*)&sigs[i].sig); + } + return result; +} + +InsecureSignature InsecureSignature::DivideBy(const std::vector& sigs) const { + if (sigs.empty()) { + return *this; + } + + InsecureSignature tmpAgg = Aggregate(sigs); + InsecureSignature result(*this); + g2_sub(result.sig, result.sig, tmpAgg.sig); + return result; +} + +InsecureSignature InsecureSignature::Exp(const bn_t n) const { + InsecureSignature result(*this); + g2_mul(result.sig, result.sig, const_cast(n)); + return result; +} + +void InsecureSignature::Serialize(uint8_t* buffer) const { + CompressPoint(buffer, &sig); +} + +std::vector InsecureSignature::Serialize() const { + std::vector data(SIGNATURE_SIZE); + Serialize(data.data()); + return data; +} + +bool operator==(InsecureSignature const &a, InsecureSignature const &b) { + return g2_cmp(*(g2_t*)&a.sig, *(g2_t*)b.sig) == RLC_EQ; +} + +bool operator!=(InsecureSignature const &a, InsecureSignature const &b) { + return !(a == b); +} + +std::ostream &operator<<(std::ostream &os, InsecureSignature const &s) { + uint8_t data[InsecureSignature::SIGNATURE_SIZE]; + s.Serialize(data); + return os << Util::HexStr(data, InsecureSignature::SIGNATURE_SIZE); +} + +InsecureSignature& InsecureSignature::operator=(const InsecureSignature &rhs) { + g2_copy(sig, *(g2_t*)&rhs.sig); + return *this; +} + +void InsecureSignature::CompressPoint(uint8_t* result, const g2_t* point) { + uint8_t buffer[InsecureSignature::SIGNATURE_SIZE + 1]; + g2_write_bin(buffer, InsecureSignature::SIGNATURE_SIZE + 1, *(g2_t*)point, 1); + + if (buffer[0] == 0x03) { + buffer[1] |= 0x80; + } + std::memcpy(result, buffer + 1, SIGNATURE_SIZE); +} + +/// Signature + +Signature Signature::FromBytes(const uint8_t* data) { + if ((data[0] & 0x40) > 0) { + throw std::invalid_argument("Invalid signature. Second bit is set, so it's a PrependSignature."); + } + Signature result; + result.sig = InsecureSignature::FromBytes(data); + return result; +} + +Signature Signature::FromBytes(const uint8_t *data, const AggregationInfo &info) { + if ((data[0] & 0x40) > 0) { + throw std::invalid_argument("Invalid signature. Second bit is set, so it's a PrependSignature."); + } + + Signature ret = FromBytes(data); + ret.SetAggregationInfo(info); + return ret; +} + +Signature Signature::FromG2(const g2_t* element) { + Signature result; + result.sig = InsecureSignature::FromG2(element); + return result; +} + +Signature Signature::FromG2(const g2_t* element, const AggregationInfo& info) { + Signature ret = FromG2(element); + ret.SetAggregationInfo(info); + return ret; +} + +Signature Signature::FromInsecureSig(const InsecureSignature& sig) { + return FromG2(&sig.sig); +} + +Signature Signature::FromInsecureSig(const InsecureSignature& sig, const AggregationInfo& info) { + return FromG2(&sig.sig, info); +} + +Signature::Signature(const Signature &_signature) + : sig(_signature.sig), + aggregationInfo(_signature.aggregationInfo) { +} + +const AggregationInfo* Signature::GetAggregationInfo() const { + return &aggregationInfo; +} + +void Signature::SetAggregationInfo( + const AggregationInfo &newAggregationInfo) { + aggregationInfo = newAggregationInfo; +} + +void Signature::Serialize(uint8_t* buffer) const { + sig.Serialize(buffer); +} + +std::vector Signature::Serialize() const { + return sig.Serialize(); +} + +InsecureSignature Signature::GetInsecureSig() const { + return sig; +} + +bool operator==(Signature const &a, Signature const &b) { + return a.sig == b.sig; +} + +bool operator!=(Signature const &a, Signature const &b) { + return !(a == b); +} + +std::ostream &operator<<(std::ostream &os, Signature const &s) { + uint8_t data[InsecureSignature::SIGNATURE_SIZE]; + s.Serialize(data); + return os << Util::HexStr(data, InsecureSignature::SIGNATURE_SIZE); +} + +/* + * This implementation of verify has several steps. First, it + * reorganizes the pubkeys and messages into groups, where + * each group corresponds to a message. Then, it checks if the + * siganture has info on how it was aggregated. If so, we + * exponentiate each pk based on the exponent in the AggregationInfo. + * If not, we find public keys that share messages with others, + * and aggregate all of these securely (with exponents.). + * Finally, since each public key now corresponds to a unique + * message (since we grouped them), we can verify using the + * distinct verification procedure. + */ +bool Signature::Verify() const { + if (GetAggregationInfo()->Empty()) { + return false; + } + + std::vector pubKeys = GetAggregationInfo() + ->GetPubKeys(); + std::vector messageHashes = GetAggregationInfo() + ->GetMessageHashes(); + if (pubKeys.size() != messageHashes.size()) { + return false; + } + + // Group all of the messages that are idential, with the + // pubkeys and signatures, the std::maps's key is the message hash + std::map, + Util::BytesCompare32> hashToPubKeys; + + for (size_t i = 0; i < messageHashes.size(); i++) { + auto pubKeyIter = hashToPubKeys.find(messageHashes[i]); + if (pubKeyIter != hashToPubKeys.end()) { + // Already one identical message, so push to vector + pubKeyIter->second.push_back(pubKeys[i]); + } else { + // First time seeing this message, so create a vector + std::vector newPubKey = {pubKeys[i]}; + hashToPubKeys.insert(make_pair(messageHashes[i], newPubKey)); + } + } + + // Aggregate pubkeys of identical messages + std::vector finalPubKeys; + std::vector finalMessageHashes; + std::vector collidingKeys; + + for (const auto &kv : hashToPubKeys) { + PublicKey prod; + std::map> dedupMap; + for (size_t i = 0; i < kv.second.size(); i++) { + const PublicKey& pk = kv.second[i]; + uint8_t *k = new uint8_t[PublicKey::PUBLIC_KEY_SIZE]; + pk.Serialize(k); + dedupMap.emplace(k, i); + } + + for (const auto &kv2 : dedupMap) { + const PublicKey& pk = kv.second[kv2.second]; + + bn_t exponent; + bn_new(exponent); + try { + GetAggregationInfo()->GetExponent(&exponent, kv.first, pk); + } catch (std::out_of_range) { + for (auto &p : dedupMap) { + delete[] p.first; + } + return false; + } + prod = PublicKey::AggregateInsecure({prod, pk.Exp(exponent)}); + } + finalPubKeys.push_back(prod); + finalMessageHashes.push_back(kv.first); + + for (auto &p : dedupMap) { + delete[] p.first; + } + } + + // Now we have all distinct messages, so we can verify + return sig.Verify(finalMessageHashes, finalPubKeys); +} + +Signature Signature::Aggregate( + std::vector const &sigs) { + std::vector > pubKeys; + std::vector > messageHashes; + + // Extracts the public keys and messages from the aggregation info + for (const Signature &sig : sigs) { + const AggregationInfo &info = *sig.GetAggregationInfo(); + if (info.Empty()) { + throw std::invalid_argument("Signature must include aggregation info."); + } + std::vector infoPubKeys = info.GetPubKeys(); + std::vector infoMessageHashes = info.GetMessageHashes(); + if (infoPubKeys.size() < 1 || infoMessageHashes.size() < 1) { + throw std::length_error("AggregationInfo must have items"); + } + pubKeys.push_back(infoPubKeys); + std::vector currMessageHashes; + for (const uint8_t* infoMessageHash : infoMessageHashes) { + uint8_t* messageHash = new uint8_t[BLS::MESSAGE_HASH_LEN]; + std::memcpy(messageHash, infoMessageHash, BLS::MESSAGE_HASH_LEN); + currMessageHashes.push_back(messageHash); + } + messageHashes.push_back(currMessageHashes); + } + + if (sigs.size() != pubKeys.size() + || pubKeys.size() != messageHashes.size()) { + throw std::length_error("Lengths of vectors must match."); + } + for (size_t i = 0; i < messageHashes.size(); i++) { + if (pubKeys[i].size() != messageHashes[i].size()) { + throw std::length_error("Lengths of vectors must match."); + } + } + Signature ret = AggregateSigsInternal(sigs, pubKeys, messageHashes); + for (std::vector group : messageHashes) { + for (const uint8_t* messageHash : group) { + delete[] messageHash; + } + } + return ret; +} + +Signature Signature::AggregateSigsSecure( + std::vector const &sigs, + std::vector const &pubKeys, + std::vector const &messageHashes) { + if (sigs.size() != pubKeys.size() || sigs.size() != messageHashes.size() + || sigs.size() < 1) { + throw std::invalid_argument("Must have atleast one signature, key, and message"); + } + + // Sort the public keys and signature by message + public key + std::vector serPubKeys(pubKeys.size()); + std::vector sortKeys(pubKeys.size()); + std::vector keysSorted(pubKeys.size()); + for (size_t i = 0; i < pubKeys.size(); i++) { + serPubKeys[i] = new uint8_t[PublicKey::PUBLIC_KEY_SIZE]; + pubKeys[i].Serialize(serPubKeys[i]); + + uint8_t *sortKey = new uint8_t[BLS::MESSAGE_HASH_LEN + PublicKey::PUBLIC_KEY_SIZE]; + memcpy(sortKey, messageHashes[i], BLS::MESSAGE_HASH_LEN); + memcpy(sortKey + BLS::MESSAGE_HASH_LEN, serPubKeys[i], PublicKey::PUBLIC_KEY_SIZE); + + sortKeys[i] = sortKey; + keysSorted[i] = i; + } + + std::sort(keysSorted.begin(), keysSorted.end(), [&sortKeys](size_t a, size_t b) { + return memcmp(sortKeys[a], sortKeys[b], BLS::MESSAGE_HASH_LEN + PublicKey::PUBLIC_KEY_SIZE) < 0; + }); + + bn_t* computedTs = new bn_t[keysSorted.size()]; + for (size_t i = 0; i < keysSorted.size(); i++) { + bn_new(computedTs[i]); + } + BLS::HashPubKeys(computedTs, keysSorted.size(), serPubKeys, keysSorted); + + // Raise all signatures to power of the corresponding t's and aggregate the results into aggSig + std::vector expSigs; + expSigs.reserve(keysSorted.size()); + for (size_t i = 0; i < keysSorted.size(); i++) { + auto& s = sigs[keysSorted[i]].sig; + expSigs.emplace_back(s.Exp(computedTs[i])); + } + InsecureSignature aggSig = InsecureSignature::Aggregate(expSigs); + + delete[] computedTs; + for (auto p : serPubKeys) { + delete[] p; + } + for (auto p : sortKeys) { + delete[] p; + } + + Signature ret = Signature::FromInsecureSig(aggSig); + BLS::CheckRelicErrors(); + return ret; +} + +Signature Signature::AggregateSigsInternal( + std::vector const &sigs, + std::vector > const &pubKeys, + std::vector > const &messageHashes) { + if (sigs.size() != pubKeys.size() + || pubKeys.size() != messageHashes.size()) { + throw std::length_error("Lengths of std::vectors must match."); + } + for (size_t i = 0; i < messageHashes.size(); i++) { + if (pubKeys[i].size() != messageHashes[i].size()) { + throw std::length_error("Lengths of std::vectors must match."); + } + } + + // Find colliding vectors, save colliding messages + std::set messagesSet; + std::set collidingMessagesSet; + for (auto &msgVector : messageHashes) { + std::set messagesSetLocal; + for (auto &msg : msgVector) { + auto lookupEntry = messagesSet.find(msg); + auto lookupEntryLocal = messagesSetLocal.find(msg); + if (lookupEntryLocal == messagesSetLocal.end() && + lookupEntry != messagesSet.end()) { + collidingMessagesSet.insert(msg); + } + messagesSet.insert(msg); + messagesSetLocal.insert(msg); + } + } + if (collidingMessagesSet.empty()) { + // There are no colliding messages between the groups, so we + // will just aggregate them all simply. Note that we assume + // that every group is a valid aggregate signature. If an invalid + // or insecure signature is given, and invalid signature will + // be created. We don't verify for performance reasons. + Signature ret = AggregateSigsSimple(sigs); + std::vector infos; + for (const Signature &sig : sigs) { + infos.push_back(*sig.GetAggregationInfo()); + } + ret.SetAggregationInfo(AggregationInfo::MergeInfos(infos)); + return ret; + } + + // There are groups that share messages, therefore we need + // to use a secure form of aggregation. First we find which + // groups collide, and securely aggregate these. Then, we + // use simple aggregation at the end. + std::vector collidingSigs; + std::vector nonCollidingSigs; + std::vector > collidingMessageHashes; + std::vector > collidingPks; + + for (size_t i = 0; i < sigs.size(); i++) { + bool groupCollides = false; + for (const uint8_t* msg : messageHashes[i]) { + auto lookupEntry = collidingMessagesSet.find(msg); + if (lookupEntry != collidingMessagesSet.end()) { + groupCollides = true; + collidingSigs.push_back(sigs[i]); + collidingMessageHashes.push_back(messageHashes[i]); + collidingPks.push_back(pubKeys[i]); + break; + } + } + if (!groupCollides) { + nonCollidingSigs.push_back(sigs[i]); + } + } + + // Sort signatures by aggInfo + std::vector sigsSorted(collidingSigs.size()); + for (size_t i = 0; i < sigsSorted.size(); i++) { + sigsSorted[i] = i; + } + std::sort(sigsSorted.begin(), sigsSorted.end(), [&collidingSigs](size_t a, size_t b) { + return *collidingSigs[a].GetAggregationInfo() < *collidingSigs[b].GetAggregationInfo(); + }); + + std::vector serPubKeys; + std::vector sortKeys; + std::vector sortKeysSorted; + size_t sortKeysCount = 0; + for (size_t i = 0; i < collidingPks.size(); i++) { + sortKeysCount += collidingPks[i].size(); + } + sortKeys.reserve(sortKeysCount); + sortKeysSorted.reserve(sortKeysCount); + for (size_t i = 0; i < collidingPks.size(); i++) { + for (size_t j = 0; j < collidingPks[i].size(); j++) { + uint8_t *serPk = new uint8_t[PublicKey::PUBLIC_KEY_SIZE]; + uint8_t *sortKey = new uint8_t[BLS::MESSAGE_HASH_LEN + PublicKey::PUBLIC_KEY_SIZE]; + collidingPks[i][j].Serialize(serPk); + std::memcpy(sortKey, collidingMessageHashes[i][j], BLS::MESSAGE_HASH_LEN); + std::memcpy(sortKey + BLS::MESSAGE_HASH_LEN, serPk, PublicKey::PUBLIC_KEY_SIZE); + serPubKeys.emplace_back(serPk); + sortKeysSorted.emplace_back(sortKeys.size()); + sortKeys.emplace_back(sortKey); + } + } + // Sort everything according to message || pubkey + std::sort(sortKeysSorted.begin(), sortKeysSorted.end(), [&sortKeys](size_t a, size_t b) { + return memcmp(sortKeys[a], sortKeys[b], BLS::MESSAGE_HASH_LEN + PublicKey::PUBLIC_KEY_SIZE) < 0; + }); + + std::vector pubKeysSorted; + for (size_t i = 0; i < sortKeysSorted.size(); i++) { + const uint8_t *sortKey = sortKeys[sortKeysSorted[i]]; + pubKeysSorted.push_back(PublicKey::FromBytes(sortKey + + BLS::MESSAGE_HASH_LEN)); + } + bn_t* computedTs = new bn_t[sigsSorted.size()]; + for (size_t i = 0; i < sigsSorted.size(); i++) { + bn_new(computedTs[i]); + } + BLS::HashPubKeys(computedTs, sigsSorted.size(), serPubKeys, sortKeysSorted); + + // Raise all signatures to power of the corresponding t's and aggregate the results into aggSig + // Also accumulates aggregation info for each signature + std::vector infos; + std::vector expSigs; + infos.reserve(sigsSorted.size()); + expSigs.reserve(sigsSorted.size()); + for (size_t i = 0; i < sigsSorted.size(); i++) { + auto& s = collidingSigs[sigsSorted[i]]; + expSigs.emplace_back(s.sig.Exp(computedTs[i])); + infos.emplace_back(*s.GetAggregationInfo()); + } + + // Also collect all non-colliding signatures for aggregation + // These don't need exponentiation + for (const Signature &nonColliding : nonCollidingSigs) { + expSigs.emplace_back(nonColliding.sig); + infos.emplace_back(*nonColliding.GetAggregationInfo()); + } + + InsecureSignature aggSig = InsecureSignature::Aggregate(expSigs); + Signature ret = Signature::FromInsecureSig(aggSig); + + // Merge the aggregation infos, which will be combined in an + // identical way as above. + ret.SetAggregationInfo(AggregationInfo::MergeInfos(infos)); + + delete[] computedTs; + + for (auto p : serPubKeys) { + delete[] p; + } + for (auto p : sortKeys) { + delete[] p; + } + + return ret; +} + +Signature Signature::AggregateSigsSimple(std::vector const &sigs) { + if (sigs.size() < 1) { + throw std::length_error("Must have atleast one signatures and key"); + } + if (sigs.size() == 1) { + return sigs[0]; + } + + // Multiplies the signatures together (relic uses additive group operation) + std::vector sigs2; + sigs2.reserve(sigs.size()); + for (const Signature &sig : sigs) { + sigs2.emplace_back(sig.sig); + } + InsecureSignature aggSig = InsecureSignature::Aggregate(sigs2); + Signature ret = Signature::FromInsecureSig(aggSig); + BLS::CheckRelicErrors(); + return ret; +} + +Signature Signature::DivideBy(std::vector const &divisorSigs) const { + bn_t ord; + g2_get_ord(ord); + + std::vector messageHashesToRemove; + std::vector pubKeysToRemove; + + std::vector expSigs; + expSigs.reserve(divisorSigs.size()); + for (const Signature &divisorSig : divisorSigs) { + std::vector pks = divisorSig.GetAggregationInfo() + ->GetPubKeys(); + std::vector messageHashes = divisorSig.GetAggregationInfo() + ->GetMessageHashes(); + if (pks.size() != messageHashes.size()) { + throw std::length_error("Invalid aggregation info."); + } + bn_t quotient; + for (size_t i = 0; i < pks.size(); i++) { + bn_t divisor; + bn_new(divisor); + divisorSig.GetAggregationInfo()->GetExponent(&divisor, + messageHashes[i], + pks[i]); + bn_t dividend; + bn_new(dividend); + try { + aggregationInfo.GetExponent(÷nd, messageHashes[i], + pks[i]); + } catch (std::out_of_range e) { + throw std::logic_error("Signature is not a subset."); + } + + if (i == 0) { + bn_t inverted; + fp_inv_exgcd_bn(inverted, divisor, ord); + bn_mul(quotient, dividend, inverted); + bn_mod(quotient, quotient, ord); + } else { + bn_t leftHandSide; + bn_mul(leftHandSide, quotient, divisor); + bn_mod(leftHandSide, leftHandSide, ord); + + if (bn_cmp(leftHandSide, dividend) != RLC_EQ) { + throw std::logic_error("Cannot divide by aggregate signature," + "msg/pk pairs are not unique"); + } + } + messageHashesToRemove.push_back(messageHashes[i]); + pubKeysToRemove.push_back(pks[i]); + } + expSigs.emplace_back(divisorSig.sig.Exp(quotient)); + } + + InsecureSignature prod = sig.DivideBy(expSigs); + Signature result = Signature::FromInsecureSig(prod, aggregationInfo); + result.aggregationInfo.RemoveEntries(messageHashesToRemove, pubKeysToRemove); + + return result; +} + +// Prepend Signature + +PrependSignature PrependSignature::FromBytes(const uint8_t *data) { + PrependSignature result; + if ((data[0] & 0x40) == 0) { + throw std::invalid_argument("Invalid prepend signature. Second bit must be set to two"); + } + uint8_t new_data[PrependSignature::SIGNATURE_SIZE]; + memcpy(new_data, data, SIGNATURE_SIZE); + new_data[0] ^= 0x40; + result.sig = InsecureSignature::FromBytes(new_data); + return result; +} + +PrependSignature PrependSignature::FromG2(const g2_t* element) { + PrependSignature ret; + ret.sig = InsecureSignature::FromG2(element); + return ret; +} + +PrependSignature PrependSignature::FromInsecureSig(const InsecureSignature& sig) { + return FromG2(&sig.sig); +} + +PrependSignature::PrependSignature(const PrependSignature &_signature) + : sig(_signature.sig) {} + + +bool PrependSignature::Verify(const std::vector& hashes, + const std::vector& pubKeys) const { + if (pubKeys.size() != hashes.size()) { + return false; + } + + std::vector newHashes; + for (uint32_t i = 0; i < hashes.size(); i++) { + uint8_t newMessage[PublicKey::PUBLIC_KEY_SIZE + BLS::MESSAGE_HASH_LEN]; + pubKeys[i].Serialize(newMessage); + memcpy(newMessage + PublicKey::PUBLIC_KEY_SIZE, hashes[i], BLS::MESSAGE_HASH_LEN); + uint8_t* newHash = new uint8_t[BLS::MESSAGE_HASH_LEN]; + Util::Hash256(newHash, newMessage, PublicKey::PUBLIC_KEY_SIZE + BLS::MESSAGE_HASH_LEN); + newHashes.push_back(newHash); + } + + bool res = sig.Verify(newHashes, pubKeys); + for (uint32_t i = 0; i < newHashes.size(); i++) { + delete[] newHashes[i]; + } + return res; +} + +PrependSignature PrependSignature::Aggregate(std::vector const &sigs) { + std::vector insecureSignatures; + for (PrependSignature sig : sigs) { + insecureSignatures.push_back(sig.GetInsecureSig()); + } + return PrependSignature::FromInsecureSig(InsecureSignature::Aggregate(insecureSignatures)); +} + +PrependSignature PrependSignature::DivideBy(std::vector const &divisorSigs) const { + std::vector insecureSignatures; + for (PrependSignature sig : divisorSigs) { + insecureSignatures.push_back(sig.GetInsecureSig()); + } + return PrependSignature::FromInsecureSig(sig.DivideBy(insecureSignatures)); +} + +void PrependSignature::Serialize(uint8_t* buffer) const { + sig.Serialize(buffer); + buffer[0] |= 0x40; +} + +std::vector PrependSignature::Serialize() const { + std::vector ret = sig.Serialize(); + ret[0] |= 0x40; + return ret; +} + +InsecureSignature PrependSignature::GetInsecureSig() const { + return sig; +} + +bool operator==(PrependSignature const &a, PrependSignature const &b) { + return a.sig == b.sig; +} + +bool operator!=(PrependSignature const &a, PrependSignature const &b) { + return !(a == b); +} + +std::ostream &operator<<(std::ostream &os, PrependSignature const &s) { + uint8_t data[InsecureSignature::SIGNATURE_SIZE]; + s.Serialize(data); + return os << Util::HexStr(data, InsecureSignature::SIGNATURE_SIZE); +} + +} // end namespace bls diff --git a/bls/src/signature.hpp b/bls/src/signature.hpp new file mode 100644 index 00000000..79cb698f --- /dev/null +++ b/bls/src/signature.hpp @@ -0,0 +1,242 @@ +// Copyright 2018 Chia Network Inc + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_BLSSIGNATURE_HPP_ +#define SRC_BLSSIGNATURE_HPP_ + +#include +#include + +#include "relic_conf.h" + +#if defined GMP && ARITH == GMP +#include +#endif + +#include "util.hpp" +#include "aggregationinfo.hpp" +namespace bls { +/** + * An insecure BLS signature. + * A Signature is a group element of g2 + * Aggregation of these signatures is not secure on it's own, use Signature or PrependSignature instead. + * For more documentation of the rogue public key attack, and the insecurity of this class, + * see https://crypto.stanford.edu/~dabo/pubs/papers/BLSmultisig.html. + */ +class InsecureSignature { + friend class Signature; + friend class PrependSignature; + friend class Threshold; + public: + static const size_t SIGNATURE_SIZE = 96; + + // Initializes from serialized byte array. + static InsecureSignature FromBytes(const uint8_t *data); + + // Initializes from native relic g2 element. + static InsecureSignature FromG2(const g2_t* element); + + // Copy constructor. Deep copies contents. + InsecureSignature(const InsecureSignature &signature); + + // This verification method is insecure in regard to the rogue public key attack + bool Verify(const std::vector& hashes, const std::vector& pubKeys) const; + + // Insecurely aggregates signatures + static InsecureSignature Aggregate(const std::vector& sigs); + + // Insecurely divides signatures + InsecureSignature DivideBy(const std::vector& sigs) const; + + // Serializes ONLY the 96 byte public key. It does not serialize + // the aggregation info. + void Serialize(uint8_t* buffer) const; + std::vector Serialize() const; + + friend bool operator==(InsecureSignature const &a, InsecureSignature const &b); + friend bool operator!=(InsecureSignature const &a, InsecureSignature const &b); + friend std::ostream &operator<<(std::ostream &os, InsecureSignature const &s); + InsecureSignature& operator=(const InsecureSignature& rhs); + + private: + // Prevent public construction, force static method + InsecureSignature(); + + // Exponentiate signature with n + InsecureSignature Exp(const bn_t n) const; + + static void CompressPoint(uint8_t* result, const g2_t* point); + + // Performs multipairing and checks that everything matches. This is an + // internal method, only called from Verify. It should not be used + // anywhere else. + static bool VerifyNative( + g1_t* pubKeys, + g2_t* mappedHashes, + size_t len); + + private: + // Signature group element + g2_t sig; +}; + +/** + * An encapsulated signature. + * A Signature is composed of two things: + * 1. 96 byte group element of g2 + * 2. AggregationInfo object, which describes how the signature was + * generated, and how it should be verified. + */ +class Signature { + public: + static const size_t SIGNATURE_SIZE = InsecureSignature::SIGNATURE_SIZE; + + // Initializes from serialized byte array. + static Signature FromBytes(const uint8_t *data); + + // Initializes from bytes with AggregationInfo. + static Signature FromBytes(const uint8_t *data, const AggregationInfo &info); + + // Initializes from native relic g2 element. + static Signature FromG2(const g2_t* element); + + // Initializes from native relic g2 element with AggregationInfo. + static Signature FromG2(const g2_t* element, const AggregationInfo &info); + + // Initializes from insecure signature/ + static Signature FromInsecureSig(const InsecureSignature& sig); + + // Initializes from insecure signature with AggregationInfo/ + static Signature FromInsecureSig(const InsecureSignature& sig, const AggregationInfo &info); + + // Copy constructor. Deep copies contents. + Signature(const Signature &signature); + + // Verifies a single or aggregate signature. + // Performs two pairing operations, sig must contain information on + // how aggregation was performed (AggregationInfo). The Aggregation + // Info contains all the public keys and messages required. + bool Verify() const; + + // Securely aggregates many signatures on messages, some of + // which may be identical. The returned signature contains + // information on how the aggregation was done (AggragationInfo). + static Signature Aggregate(std::vector const &sigs); + + // Divides the aggregate signature (this) by a list of signatures. + // These divisors can be single or aggregate signatures, but all + // msg/pk pairs in these signatures must be distinct and unique. + Signature DivideBy(std::vector const &divisorSigs) const; + + // Gets the aggregation info on this signature. + const AggregationInfo* GetAggregationInfo() const; + + // Sets the aggregation information on this signature, which + // describes how this signature was generated, and how it should + // be verified. + void SetAggregationInfo(const AggregationInfo &newAggregationInfo); + + // Serializes ONLY the 96 byte public key. It does not serialize + // the aggregation info. + void Serialize(uint8_t* buffer) const; + std::vector Serialize() const; + + InsecureSignature GetInsecureSig() const; + + friend bool operator==(Signature const &a, Signature const &b); + friend bool operator!=(Signature const &a, Signature const &b); + friend std::ostream &operator<<(std::ostream &os, Signature const &s); + + private: + // Prevent public construction, force static method + Signature() {} + + // Aggregates many signatures using the secure aggregation method. + // Performs ~ n * 256 g2 operations. + static Signature AggregateSigsSecure( + std::vector const &sigs, + std::vector const &pubKeys, + std::vector const &messageHashes); + + // Internal methods + static Signature AggregateSigsInternal( + std::vector const &sigs, + std::vector > const &pubKeys, + std::vector > const &messageHashes); + + // Efficiently aggregates many signatures using the simple aggregation + // method. Performs only n g2 operations. + static Signature AggregateSigsSimple( + std::vector const &sigs); + + private: + // internal signature + InsecureSignature sig; + + // Optional info about how this was aggregated + AggregationInfo aggregationInfo; +}; + +/** + * An encapsulated signature. + * A Prepend Signature is generated using PrivateKey::SignPrepend. It a secure against rogue + * public key attacks, since it signs the signer's public key. + */ +class PrependSignature { + public: + static const size_t SIGNATURE_SIZE = InsecureSignature::SIGNATURE_SIZE; + + // Initializes from serialized byte array. + static PrependSignature FromBytes(const uint8_t *data); + + // Initializes from native relic g2 element. + static PrependSignature FromG2(const g2_t* element); + + // Initializes from insecure signature. + static PrependSignature FromInsecureSig(const InsecureSignature& sig); + + // Copy constructor. Deep copies contents. + PrependSignature(const PrependSignature &signature); + + // Verifies a single or aggregate signature. + bool Verify(const std::vector& hashes, const std::vector& pubKeys) const; + + static PrependSignature Aggregate(std::vector const &sigs); + + // Divides the aggregate signature (this) by a list of signatures. + // These divisors can be single or aggregate signatures, but all + // msg/pk pairs in these signatures must be distinct and unique. + PrependSignature DivideBy(std::vector const &divisorSigs) const; + + void Serialize(uint8_t* buffer) const; + std::vector Serialize() const; + + InsecureSignature GetInsecureSig() const; + + friend bool operator==(PrependSignature const &a, PrependSignature const &b); + friend bool operator!=(PrependSignature const &a, PrependSignature const &b); + friend std::ostream &operator<<(std::ostream &os, PrependSignature const &s); + + private: + // Prevent public construction, force static method + PrependSignature() {} + + private: + // internal signature + InsecureSignature sig; +}; + +} // end namespace bls + +#endif // SRC_BLSSIGNATURE_HPP_ diff --git a/bls/src/test-bench.cpp b/bls/src/test-bench.cpp new file mode 100644 index 00000000..10d2bb17 --- /dev/null +++ b/bls/src/test-bench.cpp @@ -0,0 +1,199 @@ +// Copyright 2018 Chia Network Inc + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include "bls.hpp" +#include "test-utils.hpp" +#include "relic.h" + +using std::string; +using std::vector; +using std::cout; +using std::endl; + +using namespace bls; + +void benchSigs() { + string testName = "Sigining"; + double numIters = 1000; + uint8_t seed[32]; + getRandomSeed(seed); + PrivateKey sk = PrivateKey::FromSeed(seed, 32); + PublicKey pk = sk.GetPublicKey(); + uint8_t message1[48]; + pk.Serialize(message1); + + auto start = startStopwatch(); + + for (size_t i = 0; i < numIters; i++) { + sk.Sign(message1, sizeof(message1)); + } + endStopwatch(testName, start, numIters); +} + +void benchVerification() { + string testName = "Verification"; + double numIters = 1000; + uint8_t seed[32]; + getRandomSeed(seed); + PrivateKey sk = PrivateKey::FromSeed(seed, 32); + + std::vector sigs; + + for (size_t i = 0; i < numIters; i++) { + uint8_t message[4]; + Util::IntToFourBytes(message, i); + sigs.push_back(sk.Sign(message, 4)); + } + + auto start = startStopwatch(); + for (size_t i = 0; i < numIters; i++) { + uint8_t message[4]; + Util::IntToFourBytes(message, i); + bool ok = sigs[i].Verify(); + ASSERT(ok); + } + endStopwatch(testName, start, numIters); +} + +void benchAggregateSigsSecure() { + uint8_t message1[7] = {100, 2, 254, 88, 90, 45, 23}; + double numIters = 1000; + + std::vector sks; + std::vector pks; + std::vector sigs; + + for (int i = 0; i < numIters; i++) { + uint8_t seed[32]; + getRandomSeed(seed); + + PrivateKey sk = PrivateKey::FromSeed(seed, 32); + const PublicKey pk = sk.GetPublicKey(); + sks.push_back(sk); + pks.push_back(pk); + sigs.push_back(sk.Sign(message1, sizeof(message1))); + } + + auto start = startStopwatch(); + Signature aggSig = Signature::Aggregate(sigs); + endStopwatch("Generate aggregate signature, same message", + start, numIters); + + auto start2 = startStopwatch(); + const PublicKey aggPubKey = PublicKey::Aggregate(pks); + endStopwatch("Generate aggregate pk, same message", start2, numIters); + + auto start3 = startStopwatch(); + aggSig.SetAggregationInfo(AggregationInfo::FromMsg( + aggPubKey, message1, sizeof(message1))); + ASSERT(aggSig.Verify()); + endStopwatch("Verify agg signature, same message", start3, numIters); +} + +void benchBatchVerification() { + string testName = "Batch verification"; + double numIters = 1000; + + std::vector sigs; + std::vector cache; + for (size_t i = 0; i < numIters; i++) { + uint8_t seed[32]; + getRandomSeed(seed); + + PrivateKey sk = PrivateKey::FromSeed(seed, 32); + uint8_t *message = new uint8_t[32]; + getRandomSeed(message); + sigs.push_back(sk.Sign(message, 1 + (i % 5))); + // Small message, so some messages are the same + if (message[0] < 225) { // Simulate having ~90% cached transactions + sigs.back().Verify(); + cache.push_back(sigs.back()); + } + } + + Signature aggregate = Signature::Aggregate(sigs); + + auto start = startStopwatch(); + ASSERT(aggregate.Verify()); + endStopwatch(testName, start, numIters); + + + start = startStopwatch(); + const Signature aggSmall = aggregate.DivideBy(cache); + ASSERT(aggSmall.Verify()); + endStopwatch(testName + " with cached verifications", start, numIters); +} + +void benchAggregateSigsSimple() { + double numIters = 1000; + std::vector sks; + std::vector sigs; + + for (int i = 0; i < numIters; i++) { + uint8_t* message = new uint8_t[48]; + uint8_t seed[32]; + getRandomSeed(seed); + + PrivateKey sk = PrivateKey::FromSeed(seed, 32); + const PublicKey pk = sk.GetPublicKey(); + pk.Serialize(message); + sks.push_back(sk); + sigs.push_back(sk.Sign(message, sizeof(message))); + } + + auto start = startStopwatch(); + Signature aggSig = Signature::Aggregate(sigs); + endStopwatch("Generate aggregate signature, distinct messages", + start, numIters); + + auto start2 = startStopwatch(); + ASSERT(aggSig.Verify()); + endStopwatch("Verify aggregate signature, distinct messages", + start2, numIters); +} + +void benchDegenerateTree() { + double numIters = 30; + uint8_t message1[7] = {100, 2, 254, 88, 90, 45, 23}; + uint8_t seed[32]; + getRandomSeed(seed); + PrivateKey sk1 = PrivateKey::FromSeed(seed, 32); + Signature aggSig = sk1.Sign(message1, sizeof(message1)); + + auto start = startStopwatch(); + for (size_t i = 0; i < numIters; i++) { + getRandomSeed(seed); + PrivateKey sk = PrivateKey::FromSeed(seed, 32); + Signature sig = sk.Sign(message1, sizeof(message1)); + std::vector sigs = {aggSig, sig}; + aggSig = Signature::Aggregate(sigs); + } + endStopwatch("Generate degenerate aggSig tree", + start, numIters); + + start = startStopwatch(); + ASSERT(aggSig.Verify()); + endStopwatch("Verify degenerate aggSig tree", + start, numIters); +} + +int main(int argc, char* argv[]) { + benchSigs(); + benchVerification(); + benchBatchVerification(); + benchAggregateSigsSecure(); + benchAggregateSigsSimple(); + benchDegenerateTree(); +} diff --git a/bls/src/test-utils.hpp b/bls/src/test-utils.hpp new file mode 100644 index 00000000..1fa7bee3 --- /dev/null +++ b/bls/src/test-utils.hpp @@ -0,0 +1,50 @@ +// Copyright 2018 Chia Network Inc + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include "bls.hpp" + +using std::string; +using std::vector; +using std::cout; +using std::endl; + +#define STR(x) #x +#define ASSERT(x) if (!(x)) { printf("BLS assertion failed: (%s), function %s, file %s, line %d.\n", STR(x), __PRETTY_FUNCTION__, __FILE__, __LINE__); abort(); } + +std::chrono::time_point startStopwatch() { + return std::chrono::steady_clock::now(); +} + +void endStopwatch(string testName, + std::chrono::time_point start, + double numIters) { + auto end = std::chrono::steady_clock::now(); + auto now_ms = std::chrono::duration_cast( + end - start); + + cout << endl << testName << endl; + cout << "Total: " << numIters << " runs in " << now_ms.count() + << " ms" << endl; + cout << "Avg: " << now_ms.count() / numIters + << " ms" << endl; +} + +void getRandomSeed(uint8_t* seed) { + bn_t r; + bn_new(r); + bn_rand(r, RLC_POS, 256); + bn_write_bin(seed, 32, r); +} diff --git a/bls/src/test.cpp b/bls/src/test.cpp new file mode 100644 index 00000000..20a8fdba --- /dev/null +++ b/bls/src/test.cpp @@ -0,0 +1,1659 @@ + +// Copyright 2018 Chia Network Inc + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#define CATCH_CONFIG_RUNNER +#include "catch.hpp" +#include "bls.hpp" +#include "test-utils.hpp" +#include "relic.h" +#include "relic_test.h" + +#include +using std::string; +using std::vector; +using std::cout; +using std::endl; + +using namespace bls; + +TEST_CASE("Test vectors") { + SECTION("Test vectors 1") { + uint8_t seed1[5] = {1, 2, 3, 4, 5}; + uint8_t seed2[6] = {1, 2, 3, 4, 5, 6}; + uint8_t message1[3] = {7, 8, 9}; + + PrivateKey sk1 = PrivateKey::FromSeed(seed1, sizeof(seed1)); + PublicKey pk1 = sk1.GetPublicKey(); + Signature sig1 = sk1.Sign(message1, sizeof(message1)); + + PrivateKey sk2 = PrivateKey::FromSeed(seed2, sizeof(seed2)); + PublicKey pk2 = sk2.GetPublicKey(); + Signature sig2 = sk2.Sign(message1, sizeof(message1)); + + uint8_t buf[Signature::SIGNATURE_SIZE]; + uint8_t buf2[PrivateKey::PRIVATE_KEY_SIZE]; + + REQUIRE(pk1.GetFingerprint() == 0x26d53247); + REQUIRE(pk2.GetFingerprint() == 0x289bb56e); + + + sig1.Serialize(buf); + sk1.Serialize(buf2); + + REQUIRE(Util::HexStr(buf, Signature::SIGNATURE_SIZE) + == "93eb2e1cb5efcfb31f2c08b235e8203a67265bc6a13d9f0ab77727293b74a357ff0459ac210dc851fcb8a60cb7d393a419915cfcf83908ddbeac32039aaa3e8fea82efcb3ba4f740f20c76df5e97109b57370ae32d9b70d256a98942e5806065"); + REQUIRE(Util::HexStr(buf2, PrivateKey::PRIVATE_KEY_SIZE) + == "022fb42c08c12de3a6af053880199806532e79515f94e83461612101f9412f9e"); + + sig2.Serialize(buf); + REQUIRE(Util::HexStr(buf, Signature::SIGNATURE_SIZE) + == "975b5daa64b915be19b5ac6d47bc1c2fc832d2fb8ca3e95c4805d8216f95cf2bdbb36cc23645f52040e381550727db420b523b57d494959e0e8c0c6060c46cf173872897f14d43b2ac2aec52fc7b46c02c5699ff7a10beba24d3ced4e89c821e"); + + vector sigs = {sig1, sig2}; + Signature aggSig1 = Signature::Aggregate(sigs); + + aggSig1.Serialize(buf); + REQUIRE(Util::HexStr(buf, Signature::SIGNATURE_SIZE) + == "0a638495c1403b25be391ed44c0ab013390026b5892c796a85ede46310ff7d0e0671f86ebe0e8f56bee80f28eb6d999c0a418c5fc52debac8fc338784cd32b76338d629dc2b4045a5833a357809795ef55ee3e9bee532edfc1d9c443bf5bc658"); + REQUIRE(aggSig1.Verify()); + + uint8_t message2[3] = {1, 2, 3}; + uint8_t message3[4] = {1, 2, 3, 4}; + uint8_t message4[2] = {1, 2}; + Signature sig3 = sk1.Sign(message2, sizeof(message2)); + Signature sig4 = sk1.Sign(message3, sizeof(message3)); + Signature sig5 = sk2.Sign(message4, sizeof(message4)); + vector sigs2 = {sig3, sig4, sig5}; + Signature aggSig2 = Signature::Aggregate(sigs2); + REQUIRE(aggSig2.Verify()); + aggSig2.Serialize(buf); + REQUIRE(Util::HexStr(buf, Signature::SIGNATURE_SIZE) + == "8b11daf73cd05f2fe27809b74a7b4c65b1bb79cc1066bdf839d96b97e073c1a635d2ec048e0801b4a208118fdbbb63a516bab8755cc8d850862eeaa099540cd83621ff9db97b4ada857ef54c50715486217bd2ecb4517e05ab49380c041e159b"); + } + + SECTION("Test vector 2") { + uint8_t message1[4] = {1, 2, 3, 40}; + uint8_t message2[4] = {5, 6, 70, 201}; + uint8_t message3[5] = {9, 10, 11, 12, 13}; + uint8_t message4[6] = {15, 63, 244, 92, 0, 1}; + + uint8_t seed1[5] = {1, 2, 3, 4, 5}; + uint8_t seed2[6] = {1, 2, 3, 4, 5, 6}; + + PrivateKey sk1 = PrivateKey::FromSeed(seed1, sizeof(seed1)); + PrivateKey sk2 = PrivateKey::FromSeed(seed2, sizeof(seed2)); + + PublicKey pk1 = sk1.GetPublicKey(); + PublicKey pk2 = sk2.GetPublicKey(); + + Signature sig1 = sk1.Sign(message1, sizeof(message1)); + Signature sig2 = sk2.Sign(message2, sizeof(message2)); + Signature sig3 = sk2.Sign(message1, sizeof(message1)); + Signature sig4 = sk1.Sign(message3, sizeof(message3)); + Signature sig5 = sk1.Sign(message1, sizeof(message1)); + Signature sig6 = sk1.Sign(message4, sizeof(message4)); + + std::vector const sigsL = {sig1, sig2}; + const Signature aggSigL = Signature::Aggregate(sigsL); + + std::vector const sigsR = {sig3, sig4, sig5}; + const Signature aggSigR = Signature::Aggregate(sigsR); + + std::vector sigs = {aggSigL, aggSigR, sig6}; + + Signature aggSig = Signature::Aggregate(sigs); + + REQUIRE(aggSig.Verify()); + + uint8_t buf[Signature::SIGNATURE_SIZE]; + aggSig.Serialize(buf); + REQUIRE(Util::HexStr(buf, Signature::SIGNATURE_SIZE) + == "07969958fbf82e65bd13ba0749990764cac81cf10d923af9fdd2723f1e3910c3fdb874a67f9d511bb7e4920f8c01232b12e2fb5e64a7c2d177a475dab5c3729ca1f580301ccdef809c57a8846890265d195b694fa414a2a3aa55c32837fddd80"); + vector signatures_to_divide = {sig2, sig5, sig6}; + Signature quotient = aggSig.DivideBy(signatures_to_divide); + aggSig.DivideBy(signatures_to_divide); + + quotient.Serialize(buf); + REQUIRE(Util::HexStr(buf, Signature::SIGNATURE_SIZE) + == "8ebc8a73a2291e689ce51769ff87e517be6089fd0627b2ce3cd2f0ee1ce134b39c4da40928954175014e9bbe623d845d0bdba8bfd2a85af9507ddf145579480132b676f027381314d983a63842fcc7bf5c8c088461e3ebb04dcf86b431d6238f"); + + REQUIRE(quotient.Verify()); + REQUIRE(quotient.DivideBy(vector()) == quotient); + signatures_to_divide = {sig6}; + REQUIRE_THROWS(quotient.DivideBy(signatures_to_divide)); + + // Should not throw + signatures_to_divide = {sig1}; + aggSig.DivideBy(signatures_to_divide); + + // Should throw due to not unique + signatures_to_divide = {aggSigL}; + REQUIRE_THROWS(aggSig.DivideBy(signatures_to_divide)); + + Signature sig7 = sk2.Sign(message3, sizeof(message3)); + Signature sig8 = sk2.Sign(message4, sizeof(message4)); + + // Divide by aggregate + std::vector sigsR2 = {sig7, sig8}; + Signature aggSigR2 = Signature::Aggregate(sigsR2); + std::vector sigsFinal2 = {aggSig, aggSigR2}; + Signature aggSig2 = Signature::Aggregate(sigsFinal2); + std::vector divisorFinal2 = {aggSigR2}; + Signature quotient2 = aggSig2.DivideBy(divisorFinal2); + + REQUIRE(quotient2.Verify()); + quotient2.Serialize(buf); + REQUIRE(Util::HexStr(buf, Signature::SIGNATURE_SIZE) + == "06af6930bd06838f2e4b00b62911fb290245cce503ccf5bfc2901459897731dd08fc4c56dbde75a11677ccfbfa61ab8b14735fddc66a02b7aeebb54ab9a41488f89f641d83d4515c4dd20dfcf28cbbccb1472c327f0780be3a90c005c58a47d3"); + } + + SECTION("Test vector 3") { + uint8_t seed[] = {1, 50, 6, 244, 24, 199, 1, 25}; + ExtendedPrivateKey esk = ExtendedPrivateKey::FromSeed( + seed, sizeof(seed)); + REQUIRE(esk.GetPublicKey().GetFingerprint() == 0xa4700b27); + uint8_t chainCode[32]; + esk.GetChainCode().Serialize(chainCode); + REQUIRE(Util::HexStr(chainCode, 32) == "d8b12555b4cc5578951e4a7c80031e22019cc0dce168b3ed88115311b8feb1e3"); + + ExtendedPrivateKey esk77 = esk.PrivateChild(77 + (1 << 31)); + esk77.GetChainCode().Serialize(chainCode); + REQUIRE(Util::HexStr(chainCode, 32) == "f2c8e4269bb3e54f8179a5c6976d92ca14c3260dd729981e9d15f53049fd698b"); + REQUIRE(esk77.GetPrivateKey().GetPublicKey().GetFingerprint() == 0xa8063dcf); + + REQUIRE(esk.PrivateChild(3) + .PrivateChild(17) + .GetPublicKey() + .GetFingerprint() == 0xff26a31f); + REQUIRE(esk.GetExtendedPublicKey() + .PublicChild(3) + .PublicChild(17) + .GetPublicKey() + .GetFingerprint() == 0xff26a31f); + } + + SECTION("Test vector 4") { + uint8_t seed1[5] = {1, 2, 3, 4, 5}; + uint8_t seed2[6] = {1, 2, 3, 4, 5, 6}; + uint8_t message1[3] = {7, 8, 9}; + uint8_t message2[3] = {10, 11, 12}; + + PrivateKey sk1 = PrivateKey::FromSeed(seed1, sizeof(seed1)); + PublicKey pk1 = sk1.GetPublicKey(); + + PrivateKey sk2 = PrivateKey::FromSeed(seed2, sizeof(seed2)); + PublicKey pk2 = sk2.GetPublicKey(); + + PrependSignature sig9 = sk1.SignPrepend(message1, sizeof(message1)); + PrependSignature sig10 = sk2.SignPrepend(message2, sizeof(message2)); + + uint8_t buf[Signature::SIGNATURE_SIZE]; + sig9.Serialize(buf); + REQUIRE(Util::HexStr(buf, Signature::SIGNATURE_SIZE) + == "d2135ad358405d9f2d4e68dc253d64b6049a821797817cffa5aa804086a8fb7b135175bb7183750e3aa19513db1552180f0b0ffd513c322f1c0c30a0a9c179f6e275e0109d4db7fa3e09694190947b17d890f3d58fe0b1866ec4d4f5a59b16ed"); + sig10.Serialize(buf); + REQUIRE(Util::HexStr(buf, Signature::SIGNATURE_SIZE) + == "cc58c982f9ee5817d4fbf22d529cfc6792b0fdcf2d2a8001686755868e10eb32b40e464e7fbfe30175a962f1972026f2087f0495ba6e293ac3cf271762cd6979b9413adc0ba7df153cf1f3faab6b893404c2e6d63351e48cd54e06e449965f08"); + + uint8_t messageHash1[BLS::MESSAGE_HASH_LEN]; + uint8_t messageHash2[BLS::MESSAGE_HASH_LEN]; + Util::Hash256(messageHash1, message1, sizeof(message1)); + Util::Hash256(messageHash2, message2, sizeof(message2)); + vector messageHashes1 = {messageHash1}; + vector messageHashes2 = {messageHash2}; + vector messageHashes = {messageHash1, messageHash1, messageHash2}; + vector pks = {pk1, pk1, pk2}; + + vector sigs = {sig9, sig9, sig10}; + PrependSignature agg = PrependSignature::Aggregate(sigs); + + agg.Serialize(buf); + REQUIRE(Util::HexStr(buf, Signature::SIGNATURE_SIZE) + == "c37077684e735e62e3f1fd17772a236b4115d4b581387733d3b97cab08b90918c7e91c23380c93e54be345544026f93505d41e6000392b82ab3c8af1b2e3954b0ef3f62c52fc89f99e646ff546881120396c449856428e672178e5e0e14ec894"); + + REQUIRE(agg.Verify(messageHashes, pks)); + } +} + +TEST_CASE("Key generation") { + SECTION("Should generate a keypair from a seed") { + uint8_t seed[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + + + PrivateKey sk = PrivateKey::FromSeed(seed, sizeof(seed)); + PublicKey pk = sk.GetPublicKey(); + REQUIRE(core_get()->code == RLC_OK); + REQUIRE(pk.GetFingerprint() == 0xddad59bb); + } +} + +TEST_CASE("Error handling") { + SECTION("Should throw on a bad private key") { + uint8_t seed[32]; + getRandomSeed(seed); + PrivateKey sk1 = PrivateKey::FromSeed(seed, 32); + uint8_t* skData = Util::SecAlloc( + Signature::SIGNATURE_SIZE); + sk1.Serialize(skData); + skData[0] = 255; + REQUIRE_THROWS(PrivateKey::FromBytes(skData)); + + Util::SecFree(skData); + } + + SECTION("Should throw on a bad public key") { + uint8_t buf[PublicKey::PUBLIC_KEY_SIZE] = {0}; + std::set invalid = {1, 2, 3, 4}; + + for (int i = 0; i < 10; i++) { + buf[0] = (uint8_t)i; + try { + PublicKey::FromBytes(buf); + REQUIRE(invalid.count(i) == 0); + } catch (std::invalid_argument& s) { + REQUIRE(invalid.count(i) != 0); + } + } + } + + SECTION("Should throw on a bad signature") { + uint8_t buf[Signature::SIGNATURE_SIZE] = {0}; + std::set invalid = {0, 1, 2, 3, 5, 6, 7, 8}; + + for (int i = 0; i < 10; i++) { + buf[0] = (uint8_t)i; + try { + Signature::FromBytes(buf); + REQUIRE(invalid.count(i) == 0); + } catch (std::invalid_argument& s) { + REQUIRE(invalid.count(i) != 0); + } + } + } + + SECTION("Error handling should be thread safe") { + core_get()->code = 10; + REQUIRE(core_get()->code == 10); + + ctx_t* ctx1 = core_get(); + bool ctxError = false; + + // spawn a thread and make sure it uses a different context + std::thread([&]() { + if (ctx1 == core_get()) { + ctxError = true; + } + if (core_get()->code != RLC_OK) { + ctxError = true; + } + // this should not modify the code of the main thread + core_get()->code = 1; + }).join(); + + REQUIRE(!ctxError); + + // other thread should not modify code + REQUIRE(core_get()->code == 10); + + // reset so that future test cases don't fail + core_get()->code = RLC_OK; + } +} + +TEST_CASE("Util tests") { + SECTION("Should convert an int to four bytes") { + uint32_t x = 1024; + uint8_t expected[4] = {0x00, 0x00, 0x04, 0x00}; + uint8_t result[4]; + Util::IntToFourBytes(result, x); + REQUIRE(result[0] == expected[0]); + REQUIRE(result[1] == expected[1]); + REQUIRE(result[2] == expected[2]); + REQUIRE(result[3] == expected[3]); + uint32_t again = Util::FourBytesToInt(result); + REQUIRE(again == x); + } + + SECTION("Should calculate public key fingerprints") { + uint8_t seed[] = {1, 50, 6, 244, 24, 199, 1, 25}; + ExtendedPrivateKey esk = ExtendedPrivateKey::FromSeed( + seed, sizeof(seed)); + uint32_t fingerprint = esk.GetPublicKey().GetFingerprint(); + REQUIRE(fingerprint == 0xa4700b27); + } +} + +TEST_CASE("Signatures") { + SECTION("Should sign and verify") { + uint8_t message1[7] = {1, 65, 254, 88, 90, 45, 22}; + + uint8_t seed[6] = {28, 20, 102, 229, 1, 157}; + PrivateKey sk1 = PrivateKey::FromSeed(seed, sizeof(seed)); + PublicKey pk1 = sk1.GetPublicKey(); + Signature sig1 = sk1.Sign(message1, sizeof(message1)); + + sig1.SetAggregationInfo( + AggregationInfo::FromMsg(pk1, message1, sizeof(message1))); + REQUIRE(sig1.Verify()); + + uint8_t hash[32]; + Util::Hash256(hash, message1, 7); + Signature sig2 = sk1.SignPrehashed(hash); + sig2.SetAggregationInfo( + AggregationInfo::FromMsg(pk1, message1, sizeof(message1))); + REQUIRE(sig1 == sig2); + REQUIRE(sig2.Verify()); + + // Hashing to g1 + uint8_t mapMsg[0] = {}; + g1_t result; + uint8_t buf[49]; + ep_map(result, mapMsg, 0); + g1_write_bin(buf, 49, result, 1); + REQUIRE(Util::HexStr(buf + 1, 48) == "12fc5ad5a2fbe9d4b6eb0bc16d530e5f263b6d59cbaf26c3f2831962924aa588ab84d46cc80d3a433ce064adb307f256"); + } + + SECTION("Should use copy constructor") { + uint8_t message1[7] = {1, 65, 254, 88, 90, 45, 22}; + + uint8_t seed[32]; + getRandomSeed(seed); + PrivateKey sk1 = PrivateKey::FromSeed(seed, 32); + PublicKey pk1 = sk1.GetPublicKey(); + PrivateKey sk2 = PrivateKey(sk1); + + uint8_t skBytes[PrivateKey::PRIVATE_KEY_SIZE]; + sk2.Serialize(skBytes); + PrivateKey sk4 = PrivateKey::FromBytes(skBytes); + + PublicKey pk2 = PublicKey(pk1); + Signature sig1 = sk4.Sign(message1, sizeof(message1)); + Signature sig2 = Signature(sig1); + + REQUIRE(sig2.Verify()); + } + + SECTION("Should use operators") { + uint8_t message1[7] = {1, 65, 254, 88, 90, 45, 22}; + uint8_t seed[32]; + getRandomSeed(seed); + uint8_t seed3[32]; + getRandomSeed(seed3); + + PrivateKey sk1 = PrivateKey::FromSeed(seed, 32); + PrivateKey sk2 = PrivateKey(sk1); + PrivateKey sk3 = PrivateKey::FromSeed(seed3, 32); + PublicKey pk1 = sk1.GetPublicKey(); + PublicKey pk2 = sk2.GetPublicKey(); + PublicKey pk3 = PublicKey(pk2); + PublicKey pk4 = sk3.GetPublicKey(); + Signature sig1 = sk1.Sign(message1, sizeof(message1)); + Signature sig2 = sk1.Sign(message1, sizeof(message1)); + Signature sig3 = sk2.Sign(message1, sizeof(message1)); + Signature sig4 = sk3.Sign(message1, sizeof(message1)); + + REQUIRE(sk1 == sk2); + REQUIRE(sk1 != sk3); + REQUIRE(pk1 == pk2); + REQUIRE(pk2 == pk3); + REQUIRE(pk1 != pk4); + REQUIRE(sig1 == sig2); + REQUIRE(sig2 == sig3); + REQUIRE(sig3 != sig4); + + REQUIRE(pk1.Serialize() == pk2.Serialize()); + REQUIRE(sig1.Serialize() == sig2.Serialize()); + } + + SECTION("Should serialize and deserialize") { + uint8_t message1[7] = {1, 65, 254, 88, 90, 45, 22}; + + uint8_t seed[32]; + getRandomSeed(seed); + PrivateKey sk1 = PrivateKey::FromSeed(seed, 32); + PublicKey pk1 = sk1.GetPublicKey(); + + uint8_t* skData = Util::SecAlloc( + Signature::SIGNATURE_SIZE); + sk1.Serialize(skData); + PrivateKey sk2 = PrivateKey::FromBytes(skData); + REQUIRE(sk1 == sk2); + + uint8_t pkData[PublicKey::PUBLIC_KEY_SIZE]; + pk1.Serialize(pkData); + + PublicKey pk2 = PublicKey::FromBytes(pkData); + REQUIRE(pk1 == pk2); + + Signature sig1 = sk1.Sign(message1, sizeof(message1)); + + uint8_t sigData[Signature::SIGNATURE_SIZE]; + sig1.Serialize(sigData); + + Signature sig2 = Signature::FromBytes(sigData); + REQUIRE(sig1 == sig2); + sig2.SetAggregationInfo(AggregationInfo::FromMsg( + pk2, message1, sizeof(message1))); + + REQUIRE(sig2.Verify()); + Util::SecFree(skData); + + InsecureSignature sig3 = InsecureSignature::FromBytes(sigData); + REQUIRE(Signature::FromInsecureSig(sig3) == sig2); + } + + SECTION("Should not validate a bad sig") { + uint8_t message1[7] = {100, 2, 254, 88, 90, 45, 22}; + uint8_t seed[32]; + getRandomSeed(seed); + uint8_t seed2[32]; + getRandomSeed(seed2); + PrivateKey sk1 = PrivateKey::FromSeed(seed, 32); + PrivateKey sk2 = PrivateKey::FromSeed(seed2, 32); + + PublicKey pk1 = sk1.GetPublicKey(); + PublicKey pk2 = sk2.GetPublicKey(); + + Signature sig2 = sk2.Sign(message1, sizeof(message1)); + sig2.SetAggregationInfo(AggregationInfo::FromMsg( + pk1, message1, sizeof(message1))); + + REQUIRE(sig2.Verify() == false); + } + + SECTION("Should insecurely aggregate and verify aggregate same message") { + uint8_t message[7] = {100, 2, 254, 88, 90, 45, 23}; + uint8_t hash[BLS::MESSAGE_HASH_LEN]; + + uint8_t seed[32]; + getRandomSeed(seed); + uint8_t seed2[32]; + getRandomSeed(seed2); + + Util::Hash256(hash, message, sizeof(message)); + + PrivateKey sk1 = PrivateKey::FromSeed(seed, 32); + PrivateKey sk2 = PrivateKey::FromSeed(seed2, 32); + + InsecureSignature sig1 = sk1.SignInsecure(message, sizeof(message)); + InsecureSignature sig2 = sk2.SignInsecure(message, sizeof(message)); + REQUIRE(sig1 != sig2); + REQUIRE(sig1.Verify({hash}, {sk1.GetPublicKey()})); + REQUIRE(sig2.Verify({hash}, {sk2.GetPublicKey()})); + + std::vector const sigs = {sig1, sig2}; + std::vector const pks = {sk1.GetPublicKey(), sk2.GetPublicKey()}; + InsecureSignature aggSig = InsecureSignature::Aggregate(sigs); + PublicKey aggPk = PublicKey::AggregateInsecure(pks); + REQUIRE(aggSig.Verify({hash}, {aggPk})); + } + + SECTION("Should insecurely aggregate and verify aggregate diff messages") { + uint8_t message1[7] = {100, 2, 254, 88, 90, 45, 23}; + uint8_t message2[8] = {100, 2, 254, 88, 90, 45, 24, 1}; + + uint8_t seed[32]; + getRandomSeed(seed); + uint8_t seed2[32]; + getRandomSeed(seed2); + + PrivateKey sk1 = PrivateKey::FromSeed(seed, 32); + PrivateKey sk2 = PrivateKey::FromSeed(seed2, 32); + + uint8_t hash1[BLS::MESSAGE_HASH_LEN]; + uint8_t hash2[BLS::MESSAGE_HASH_LEN]; + Util::Hash256(hash1, message1, sizeof(message1)); + Util::Hash256(hash2, message2, sizeof(message2)); + + InsecureSignature sig1 = sk1.SignInsecurePrehashed(hash1); + InsecureSignature sig2 = sk2.SignInsecurePrehashed(hash2); + REQUIRE(sig1 != sig2); + REQUIRE(sig1.Verify({hash1}, {sk1.GetPublicKey()})); + REQUIRE(sig2.Verify({hash2}, {sk2.GetPublicKey()})); + + std::vector const sigs = {sig1, sig2}; + std::vector const pks = {sk1.GetPublicKey(), sk2.GetPublicKey()}; + InsecureSignature aggSig = InsecureSignature::Aggregate(sigs); + + // same message verification should fail + PublicKey aggPk = PublicKey::AggregateInsecure(pks); + REQUIRE(!aggSig.Verify({hash1}, {aggPk})); + REQUIRE(!aggSig.Verify({hash2}, {aggPk})); + + // diff message verification should succeed + std::vector hashes = {hash1, hash2}; + REQUIRE(aggSig.Verify(hashes, pks)); + } + + SECTION("Should securely aggregate and verify aggregate") { + uint8_t message1[7] = {100, 2, 254, 88, 90, 45, 23}; + uint8_t message2[7] = {192, 29, 2, 0, 0, 45, 23}; + + uint8_t seed[32]; + getRandomSeed(seed); + uint8_t seed2[32]; + getRandomSeed(seed2); + + PrivateKey sk1 = PrivateKey::FromSeed(seed, 32); + PrivateKey sk2 = PrivateKey::FromSeed(seed2, 32); + + PublicKey pk1 = sk1.GetPublicKey(); + PublicKey pk2 = sk2.GetPublicKey(); + + Signature sig1 = sk1.Sign(message1, sizeof(message1)); + Signature sig2 = sk2.Sign(message2, sizeof(message2)); + + std::vector const sigs = {sig1, sig2}; + Signature aggSig = Signature::Aggregate(sigs); + + Signature sig3 = sk1.Sign(message1, sizeof(message1)); + Signature sig4 = sk2.Sign(message2, sizeof(message2)); + + std::vector const sigs2 = {sig3, sig4}; + Signature aggSig2 = Signature::Aggregate(sigs2); + REQUIRE(sig1 == sig3); + REQUIRE(sig2 == sig4); + REQUIRE(aggSig == aggSig2); + REQUIRE(sig1 != sig2); + + REQUIRE(aggSig.Verify()); + } + + SECTION("Should securely aggregate many signatures, diff message") { + std::vector sks; + std::vector sigs; + + for (int i = 0; i < 80; i++) { + uint8_t* message = new uint8_t[8]; + message[0] = 0; + message[1] = 100; + message[2] = 2; + message[3] = 59; + message[4] = 255; + message[5] = 92; + message[6] = 5; + message[7] = i; + uint8_t seed[32]; + getRandomSeed(seed); + const PrivateKey sk = PrivateKey::FromSeed(seed, 32); + const PublicKey pk = sk.GetPublicKey(); + sks.push_back(sk); + sigs.push_back(sk.Sign(message, sizeof(message))); + delete[] message; + } + + Signature aggSig = Signature::Aggregate(sigs); + + REQUIRE(aggSig.Verify()); + } + + SECTION("Should insecurely aggregate many signatures, diff message") { + std::vector sks; + std::vector pks; + std::vector sigs; + std::vector hashes; + + for (int i = 0; i < 80; i++) { + uint8_t* message = new uint8_t[8]; + uint8_t* hash = new uint8_t[BLS::MESSAGE_HASH_LEN]; + message[0] = 0; + message[1] = 100; + message[2] = 2; + message[3] = 59; + message[4] = 255; + message[5] = 92; + message[6] = 5; + message[7] = i; + Util::Hash256(hash, message, 8); + hashes.push_back(hash); + uint8_t seed[32]; + getRandomSeed(seed); + const PrivateKey sk = PrivateKey::FromSeed(seed, 32); + const PublicKey pk = sk.GetPublicKey(); + sks.push_back(sk); + pks.push_back(pk); + sigs.push_back(sk.SignInsecurePrehashed(hash)); + delete[] message; + } + + InsecureSignature aggSig = InsecureSignature::Aggregate(sigs); + + REQUIRE(aggSig.Verify(hashes, pks)); + std::swap(pks[0], pks[1]); + REQUIRE(!aggSig.Verify(hashes, pks)); + std::swap(hashes[0], hashes[1]); + REQUIRE(aggSig.Verify(hashes, pks)); + + for (auto& p : hashes) { + delete[] p; + } + } + + SECTION("Should securely aggregate same message") { + uint8_t message1[7] = {100, 2, 254, 88, 90, 45, 23}; + uint8_t seed[32]; + getRandomSeed(seed); + uint8_t seed2[32]; + getRandomSeed(seed2); + uint8_t seed3[32]; + getRandomSeed(seed3); + + PrivateKey sk1 = PrivateKey::FromSeed(seed, 32); + PublicKey pk1 = sk1.GetPublicKey(); + + PrivateKey sk2 = PrivateKey::FromSeed(seed2, 32); + PublicKey pk2 = sk2.GetPublicKey(); + + PrivateKey sk3 = PrivateKey::FromSeed(seed3, 32); + PublicKey pk3 = sk3.GetPublicKey(); + + Signature sig1 = sk1.Sign(message1, sizeof(message1)); + Signature sig2 = sk2.Sign(message1, sizeof(message1)); + Signature sig3 = sk3.Sign(message1, sizeof(message1)); + + std::vector const sigs = {sig1, sig2, sig3}; + std::vector const pubKeys = {pk1, pk2, pk3}; + Signature aggSig = Signature::Aggregate(sigs); + + const PublicKey aggPubKey = PublicKey::Aggregate(pubKeys); + aggSig.SetAggregationInfo(AggregationInfo::FromMsg( + aggPubKey, message1, sizeof(message1))); + REQUIRE(aggSig.Verify()); + } + + SECTION("Should securely divide signatures") { + uint8_t message1[7] = {100, 2, 254, 88, 90, 45, 23}; + uint8_t seed[32]; + getRandomSeed(seed); + uint8_t seed2[32]; + getRandomSeed(seed2); + uint8_t seed3[32]; + getRandomSeed(seed3); + + PrivateKey sk1 = PrivateKey::FromSeed(seed, 32); + PublicKey pk1 = sk1.GetPublicKey(); + + PrivateKey sk2 = PrivateKey::FromSeed(seed2, 32); + PublicKey pk2 = sk2.GetPublicKey(); + + PrivateKey sk3 = PrivateKey::FromSeed(seed3, 32); + PublicKey pk3 = sk3.GetPublicKey(); + + Signature sig1 = sk1.Sign(message1, sizeof(message1)); + Signature sig2 = sk2.Sign(message1, sizeof(message1)); + Signature sig3 = sk3.Sign(message1, sizeof(message1)); + + std::vector sigs = {sig1, sig2, sig3}; + Signature aggSig = Signature::Aggregate(sigs); + + REQUIRE(sig2.Verify()); + REQUIRE(sig3.Verify()); + std::vector divisorSigs = {sig2, sig3}; + + REQUIRE(aggSig.Verify()); + + REQUIRE(aggSig.GetAggregationInfo()->GetPubKeys().size() == 3); + const Signature aggSig2 = aggSig.DivideBy(divisorSigs); + REQUIRE(aggSig.GetAggregationInfo()->GetPubKeys().size() == 3); + REQUIRE(aggSig2.GetAggregationInfo()->GetPubKeys().size() == 1); + + REQUIRE(aggSig.Verify()); + REQUIRE(aggSig2.Verify()); + } + + SECTION("Should securely divide aggregate signatures") { + uint8_t message1[7] = {100, 2, 254, 88, 90, 45, 23}; + uint8_t message2[7] = {92, 20, 5, 89, 91, 15, 105}; + uint8_t message3[7] = {200, 10, 10, 159, 4, 15, 24}; + uint8_t seed[32]; + getRandomSeed(seed); + uint8_t seed2[32]; + getRandomSeed(seed2); + uint8_t seed3[32]; + getRandomSeed(seed3); + uint8_t seed4[32]; + getRandomSeed(seed4); + + PrivateKey sk1 = PrivateKey::FromSeed(seed, 32); + PublicKey pk1 = sk1.GetPublicKey(); + + PrivateKey sk2 = PrivateKey::FromSeed(seed2, 32); + PublicKey pk2 = sk2.GetPublicKey(); + + PrivateKey sk3 = PrivateKey::FromSeed(seed3, 32); + PublicKey pk3 = sk3.GetPublicKey(); + + PrivateKey sk4 = PrivateKey::FromSeed(seed4, 32); + PublicKey pk4 = sk4.GetPublicKey(); + + Signature sig1 = sk1.Sign(message1, sizeof(message1)); + Signature sig2 = sk2.Sign(message1, sizeof(message1)); + Signature sig3 = sk3.Sign(message1, sizeof(message1)); + Signature sig4 = sk4.Sign(message2, sizeof(message2)); + Signature sig5 = sk4.Sign(message1, sizeof(message1)); + Signature sig6 = sk2.Sign(message3, sizeof(message3)); + + std::vector sigsL = {sig1, sig2}; + std::vector sigsC = {sig3, sig4}; + std::vector sigsR = {sig5, sig6}; + Signature aggSigL = Signature::Aggregate(sigsL); + Signature aggSigC = Signature::Aggregate(sigsC); + Signature aggSigR = Signature::Aggregate(sigsR); + + std::vector sigsL2 = {aggSigL, aggSigC}; + Signature aggSigL2 = Signature::Aggregate(sigsL2); + + std::vector sigsFinal = {aggSigL2, aggSigR}; + Signature aggSigFinal = Signature::Aggregate(sigsFinal); + + REQUIRE(aggSigFinal.Verify()); + REQUIRE(aggSigFinal.GetAggregationInfo()->GetPubKeys().size() == 6); + std::vector divisorSigs = {aggSigL, sig6}; + aggSigFinal = aggSigFinal.DivideBy(divisorSigs); + REQUIRE(aggSigFinal.GetAggregationInfo()->GetPubKeys().size() == 3); + REQUIRE(aggSigFinal.Verify()); + + // Throws when the m/pk pair is not unique within the aggregate (sig1 + // is in both aggSigL2 and sig1. + std::vector sigsFinal2 = {aggSigL2, aggSigR, sig1}; + Signature aggSigFinal2 = Signature::Aggregate(sigsFinal2); + std::vector divisorSigs2 = {aggSigL}; + std::vector divisorSigs3 = {sig6}; + aggSigFinal2 = aggSigFinal2.DivideBy(divisorSigs3); + REQUIRE_THROWS(aggSigFinal2.DivideBy(divisorSigs)); + } + + SECTION("Should insecurely aggregate many sigs, same message") { + uint8_t message1[7] = {100, 2, 254, 88, 90, 45, 23}; + uint8_t hash1[BLS::MESSAGE_HASH_LEN]; + + std::vector sks; + std::vector pks; + std::vector sigs; + + Util::Hash256(hash1, message1, sizeof(message1)); + + for (int i = 0; i < 70; i++) { + uint8_t seed[32]; + getRandomSeed(seed); + PrivateKey sk = PrivateKey::FromSeed(seed, 32); + const PublicKey pk = sk.GetPublicKey(); + sks.push_back(sk); + pks.push_back(pk); + sigs.push_back(sk.SignInsecure(message1, sizeof(message1))); + } + + InsecureSignature aggSig = InsecureSignature::Aggregate(sigs); + const PublicKey aggPubKey = PublicKey::AggregateInsecure(pks); + REQUIRE(aggSig.Verify({hash1}, {aggPubKey})); + } + + SECTION("Should securely aggregate many sigs, same message") { + uint8_t message1[7] = {100, 2, 254, 88, 90, 45, 23}; + + std::vector sks; + std::vector pks; + std::vector sigs; + + for (int i = 0; i < 70; i++) { + uint8_t seed[32]; + getRandomSeed(seed); + PrivateKey sk = PrivateKey::FromSeed(seed, 32); + const PublicKey pk = sk.GetPublicKey(); + sks.push_back(sk); + pks.push_back(pk); + sigs.push_back(sk.Sign(message1, sizeof(message1))); + } + + Signature aggSig = Signature::Aggregate(sigs); + const PublicKey aggPubKey = PublicKey::Aggregate(pks); + aggSig.SetAggregationInfo(AggregationInfo::FromMsg( + aggPubKey, message1, sizeof(message1))); + REQUIRE(aggSig.Verify()); + } + + SECTION("Should have at least one sig, with AggregationInfo") { + uint8_t message1[7] = {100, 2, 254, 88, 90, 45, 23}; + uint8_t seed[32]; + getRandomSeed(seed); + PrivateKey sk1 = PrivateKey::FromSeed(seed, 32); + PublicKey pk1 = sk1.GetPublicKey(); + + Signature sig1 = sk1.Sign(message1, sizeof(message1)); + + std::vector const sigs = {}; + REQUIRE_THROWS(Signature::Aggregate(sigs)); + + sig1.SetAggregationInfo(AggregationInfo()); + std::vector const sigs2 = {sig1}; + REQUIRE_THROWS(Signature::Aggregate(sigs2)); + } + + SECTION("Should perform batch verification") { + uint8_t message1[7] = {100, 2, 254, 88, 90, 45, 23}; + uint8_t message2[8] = {10, 28, 254, 88, 90, 45, 29, 38}; + uint8_t message3[9] = {10, 28, 254, 88, 90, 45, 29, 38, 177}; + uint8_t seed[32]; + getRandomSeed(seed); + uint8_t seed2[32]; + getRandomSeed(seed2); + uint8_t seed3[32]; + getRandomSeed(seed3); + uint8_t seed4[32]; + getRandomSeed(seed4); + + PrivateKey sk1 = PrivateKey::FromSeed(seed, 32); + PublicKey pk1 = sk1.GetPublicKey(); + + PrivateKey sk2 = PrivateKey::FromSeed(seed2, 32); + PublicKey pk2 = sk2.GetPublicKey(); + + PrivateKey sk3 = PrivateKey::FromSeed(seed3, 32); + PublicKey pk3 = sk3.GetPublicKey(); + + PrivateKey sk4 = PrivateKey::FromSeed(seed4, 32); + PublicKey pk4 = sk4.GetPublicKey(); + + + Signature sig1 = sk1.Sign(message1, sizeof(message1)); + Signature sig2 = sk2.Sign(message1, sizeof(message1)); + Signature sig3 = sk3.Sign(message2, sizeof(message2)); + Signature sig4 = sk4.Sign(message3, sizeof(message3)); + Signature sig5 = sk3.Sign(message1, sizeof(message1)); + Signature sig6 = sk2.Sign(message1, sizeof(message1)); + Signature sig7 = sk4.Sign(message2, sizeof(message2)); + + std::vector const sigs = + {sig1, sig2, sig3, sig4, sig5, sig6, sig7}; + std::vector const pubKeys = + {pk1, pk2, pk3, pk4, pk3, pk2, pk4}; + std::vector const messages = + {message1, message1, message2, message3, message1, + message1, message2}; + std::vector const messageLens = + {sizeof(message1), sizeof(message1), sizeof(message2), + sizeof(message3), sizeof(message1), sizeof(message1), + sizeof(message2)}; + + // Verifier generates a batch signature for efficiency + Signature aggSig = Signature::Aggregate(sigs); + REQUIRE(aggSig.Verify()); + } + + SECTION("Should perform batch verification with cache optimization") { + uint8_t message1[7] = {100, 2, 254, 88, 90, 45, 23}; + uint8_t message2[8] = {10, 28, 254, 88, 90, 45, 29, 38}; + uint8_t message3[9] = {10, 28, 254, 88, 90, 45, 29, 38, 177}; + uint8_t seed[32]; + getRandomSeed(seed); + uint8_t seed2[32]; + getRandomSeed(seed2); + uint8_t seed3[32]; + getRandomSeed(seed3); + uint8_t seed4[32]; + getRandomSeed(seed4); + + PrivateKey sk1 = PrivateKey::FromSeed(seed, 32); + PublicKey pk1 = sk1.GetPublicKey(); + + PrivateKey sk2 = PrivateKey::FromSeed(seed2, 32); + PublicKey pk2 = sk2.GetPublicKey(); + + PrivateKey sk3 = PrivateKey::FromSeed(seed3, 32); + PublicKey pk3 = sk3.GetPublicKey(); + + PrivateKey sk4 = PrivateKey::FromSeed(seed4, 32); + PublicKey pk4 = sk4.GetPublicKey(); + + + Signature sig1 = sk1.Sign(message1, sizeof(message1)); + Signature sig2 = sk2.Sign(message1, sizeof(message1)); + Signature sig3 = sk3.Sign(message2, sizeof(message2)); + Signature sig4 = sk4.Sign(message3, sizeof(message3)); + Signature sig5 = sk3.Sign(message1, sizeof(message1)); + Signature sig6 = sk2.Sign(message1, sizeof(message1)); + Signature sig7 = sk4.Sign(message2, sizeof(message2)); + + std::vector const sigs = + {sig1, sig2, sig3, sig4, sig5, sig6, sig7}; + + REQUIRE(sig1.Verify()); + REQUIRE(sig3.Verify()); + REQUIRE(sig4.Verify()); + REQUIRE(sig7.Verify()); + std::vector cache = {sig1, sig3, sig4, sig7}; + + // Verifier generates a batch signature for efficiency + Signature aggSig = Signature::Aggregate(sigs); + + const Signature aggSig2 = aggSig.DivideBy(cache); + REQUIRE(aggSig.Verify()); + REQUIRE(aggSig2.Verify()); + } + + SECTION("Should aggregate same message with agg sk") { + uint8_t message1[7] = {100, 2, 254, 88, 90, 45, 23}; + uint8_t seed[32]; + getRandomSeed(seed); + uint8_t seed2[32]; + getRandomSeed(seed2); + + PrivateKey sk1 = PrivateKey::FromSeed(seed, 32); + PublicKey pk1 = sk1.GetPublicKey(); + + PrivateKey sk2 = PrivateKey::FromSeed(seed2, 32); + PublicKey pk2 = sk2.GetPublicKey(); + + std::vector const privateKeys = {sk1, sk2}; + std::vector const pubKeys = {pk1, pk2}; + const PrivateKey aggSk = PrivateKey::Aggregate( + privateKeys, pubKeys); + + Signature sig1 = sk1.Sign(message1, sizeof(message1)); + Signature sig2 = sk2.Sign(message1, sizeof(message1)); + + Signature aggSig2 = aggSk.Sign(message1, sizeof(message1)); + + std::vector const sigs = {sig1, sig2}; + std::vector const messages = {message1, message1}; + std::vector const messageLens = {sizeof(message1), sizeof(message1)}; + Signature aggSig = Signature::Aggregate(sigs); + ASSERT(aggSig == aggSig2); + + const PublicKey aggPubKey = PublicKey::Aggregate(pubKeys); + REQUIRE(aggSig.Verify()); + REQUIRE(aggSig2.Verify()); + } +} + +TEST_CASE("HD keys") { + SECTION("Should create an extended private key from seed") { + uint8_t seed[] = {1, 50, 6, 244, 24, 199, 1, 25}; + ExtendedPrivateKey esk = ExtendedPrivateKey::FromSeed( + seed, sizeof(seed)); + + ExtendedPrivateKey esk77 = esk.PrivateChild(77 + (1 << 31)); + ExtendedPrivateKey esk77copy = esk.PrivateChild(77 + (1 << 31)); + + REQUIRE(esk77 == esk77copy); + + ExtendedPrivateKey esk77nh = esk.PrivateChild(77); + + auto eskLong = esk.PrivateChild((1 << 31) + 5) + .PrivateChild(0) + .PrivateChild(0) + .PrivateChild((1 << 31) + 56) + .PrivateChild(70) + .PrivateChild(4); + uint8_t chainCode[32]; + eskLong.GetChainCode().Serialize(chainCode); + } + + + SECTION("Should match derivation through private and public keys") { + uint8_t seed[] = {1, 50, 6, 244, 24, 199, 1, 25}; + ExtendedPrivateKey esk = ExtendedPrivateKey::FromSeed( + seed, sizeof(seed)); + ExtendedPublicKey epk = esk.GetExtendedPublicKey(); + + PublicKey pk1 = esk.PrivateChild(238757).GetPublicKey(); + PublicKey pk2 = epk.PublicChild(238757).GetPublicKey(); + + REQUIRE(pk1 == pk2); + + PrivateKey sk3 = esk.PrivateChild(0) + .PrivateChild(3) + .PrivateChild(8) + .PrivateChild(1) + .GetPrivateKey(); + + PublicKey pk4 = epk.PublicChild(0) + .PublicChild(3) + .PublicChild(8) + .PublicChild(1) + .GetPublicKey(); + REQUIRE(sk3.GetPublicKey() == pk4); + + Signature sig = sk3.Sign(seed, sizeof(seed)); + + REQUIRE(sig.Verify()); + } + + SECTION("Should prevent hardened pk derivation") { + uint8_t seed[] = {1, 50, 6, 244, 24, 199, 1, 25}; + ExtendedPrivateKey esk = ExtendedPrivateKey::FromSeed( + seed, sizeof(seed)); + ExtendedPublicKey epk = esk.GetExtendedPublicKey(); + + ExtendedPrivateKey sk = esk.PrivateChild((1 << 31) + 3); + REQUIRE_THROWS(epk.PublicChild((1 << 31) + 3)); + } + + SECTION("Should derive public child from parent") { + uint8_t seed[] = {1, 50, 6, 244, 24, 199, 1, 0, 0, 0}; + ExtendedPrivateKey esk = ExtendedPrivateKey::FromSeed( + seed, sizeof(seed)); + ExtendedPublicKey epk = esk.GetExtendedPublicKey(); + + ExtendedPublicKey pk1 = esk.PublicChild(13); + ExtendedPublicKey pk2 = epk.PublicChild(13); + + REQUIRE(pk1 == pk2); + } + + SECTION("Should cout structures") { + uint8_t seed[] = {1, 50, 6, 244, 24, 199, 1, 0, 0, 0}; + ExtendedPrivateKey esk = ExtendedPrivateKey::FromSeed( + seed, sizeof(seed)); + ExtendedPublicKey epk = esk.GetExtendedPublicKey(); + + cout << epk << endl; + cout << epk.GetPublicKey() << endl; + cout << epk.GetChainCode() << endl; + + Signature sig1 = esk.GetPrivateKey() + .Sign(seed, sizeof(seed)); + cout << sig1 << endl; + } + + SECTION("Should serialize extended keys") { + uint8_t seed[] = {1, 50, 6, 244, 25, 199, 1, 25}; + ExtendedPrivateKey esk = ExtendedPrivateKey::FromSeed( + seed, sizeof(seed)); + ExtendedPublicKey epk = esk.GetExtendedPublicKey(); + + PublicKey pk1 = esk.PrivateChild(238757).GetPublicKey(); + PublicKey pk2 = epk.PublicChild(238757).GetPublicKey(); + + REQUIRE(pk1 == pk2); + + ExtendedPrivateKey sk3 = esk.PrivateChild(0) + .PrivateChild(3) + .PrivateChild(8) + .PrivateChild(1); + + ExtendedPublicKey pk4 = epk.PublicChild(0) + .PublicChild(3) + .PublicChild(8) + .PublicChild(1); + uint8_t buffer1[ExtendedPrivateKey::EXTENDED_PRIVATE_KEY_SIZE]; + uint8_t buffer2[ExtendedPublicKey::EXTENDED_PUBLIC_KEY_SIZE]; + uint8_t buffer3[ExtendedPublicKey::EXTENDED_PUBLIC_KEY_SIZE]; + + sk3.Serialize(buffer1); + sk3.GetExtendedPublicKey().Serialize(buffer2); + pk4.Serialize(buffer3); + REQUIRE(std::memcmp(buffer2, buffer3, + ExtendedPublicKey::EXTENDED_PUBLIC_KEY_SIZE) == 0); + } +} + +TEST_CASE("AggregationInfo") { + SECTION("Should create object") { + uint8_t message1[7] = {1, 65, 254, 88, 90, 45, 22}; + uint8_t message2[8] = {1, 65, 254, 88, 90, 45, 22, 12}; + uint8_t message3[8] = {2, 65, 254, 88, 90, 45, 22, 12}; + uint8_t message4[8] = {3, 65, 254, 88, 90, 45, 22, 12}; + uint8_t message5[8] = {4, 65, 254, 88, 90, 45, 22, 12}; + uint8_t message6[8] = {5, 65, 254, 88, 90, 45, 22, 12}; + uint8_t messageHash1[32]; + uint8_t messageHash2[32]; + uint8_t messageHash3[32]; + uint8_t messageHash4[32]; + uint8_t messageHash5[32]; + uint8_t messageHash6[32]; + Util::Hash256(messageHash1, message1, 7); + Util::Hash256(messageHash2, message2, 8); + Util::Hash256(messageHash3, message3, 8); + Util::Hash256(messageHash4, message4, 8); + Util::Hash256(messageHash5, message5, 8); + Util::Hash256(messageHash6, message6, 8); + + uint8_t seed[32]; + getRandomSeed(seed); + PrivateKey sk1 = PrivateKey::FromSeed(seed, 32); + getRandomSeed(seed); + PrivateKey sk2 = PrivateKey::FromSeed(seed, 32); + getRandomSeed(seed); + PrivateKey sk3 = PrivateKey::FromSeed(seed, 32); + getRandomSeed(seed); + PrivateKey sk4 = PrivateKey::FromSeed(seed, 32); + getRandomSeed(seed); + PrivateKey sk5 = PrivateKey::FromSeed(seed, 32); + getRandomSeed(seed); + PrivateKey sk6 = PrivateKey::FromSeed(seed, 32); + + PublicKey pk1 = sk1.GetPublicKey(); + PublicKey pk2 = sk2.GetPublicKey(); + PublicKey pk3 = sk3.GetPublicKey(); + PublicKey pk4 = sk4.GetPublicKey(); + PublicKey pk5 = sk5.GetPublicKey(); + PublicKey pk6 = sk6.GetPublicKey(); + + AggregationInfo a1 = AggregationInfo::FromMsgHash(pk1, messageHash1); + AggregationInfo a2 = AggregationInfo::FromMsgHash(pk2, messageHash2); + std::vector infosA = {a1, a2}; + std::vector infosAcopy = {a2, a1}; + + AggregationInfo a3 = AggregationInfo::FromMsgHash(pk3, messageHash1); + AggregationInfo a4 = AggregationInfo::FromMsgHash(pk4, messageHash1); + std::vector infosB = {a3, a4}; + std::vector infosBcopy = {a4, a3}; + std::vector infosC = {a1, a2, a3, a4}; + + AggregationInfo a5 = AggregationInfo::MergeInfos(infosA); + AggregationInfo a5b = AggregationInfo::MergeInfos(infosAcopy); + AggregationInfo a6 = AggregationInfo::MergeInfos(infosB); + AggregationInfo a6b = AggregationInfo::MergeInfos(infosBcopy); + std::vector infosD = {a5, a6}; + + AggregationInfo a7 = AggregationInfo::MergeInfos(infosC); + AggregationInfo a8 = AggregationInfo::MergeInfos(infosD); + + REQUIRE(a5 == a5b); + REQUIRE(a5 != a6); + REQUIRE(a6 == a6b); + + std::vector infosE = {a1, a3, a4}; + AggregationInfo a9 = AggregationInfo::MergeInfos(infosE); + std::vector infosF = {a2, a9}; + AggregationInfo a10 = AggregationInfo::MergeInfos(infosF); + + REQUIRE(a10 == a7); + + AggregationInfo a11 = AggregationInfo::FromMsgHash(pk1, messageHash1); + AggregationInfo a12 = AggregationInfo::FromMsgHash(pk2, messageHash2); + AggregationInfo a13 = AggregationInfo::FromMsgHash(pk3, messageHash3); + AggregationInfo a14 = AggregationInfo::FromMsgHash(pk4, messageHash4); + AggregationInfo a15 = AggregationInfo::FromMsgHash(pk5, messageHash5); + AggregationInfo a16 = AggregationInfo::FromMsgHash(pk6, messageHash6); + AggregationInfo a17 = AggregationInfo::FromMsgHash(pk6, messageHash5); + AggregationInfo a18 = AggregationInfo::FromMsgHash(pk5, messageHash6); + + // Tree L + std::vector L1 = {a15, a17}; + std::vector L2 = {a11, a13}; + std::vector L3 = {a18, a14}; + + AggregationInfo a19 = AggregationInfo::MergeInfos(L1); + AggregationInfo a20 = AggregationInfo::MergeInfos(L2); + AggregationInfo a21 = AggregationInfo::MergeInfos(L3); + + std::vector L4 = {a21, a16}; + std::vector L5 = {a19, a20}; + AggregationInfo a22 = AggregationInfo::MergeInfos(L4); + AggregationInfo a23 = AggregationInfo::MergeInfos(L5); + + std::vector L6 = {a22, a12}; + AggregationInfo a24 = AggregationInfo::MergeInfos(L6); + std::vector L7 = {a23, a24}; + AggregationInfo LFinal = AggregationInfo::MergeInfos(L7); + + // Tree R + std::vector R1 = {a17, a12, a11, a15}; + std::vector R2 = {a14, a18}; + + AggregationInfo a25 = AggregationInfo::MergeInfos(R1); + AggregationInfo a26 = AggregationInfo::MergeInfos(R2); + + std::vector R3 = {a26, a16}; + + AggregationInfo a27 = AggregationInfo::MergeInfos(R3); + + std::vector R4 = {a27, a13}; + AggregationInfo a28 = AggregationInfo::MergeInfos(R4); + std::vector R5 = {a25, a28}; + + AggregationInfo RFinal = AggregationInfo::MergeInfos(R5); + + REQUIRE(LFinal == RFinal); + } + + SECTION("Should aggregate with multiple levels.") { + uint8_t message1[7] = {100, 2, 254, 88, 90, 45, 23}; + uint8_t message2[8] = {192, 29, 2, 0, 0, 45, 23, 192}; + uint8_t message3[7] = {52, 29, 2, 0, 0, 45, 102}; + uint8_t message4[7] = {99, 29, 2, 0, 0, 45, 222}; + + uint8_t seed[32]; + getRandomSeed(seed); + uint8_t seed2[32]; + getRandomSeed(seed2); + + PrivateKey sk1 = PrivateKey::FromSeed(seed, 32); + PrivateKey sk2 = PrivateKey::FromSeed(seed2, 32); + + PublicKey pk1 = sk1.GetPublicKey(); + PublicKey pk2 = sk2.GetPublicKey(); + + Signature sig1 = sk1.Sign(message1, sizeof(message1)); + Signature sig2 = sk2.Sign(message2, sizeof(message2)); + Signature sig3 = sk2.Sign(message1, sizeof(message1)); + Signature sig4 = sk1.Sign(message3, sizeof(message3)); + Signature sig5 = sk1.Sign(message4, sizeof(message4)); + Signature sig6 = sk1.Sign(message1, sizeof(message1)); + + std::vector const sigsL = {sig1, sig2}; + std::vector const pksL = {pk1, pk2}; + const Signature aggSigL = Signature::Aggregate(sigsL); + + std::vector const sigsR = {sig3, sig4, sig6}; + const Signature aggSigR = Signature::Aggregate(sigsR); + + std::vector pk1Vec = {pk1}; + + std::vector sigs = {aggSigL, aggSigR, sig5}; + + const Signature aggSig = Signature::Aggregate(sigs); + + REQUIRE(aggSig.Verify()); + } + + SECTION("Should aggregate with multiple levels, degenerate") { + uint8_t message1[7] = {100, 2, 254, 88, 90, 45, 23}; + uint8_t seed[32]; + getRandomSeed(seed); + PrivateKey sk1 = PrivateKey::FromSeed(seed, 32); + PublicKey pk1 = sk1.GetPublicKey(); + Signature aggSig = sk1.Sign(message1, sizeof(message1)); + + for (size_t i = 0; i < 10; i++) { + getRandomSeed(seed); + PrivateKey sk = PrivateKey::FromSeed(seed, 32); + PublicKey pk = sk.GetPublicKey(); + Signature sig = sk.Sign(message1, sizeof(message1)); + std::vector sigs = {aggSig, sig}; + aggSig = Signature::Aggregate(sigs); + } + REQUIRE(aggSig.Verify()); + uint8_t sigSerialized[Signature::SIGNATURE_SIZE]; + aggSig.Serialize(sigSerialized); + + const Signature aggSig2 = Signature::FromBytes(sigSerialized); + REQUIRE(aggSig2.Verify() == false); + } + + SECTION("Should aggregate with multiple levels, different messages") { + uint8_t message1[7] = {100, 2, 254, 88, 90, 45, 23}; + uint8_t message2[7] = {192, 29, 2, 0, 0, 45, 23}; + uint8_t message3[7] = {52, 29, 2, 0, 0, 45, 102}; + uint8_t message4[7] = {99, 29, 2, 0, 0, 45, 222}; + + uint8_t seed[32]; + getRandomSeed(seed); + uint8_t seed2[32]; + getRandomSeed(seed2); + + PrivateKey sk1 = PrivateKey::FromSeed(seed, 32); + PrivateKey sk2 = PrivateKey::FromSeed(seed2, 32); + + PublicKey pk1 = sk1.GetPublicKey(); + PublicKey pk2 = sk2.GetPublicKey(); + + Signature sig1 = sk1.Sign(message1, sizeof(message1)); + Signature sig2 = sk2.Sign(message2, sizeof(message2)); + Signature sig3 = sk2.Sign(message3, sizeof(message4)); + Signature sig4 = sk1.Sign(message4, sizeof(message4)); + + std::vector const sigsL = {sig1, sig2}; + std::vector const pksL = {pk1, pk2}; + std::vector const messagesL = {message1, message2}; + std::vector const messageLensL = {sizeof(message1), + sizeof(message2)}; + const Signature aggSigL = Signature::Aggregate(sigsL); + + std::vector const sigsR = {sig3, sig4}; + std::vector const pksR = {pk2, pk1}; + std::vector const messagesR = {message3, message4}; + std::vector const messageLensR = {sizeof(message3), + sizeof(message4)}; + const Signature aggSigR = Signature::Aggregate(sigsR); + + std::vector sigs = {aggSigL, aggSigR}; + std::vector > pks = {pksL, pksR}; + std::vector > messages = {messagesL, messagesR}; + std::vector > messageLens = {messageLensL, messageLensR}; + + const Signature aggSig = Signature::Aggregate(sigs); + + std::vector allPks = {pk1, pk2, pk2, pk1}; + std::vector allMessages = {message1, message2, + message3, message4}; + std::vector allMessageLens = {sizeof(message1), sizeof(message2), + sizeof(message3), sizeof(message4)}; + + REQUIRE(aggSig.Verify()); + } + + SECTION("Should sign and verify using prepend method") { + uint8_t message1[7] = {100, 2, 254, 88, 90, 45, 23}; + uint8_t seed[32]; + getRandomSeed(seed); + PrivateKey sk1 = PrivateKey::FromSeed(seed, 32); + PublicKey pk1 = sk1.GetPublicKey(); + std::cout << "PK: " << pk1 << std::endl; + + uint8_t messageHash[BLS::MESSAGE_HASH_LEN]; + Util::Hash256(messageHash, message1, 7); + vector messageHashes = {messageHash}; + vector pks = {pk1}; + + const PrependSignature sig1 = sk1.SignPrepend(message1, 7); + REQUIRE(sig1.Verify(messageHashes, pks)); + + uint8_t sigData[PrependSignature::SIGNATURE_SIZE]; + uint8_t sigData2[PrependSignature::SIGNATURE_SIZE]; + sig1.Serialize(sigData); + sig1.GetInsecureSig().Serialize(sigData2); + REQUIRE(memcmp(sigData, sigData2, PrependSignature::SIGNATURE_SIZE) != 0); + + PrependSignature sig2 = PrependSignature::FromBytes(sigData); + REQUIRE(sig1 == sig2); + + REQUIRE(sig2.Verify(messageHashes, pks)); + } + + SECTION("Should aggregate using prepend method") { + uint8_t message1[7] = {100, 2, 254, 88, 90, 45, 23}; + uint8_t message2[7] = {192, 29, 2, 0, 0, 45, 23}; + + uint8_t seed[32]; + getRandomSeed(seed); + uint8_t seed2[32]; + getRandomSeed(seed2); + uint8_t seed3[32]; + getRandomSeed(seed3); + + PrivateKey sk1 = PrivateKey::FromSeed(seed, 32); + PrivateKey sk2 = PrivateKey::FromSeed(seed2, 32); + PrivateKey sk3 = PrivateKey::FromSeed(seed3, 32); + + PublicKey pk1 = sk1.GetPublicKey(); + PublicKey pk2 = sk2.GetPublicKey(); + PublicKey pk3 = sk3.GetPublicKey(); + + PrependSignature sig1 = sk1.SignPrepend(message1, 7); + PrependSignature sig2 = sk2.SignPrepend(message1, 7); + PrependSignature sig3 = sk3.SignPrepend(message2, 7); + + uint8_t messageHash1[BLS::MESSAGE_HASH_LEN]; + uint8_t messageHash2[BLS::MESSAGE_HASH_LEN]; + Util::Hash256(messageHash1, message1, 7); + Util::Hash256(messageHash2, message2, 7); + vector messageHashes1 = {messageHash1}; + vector messageHashes2 = {messageHash2}; + vector messageHashes = {messageHash1, messageHash1, messageHash2}; + vector pks1 = {pk1}; + vector pks2 = {pk2}; + vector pks3 = {pk3}; + vector pks = {pk1, pk2, pk3}; + + REQUIRE(sig1.Verify(messageHashes1, pks1)); + REQUIRE(sig2.Verify(messageHashes1, pks2)); + REQUIRE(sig3.Verify(messageHashes2, pks3)); + + vector sigs = {sig1, sig2, sig3}; + + PrependSignature agg = PrependSignature::Aggregate(sigs); + REQUIRE(agg.Verify(messageHashes, pks)); + + vector pksWrong = {pk1, pk2, pk2}; + REQUIRE(agg.Verify(messageHashes, pksWrong) == false); + } + + SECTION("README") { + // Example seed, used to generate private key. Always use + // a secure RNG with sufficient entropy to generate a seed. + uint8_t seed[] = {0, 50, 6, 244, 24, 199, 1, 25, 52, 88, 192, + 19, 18, 12, 89, 6, 220, 18, 102, 58, 209, + 82, 12, 62, 89, 110, 182, 9, 44, 20, 254, 22}; + + PrivateKey sk = PrivateKey::FromSeed(seed, sizeof(seed)); + PublicKey pk = sk.GetPublicKey(); + + uint8_t msg[] = {100, 2, 254, 88, 90, 45, 23}; + + Signature sig = sk.Sign(msg, sizeof(msg)); + + uint8_t skBytes[PrivateKey::PRIVATE_KEY_SIZE]; // 32 byte array + uint8_t pkBytes[PublicKey::PUBLIC_KEY_SIZE]; // 48 byte array + uint8_t sigBytes[Signature::SIGNATURE_SIZE]; // 96 byte array + + sk.Serialize(skBytes); // 32 bytes + pk.Serialize(pkBytes); // 48 bytes + sig.Serialize(sigBytes); // 96 bytes + // Takes array of 32 bytes + sk = PrivateKey::FromBytes(skBytes); + + // Takes array of 48 bytes + pk = PublicKey::FromBytes(pkBytes); + + // Takes array of 96 bytes + sig = Signature::FromBytes(sigBytes); + // Add information required for verification, to sig object + sig.SetAggregationInfo(AggregationInfo::FromMsg(pk, msg, sizeof(msg))); + + bool ok = sig.Verify(); + // Generate some more private keys + seed[0] = 1; + PrivateKey sk1 = PrivateKey::FromSeed(seed, sizeof(seed)); + seed[0] = 2; + PrivateKey sk2 = PrivateKey::FromSeed(seed, sizeof(seed)); + + // Generate first sig + PublicKey pk1 = sk1.GetPublicKey(); + Signature sig1 = sk1.Sign(msg, sizeof(msg)); + + // Generate second sig + PublicKey pk2 = sk2.GetPublicKey(); + Signature sig2 = sk2.Sign(msg, sizeof(msg)); + + // Aggregate signatures together + std::vector sigs = {sig1, sig2}; + Signature aggSig = Signature::Aggregate(sigs); + + // For same message, public keys can be aggregated into one. + // The signature can be verified the same as a single signature, + // using this public key. + std::vector pubKeys = {pk1, pk2}; + PublicKey aggPubKey = PublicKey::Aggregate(pubKeys); + // Generate one more key + seed[0] = 3; + PrivateKey sk3 = PrivateKey::FromSeed(seed, sizeof(seed)); + PublicKey pk3 = sk3.GetPublicKey(); + uint8_t msg2[] = {100, 2, 254, 88, 90, 45, 23}; + + // Generate the signatures, assuming we have 3 private keys + sig1 = sk1.Sign(msg, sizeof(msg)); + sig2 = sk2.Sign(msg, sizeof(msg)); + Signature sig3 = sk3.Sign(msg2, sizeof(msg2)); + + // They can be noninteractively combined by anyone + // Aggregation below can also be done by the verifier, to + // make batch verification more efficient + std::vector sigsL = {sig1, sig2}; + Signature aggSigL = Signature::Aggregate(sigsL); + + // Arbitrary trees of aggregates + std::vector sigsFinal = {aggSigL, sig3}; + Signature aggSigFinal = Signature::Aggregate(sigsFinal); + + // Serialize the final signature + aggSigFinal.Serialize(sigBytes); + // Deserialize aggregate signature + aggSigFinal = Signature::FromBytes(sigBytes); + + // Create aggregation information (or deserialize it) + AggregationInfo a1 = AggregationInfo::FromMsg(pk1, msg, sizeof(msg)); + AggregationInfo a2 = AggregationInfo::FromMsg(pk2, msg, sizeof(msg)); + AggregationInfo a3 = AggregationInfo::FromMsg(pk3, msg2, sizeof(msg2)); + std::vector infos = {a1, a2}; + AggregationInfo a1a2 = AggregationInfo::MergeInfos(infos); + std::vector infos2 = {a1a2, a3}; + AggregationInfo aFinal = AggregationInfo::MergeInfos(infos2); + + // Verify final signature using the aggregation info + aggSigFinal.SetAggregationInfo(aFinal); + ok = aggSigFinal.Verify(); + + // If you previously verified a signature, you can also divide + // the aggregate signature by the signature you already verified. + ok = aggSigL.Verify(); + std::vector cache = {aggSigL}; + aggSigFinal = aggSigFinal.DivideBy(cache); + + // Final verification is now more efficient + ok = aggSigFinal.Verify(); + + std::vector privateKeysList = {sk1, sk2}; + std::vector pubKeysList = {pk1, pk2}; + + // Create an aggregate private key, that can generate + // aggregate signatures + const PrivateKey aggSk = PrivateKey::Aggregate( + privateKeysList, pubKeysList); + + Signature aggSig3 = aggSk.Sign(msg, sizeof(msg)); + + PrependSignature prepend1 = sk1.SignPrepend(msg, sizeof(msg)); + PrependSignature prepend2 = sk2.SignPrepend(msg, sizeof(msg)); + std::vector prependPubKeys = {pk1, pk2}; + uint8_t messageHash[BLS::MESSAGE_HASH_LEN]; + Util::Hash256(messageHash, msg, sizeof(msg)); + std::vector hashes = {messageHash, messageHash}; + std::vector prependSigs = {prepend1, prepend2}; + PrependSignature prependAgg = PrependSignature::Aggregate(prependSigs); + prependAgg.Verify(hashes, prependPubKeys); + } +} + +TEST_CASE("Threshold") { + SECTION("Threshold tests") { + // To initialize a T of N threshold key under a + // Joint-Feldman scheme: + size_t T = 2; + size_t N = 3; + + // 1. Each player calls Threshold::Create. + // They send everyone commitment to the polynomial, + // and send secret share fragments frags[j-1] to + // the j-th player (All players have index >= 1). + + // PublicKey commits[N][T] + // PrivateKey frags[N][N] + std::vector> commits; + std::vector> frags; + for (size_t i = 0; i < N; ++i) { + commits.emplace_back(std::vector()); + frags.emplace_back(std::vector()); + for (size_t j = 0; j < N; ++j) { + if (j < T) { + g1_t g; + commits[i].emplace_back(PublicKey::FromG1(&g)); + } + bn_t b; + bn_new(b); + frags[i].emplace_back(PrivateKey::FromBN(b)); + } + } + + PrivateKey sk1 = Threshold::Create(commits[0], frags[0], T, N); + PrivateKey sk2 = Threshold::Create(commits[1], frags[1], T, N); + PrivateKey sk3 = Threshold::Create(commits[2], frags[2], T, N); + + // 2. Each player calls Threshold::VerifySecretFragment + // on all secret fragments they receive. If any verify + // false, they complain to abort the scheme. (Note that + // repeatedly aborting, or 'speaking' last, can bias the + // master public key.) + + for (int target = 1; target <= N; ++target) { + for (int source = 1; source <= N; ++source) { + REQUIRE(Threshold::VerifySecretFragment( + target, frags[source-1][target-1], commits[source-1], T)); + } + } + + // 3. Each player computes the shared, master public key: + // masterPubkey = PublicKey::AggregateInsecure(...) + // They also create their secret share from all secret + // fragments received (now verified): + // secretShare = PrivateKey::AggregateInsecure(...) + + PublicKey masterPubkey = PublicKey::AggregateInsecure({ + commits[0][0], commits[1][0], commits[2][0] + }); + + // recvdFrags[j][i] = frags[i][j] + std::vector> recvdFrags = {{}}; + for (int i = 0; i < N; ++i) { + recvdFrags.emplace_back(std::vector()); + for (int j = 0; j < N; ++j) { + recvdFrags[i].emplace_back(frags[j][i]); + } + } + + PrivateKey secretShare1 = PrivateKey::AggregateInsecure(recvdFrags[0]); + PrivateKey secretShare2 = PrivateKey::AggregateInsecure(recvdFrags[1]); + PrivateKey secretShare3 = PrivateKey::AggregateInsecure(recvdFrags[2]); + + // 4a. Player P creates a pre-multiplied signature share wrt T players: + // sigShare = Threshold::SignWithCoefficient(...) + // These signature shares can be combined to sign the msg: + // signature = InsecureSignature::Aggregate(...) + // The advantage of this approach is that forming the final signature + // no longer requires information about the players. + + uint8_t msg[] = {100, 2, 254, 88, 90, 45, 23}; + uint8_t hash[32]; + Util::Hash256(hash, msg, sizeof(msg)); + + size_t players[] = {1, 3}; + // For example, players 1 and 3 sign. + // As we have verified the coefficients through the commitments given, + // using InsecureSignature is okay. + InsecureSignature sigShareC1 = Threshold::SignWithCoefficient( + secretShare1, msg, (size_t) sizeof(msg), (size_t) 1, players, T); + InsecureSignature sigShareC3 = Threshold::SignWithCoefficient( + secretShare3, msg, (size_t) sizeof(msg), (size_t) 3, players, T); + + InsecureSignature signature = InsecureSignature::Aggregate({ + sigShareC1, sigShareC3}); + + REQUIRE(signature.Verify({hash}, {masterPubkey})); + + // 4b. Alternatively, players may sign the message blindly, creating + // a unit signature share: sigShare = secretShare.SignInsecure(...) + // These signatures may be combined with lagrange coefficients to + // sign the message: signature = Threshold::AggregateUnitSigs(...) + // The advantage to this approach is that each player does not need + // to know the final list of signatories. + + // For example, players 1 and 3 sign. + InsecureSignature sigShareU1 = secretShare1.SignInsecure( + msg, (size_t) sizeof(msg)); + InsecureSignature sigShareU3 = secretShare3.SignInsecure( + msg, (size_t) sizeof(msg)); + InsecureSignature signature2 = Threshold::AggregateUnitSigs( + {sigShareU1, sigShareU3}, msg, (size_t) sizeof(msg), players, T); + + REQUIRE(signature2.Verify({hash}, {masterPubkey})); + } +} + +int main(int argc, char* argv[]) { + int result = Catch::Session().run(argc, argv); + return result; +} diff --git a/bls/src/threshold.cpp b/bls/src/threshold.cpp new file mode 100644 index 00000000..f7291149 --- /dev/null +++ b/bls/src/threshold.cpp @@ -0,0 +1,227 @@ +// Copyright 2018 Chia Network Inc + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include + +#include "signature.hpp" +#include "bls.hpp" + +using std::string; +namespace bls { + +PrivateKey Threshold::Create(std::vector &commitment, + std::vector &secretFragments, size_t T, size_t N) { + if (T < 1 || T > N) { + throw std::string("Threshold parameter T must be between 1 and N"); + } + PrivateKey k; + k.AllocateKeyData(); + bn_t ord; + bn_new(ord); + g1_get_ord(ord); + + // poly = [random(1, ord-1), ...] + // commitment = [g1 * poly[i], ...] + g1_t g; + bn_t *poly = new bn_t[T]; + for (int i = 0; i < T; ++i) { + bn_new(poly[i]); + bn_rand_mod(poly[i], ord); + g1_mul_gen(g, poly[i]); + commitment[i] = PublicKey::FromG1(&g); + } + + bn_t frag, w, e; + bn_new(frag); + bn_new(w); + bn_new(e); + for (int x = 1; x <= N; ++x) { + bn_zero(frag); + // frag = sum_i (poly[i] * (x ** i % ord)) + for (int i = 0; i < T; ++i) { + bn_set_dig(w, (dig_t) x); + bn_set_dig(e, (dig_t) i); + bn_mxp(w, w, e, ord); + bn_mul(w, w, poly[i]); + bn_mod(w, w, ord); + bn_add(frag, frag, w); + bn_mod(frag, frag, ord); + } + secretFragments[x-1] = PrivateKey::FromBN(frag); + } + + bn_copy(*k.keydata, poly[0]); + + delete[] poly; + + return k; +} + +InsecureSignature Threshold::SignWithCoefficient(PrivateKey sk, const uint8_t *msg, + size_t len, size_t player, size_t *players, size_t T) { + if (player == 0) { + throw std::string("player must be a positive integer"); + } + int index = std::distance(players, + std::find(players, players + T, player)); + + uint8_t messageHash[BLS::MESSAGE_HASH_LEN]; + Util::Hash256(messageHash, msg, len); + + g2_t sig; + g2_map(sig, messageHash, BLS::MESSAGE_HASH_LEN, 0); + + bn_t *coeffs = new bn_t[T]; + try { + Threshold::LagrangeCoeffsAtZero(coeffs, players, T); + } catch (const std::exception& e) { + delete[] coeffs; + throw e; + } + + g2_mul(sig, sig, coeffs[index]); + g2_mul(sig, sig, *sk.keydata); + + delete[] coeffs; + + return InsecureSignature::FromG2(&sig); +} + +InsecureSignature Threshold::AggregateUnitSigs( + std::vector sigs, const uint8_t *msg, size_t len, + size_t *players, size_t T) { + uint8_t messageHash[BLS::MESSAGE_HASH_LEN]; + Util::Hash256(messageHash, msg, len); + + bn_t *coeffs = new bn_t[T]; + Threshold::LagrangeCoeffsAtZero(coeffs, players, T); + + std::vector powers; + for (size_t i = 0; i < T; ++i) { + powers.emplace_back(sigs[i].Exp(coeffs[i])); + } + + InsecureSignature ret = InsecureSignature::Aggregate(powers); + delete[] coeffs; + return ret; +} + +void Threshold::LagrangeCoeffsAtZero(bn_t *res, size_t *players, size_t T) { + if (T <= 0) { + throw std::invalid_argument("T must be a positive integer"); + } + // n: the order of the curve + bn_t denominator, n, u, weight, x; + bn_new(denominator); + bn_new(n); + bn_new(weight); + bn_new(x); + g1_get_ord(n); + + bn_zero(denominator); + for (int j = 0; j < T; ++j) { + if (players[j] <= 0) { + throw std::invalid_argument("Player index must be positive"); + } + // weight = (prod (X[j] - X[i])) ** -1 + bn_set_dig(weight, (dig_t) 1); + for (int i = 0; i < T; ++i) if (i != j) { + if (players[j] > players[i]) { + bn_set_dig(x, (dig_t)(players[j] - players[i])); + } else if (players[i] > players[j]){ + bn_set_dig(x, (dig_t)(players[i] - players[j])); + bn_sub(x, n, x); + } else { + throw std::invalid_argument("Must not have duplicate player indices"); + } + bn_mul(weight, weight, x); + bn_mod(weight, weight, n); + } + // weight = weight ** -1 + // x = (-players[j]) ** -1 + if (bn_is_zero(weight)) { + throw std::invalid_argument("Player indices can't be equiv. mod group order"); + } + fp_inv_exgcd_bn(weight, weight, n); + bn_set_dig(x, (dig_t) players[j]); + bn_sub(x, n, x); + fp_inv_exgcd_bn(x, x, n); + + bn_mul(weight, weight, x); + bn_mod(weight, weight, n); + bn_copy(res[j], weight); + + bn_add(denominator, denominator, weight); + } + + fp_inv_exgcd_bn(denominator, denominator, n); + for (int j = 0; j < T; ++j) { + bn_mul(res[j], res[j], denominator); + bn_mod(res[j], res[j], n); + } +} + +void Threshold::InterpolateAtZero(bn_t res, size_t *X, bn_t *Y, size_t T) { + if (T <= 0) { + throw std::invalid_argument("T must be a positive integer"); + } + + bn_zero(res); + bn_t n; + bn_new(n); + g1_get_ord(n); + + bn_t *coeffs = new bn_t[T]; + LagrangeCoeffsAtZero(coeffs, X, T); + for (int i = 0; i < T; ++i) { + // res += coeffs[i] * Y[i] + bn_mul(coeffs[i], coeffs[i], Y[i]); + bn_mod(coeffs[i], coeffs[i], n); + bn_add(res, res, coeffs[i]); + bn_mod(res, res, n); + } +} + +bool Threshold::VerifySecretFragment(size_t player, PrivateKey secretFragment, std::vector const& commitment, size_t T) { + if (T <= 0) { + throw std::invalid_argument("T must be a positive integer"); + } else if (player <= 0) { + throw std::invalid_argument("Player index must be positive"); + } + + g1_t rhs, t; + bn_t x, n, e; + bn_new(x); + bn_new(n); + bn_new(e); + g1_get_ord(n); + + // rhs = sum commitment[i] ** (player ** i) + std::vector expKeys; + expKeys.reserve(T); + for (size_t i = 0; i < T; i++) { + bn_set_dig(x, (dig_t) player); + bn_set_dig(e, (dig_t) i); + bn_mxp(x, x, e, n); + expKeys.emplace_back(commitment[i].Exp(x)); + } + + return (secretFragment.GetPublicKey() == + PublicKey::AggregateInsecure(expKeys)); +} + +} // end namespace bls diff --git a/bls/src/threshold.hpp b/bls/src/threshold.hpp new file mode 100644 index 00000000..3d39689a --- /dev/null +++ b/bls/src/threshold.hpp @@ -0,0 +1,118 @@ +// Copyright 2018 Chia Network Inc + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_BLSTHRESHOLD_HPP_ +#define SRC_BLSTHRESHOLD_HPP_ + +#include +#include + +#include "relic_conf.h" + +#if defined GMP && ARITH == GMP +#include +#endif + +#include "util.hpp" + +namespace bls { +/** + * Utility functions for threshold signatures. + */ +class Threshold { +public: + /** + * Construct a PrivateKey with associated data suitable for a + * threshold signature scheme. + * + * @param[out] commitment - commitments g1 * [x^i]P to the polynomial. + * @param[out] secretFragments - P(j) for j = 1..N + * @param[in] T - the threshold parameter, deg(P) + 1 + * @param[in] N - the number of players. + * @return PrivateKey representing P(0). + */ + static PrivateKey Create(std::vector &commitment, + std::vector &secretFragments, + size_t T, size_t N); + + /** + * Sign a message with lagrange coefficients. The T signatures signed + * this way (with the same parameters players and T) can be multiplied + * together to create a final signature for that message. + * + * @param[in] sk - secret key to sign with + * @param[in] msg - message to sign + * @param[in] len - length of message + * @param[in] player - index (>= 1) of player + * @param[in] players - list of players + * @param[in] T - number of players and threshold parameter + * @return the partial signature. + */ + static InsecureSignature SignWithCoefficient(PrivateKey sk, const uint8_t *msg, + size_t len, size_t player, size_t *players, size_t T); + + /** + * Aggregate signatures (that have not been multiplied by lagrange + * coefficients) into a final signature for the master private key. + * + * @param[in] sigs - list of sigs + * @param[in] msg - message to sign + * @param[in] len - length of message + * @param[in] players - list of players + * @param[in] T - number of players and threshold parameter + * @return the final signature. + */ + static InsecureSignature AggregateUnitSigs( + std::vector sigs, const uint8_t *msg, size_t len, + size_t *players, size_t T); + + /** + * Returns lagrange coefficients of a polynomial evaluated at zero. + * If we have T points (players[i], P(players[i])), it interpolates + * to a degree T-1 polynomial P. The returned coefficients are + * such that P(0) = sum_i res[i] * P(players[i]). + * + * @param[out] res - the lagrange coefficients. + * @param[in] players - the indices of each player. + * @param[in] T - the number of points. + */ + static void LagrangeCoeffsAtZero(bn_t *res, size_t *players, size_t T); + + /** + * The points (X[i], Y[i]) for i = 0...T-1 interpolate into P, + * a degree T-1 polynomial. Returns P(0). + * + * @param[out] res - the value P(0). + * @param[in] X - the X coordinates, + * @param[in] Y - the Y coordinates. + * @param[in] T - the number of points. + */ + static void InterpolateAtZero(bn_t res, size_t *X, bn_t *Y, size_t T); + + /** + * Return true iff the secretFragment from the given player + * matches their given commitment to a polynomial. + * + * @param[in] player - the index of the player giving the fragment. + * @param[in] secretFragment - the fragment, a number in [1, n) + * @param[in] commitment - the player's claim commitment[i] = g1 * [x^i]P + * @param[in] T - the threshold parameter and number of points. + * @return true if the fragment is verified, else false. + */ + static bool VerifySecretFragment(size_t player, PrivateKey secretFragment, + std::vector const& commitment, size_t T); +}; +} // end namespace bls + +#endif // SRC_BLSTHRESHOLD_HPP_ diff --git a/bls/src/util.hpp b/bls/src/util.hpp new file mode 100644 index 00000000..1f03816d --- /dev/null +++ b/bls/src/util.hpp @@ -0,0 +1,112 @@ +// Copyright 2018 Chia Network Inc + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 + +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef SRC_BLSUTIL_HPP_ +#define SRC_BLSUTIL_HPP_ + +#include +#include +#include +#include +#include + +#include "relic_conf.h" + +#if defined GMP && ARITH == GMP +#include +#endif + +#include "relic.h" +#include "relic_test.h" + +namespace bls { + +class BLS; + +class Util { + public: + typedef void *(*SecureAllocCallback)(size_t); + typedef void (*SecureFreeCallback)(void*); + public: + static void Hash256(uint8_t* output, const uint8_t* message, + size_t messageLen) { + md_map_sh256(output, message, messageLen); + } + + template + struct BytesCompare { + bool operator() (const uint8_t* lhs, const uint8_t* rhs) const { + for (size_t i = 0; i < S; i++) { + if (lhs[i] < rhs[i]) return true; + if (lhs[i] > rhs[i]) return false; + } + return false; + } + }; + typedef struct BytesCompare<32> BytesCompare32; + typedef struct BytesCompare<80> BytesCompare80; + + static std::string HexStr(const uint8_t* data, size_t len) { + std::stringstream s; + s << std::hex; + for (int i=0; i < len; ++i) + s << std::setw(2) << std::setfill('0') << static_cast(data[i]); + return s.str(); + } + + /* + * Securely allocates a portion of memory, using libsodium. This prevents + * paging to disk, and zeroes out the memory when it's freed. + */ + template + static T* SecAlloc(size_t numTs) { + return static_cast(secureAllocCallback(sizeof(T) * numTs)); + } + + /* + * Frees memory allocated using SecAlloc. + */ + static void SecFree(void* ptr) { + secureFreeCallback(ptr); + } + + /* + * Converts a 32 bit int to bytes. + */ + static void IntToFourBytes(uint8_t* result, + const uint32_t input) { + for (size_t i = 0; i < 4; i++) { + result[3 - i] = (input >> (i * 8)); + } + } + + /* + * Converts a byte array to a 32 bit int. + */ + static uint32_t FourBytesToInt(const uint8_t* bytes) { + uint32_t sum = 0; + for (size_t i = 0; i < 4; i++) { + uint32_t addend = bytes[i] << (8 * (3 - i)); + sum += addend; + } + return sum; + } + + private: + friend class BLS; + static SecureAllocCallback secureAllocCallback; + static SecureFreeCallback secureFreeCallback; +}; +} // end namespace bls +#endif // SRC_BLSUTIL_HPP_ diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index e0e3e2ac..77fe77c3 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -18,8 +18,15 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +INCLUDE_DIRECTORIES(bls/src) +LINK_DIRECTORIES(bls/build/src) + +LINK_DIRECTORIES(bls/build/contrib/relic/lib) +INCLUDE_DIRECTORIES(bls/build/contrib/relic/include) +INCLUDE_DIRECTORIES(bls/contrib/relic/include) + add_executable(hotstuff-app hotstuff_app.cpp) -target_link_libraries(hotstuff-app hotstuff_static) +target_link_libraries(hotstuff-app hotstuff_static blstmp relic_s) add_executable(hotstuff-client hotstuff_client.cpp) -target_link_libraries(hotstuff-client hotstuff_static) +target_link_libraries(hotstuff-client hotstuff_static blstmp relic_s) diff --git a/examples/hotstuff_app.cpp b/examples/hotstuff_app.cpp index 63c29f38..5edca006 100644 --- a/examples/hotstuff_app.cpp +++ b/examples/hotstuff_app.cpp @@ -63,7 +63,7 @@ using hotstuff::MsgRespCmd; using hotstuff::get_hash; using hotstuff::promise_t; -using HotStuff = hotstuff::HotStuffSecp256k1; +using HotStuff = hotstuff::HotStuffSecp256k1 ; class HotStuffApp: public HotStuff { double stat_period; @@ -132,6 +132,7 @@ class HotStuffApp: public HotStuff { const ClientNetwork::Config &clinet_config); void start(const std::vector> &reps); + void set_master_pub(const std::string &master); void stop(); }; @@ -173,6 +174,7 @@ int main(int argc, char **argv) { auto opt_notls = Config::OptValFlag::create(false); auto opt_max_rep_msg = Config::OptValInt::create(4 << 20); // 4M by default auto opt_max_cli_msg = Config::OptValInt::create(65536); // 64K by default + auto opt_master_pub = Config::OptValStr::create(""); config.add_opt("block-size", opt_blk_size, Config::SET_VAL); config.add_opt("parent-limit", opt_parent_limit, Config::SET_VAL); @@ -197,6 +199,7 @@ int main(int argc, char **argv) { config.add_opt("max-rep-msg", opt_max_rep_msg, Config::SET_VAL, 'S', "the maximum replica message size"); config.add_opt("max-cli-msg", opt_max_cli_msg, Config::SET_VAL, 'S', "the maximum client message size"); config.add_opt("help", opt_help, Config::SWITCH_ON, 'h', "show this help info"); + config.add_opt("master-pub", opt_master_pub, Config::SET_VAL, 'p', "master public key for BLS"); EventContext ec; config.parse(argc, argv); @@ -283,6 +286,11 @@ int main(int argc, char **argv) { hotstuff::from_hex(std::get<1>(r)), hotstuff::from_hex(std::get<2>(r)))); } + + if (!opt_master_pub->get().empty()) { + papp->set_master_pub(opt_master_pub->get()); + } + auto shutdown = [&](int) { papp->stop(); }; salticidae::SigEvent ev_sigint(ec, shutdown); salticidae::SigEvent ev_sigterm(ec, shutdown); @@ -290,6 +298,7 @@ int main(int argc, char **argv) { ev_sigterm.add(SIGTERM); papp->start(reps); + elapsed.stop(true); return 0; } @@ -412,3 +421,7 @@ void HotStuffApp::print_stat() const { HOTSTUFF_LOG_INFO("--- end client msg. ---"); #endif } + +void HotStuffApp::set_master_pub(const std::string& masterPub) { + HotStuff::set_master_pub(hotstuff::from_hex(masterPub)); +} diff --git a/hotstuff-bls.conf b/hotstuff-bls.conf new file mode 100644 index 00000000..ba68173f --- /dev/null +++ b/hotstuff-bls.conf @@ -0,0 +1,9 @@ +block-size = 1 +pace-maker = rr +master-pub = 8df60c260df14181197974051be16d9a8485c6c828b1d4f241da11bc60c7d068f0ad7e0c1d269fc7aa86f2b9204e1ca1 +replica = 127.0.0.1:10000;20000, 8a0f04a4d41e7a993336d3f5cb5f32d2fa468af5ceae179b1b9f1c6e698da5c98ccc8cfcc4226f8c3eaf466941c6c8f9, 542865a568784c4e77c172b82e99cb8a1a53b7bee5f86843b04960ea4157f420 +replica = 127.0.0.1:10001;20001, 03d1052326a84450c0086f64515a71524f8f5e13cd49ca0fddf692204bde34c7e036b201668704d9ba77cb62e38cae81, c261250345ebcd676a0edeea173526608604f626b2e8bc4fd2142d3bde1d44d5 +replica = 127.0.0.1:10002;20002, 842d687d00d36f21f971858ab7cb6d5fccc6f95c016abb9f69e3598ccb4d29efa998d5243308df0a107fb0369f59cfae, 065b010aed5629edfb5289e8b22fc6cc6b33c4013bfdd128caba80c3c02d6d78 +replica = 127.0.0.1:10003;20003, 81c8addfbeae6e7fc06dbad0f4db0b438dffd62cf235c770f776b3c96c866f7a74ad0ddda5281df2c3635a77a4bf7e85, 6540a0fea67efcb08f53ec3a952df4c3f0e2e07c2778fd92320807717e29a651 + + diff --git a/hotstuff-sec-bls0.conf b/hotstuff-sec-bls0.conf new file mode 100644 index 00000000..0a264df3 --- /dev/null +++ b/hotstuff-sec-bls0.conf @@ -0,0 +1,4 @@ +privkey = 2f055108a3e61a827298b5e1f0bc6915fc194ecfbaad33ba5516a63c8880319b +tls-privkey = 308204a10201000282010100c5a358cee61ca7592dbe62cd28225426dc3fc65b33432043efb5e8fcfaf334720b2000d10c422172e6f94f82746928a6d51193342a1555684eedb141321170cb02cc7b189f5506cc30cb5c26d9b84123328ed6df61fc1a6582b046def7a662bb15d84e29ffa279f1d853c25ca79fbe3fab0200f8c85566a5eedb98df4a958e8512a647258e55a7a56c1ca8b05607b38b01b6a2669af9a70efa59141f6079341c6044f615687be756d4830ea359139ea35e23f34ce226215a1a2fb8271cc60a037841e44c460e149a71d3e2fa907a48677ad18af2e7348343932f5f29ac5241cd20ce64e6798ada684164cd1109c3a969662d9aaf9897fedc5a4e256eb92bf7bd02011102820100516160cdaa0bcc7003c6dd6388ff139787de0661c9d0589471c35fefb2a060e3aa3a5ab06e75954d6e2a6c088a496b1784e91e7ee426e6eeb7169448058eb5f93d6341bed83211db9b9f07d3c30fa259c9861c3ddd0d7447ea84d1e356ea28a7635911205a33d7dc0dc822dadb9c2129466a3ca2acd7def9080011c55af249bd98e3f84a5475a43cc0369cf7fa5e4ecdd1c09ac0b0a41bd19d8af70cad8f1b6aec66a22179e5dbf9c446c645e9daa9080b455fca64365d8e02a686fbd707198302db43cd37629033574561c025d89d29c393746ce12fa01bbe60feb3fab292928ead3f8f6def6b9a7dffcd2139f6e8d1f79844d216b28dfae29dc6ba8c11063102818100f770f6dea12236dd39cb46ba96c171f3cfa92c961a12bfb62108e82e0bac280554a9ad4b99c4faee9287467573eaf6cfcba360753668c40ab1b015fbbb95f6a2d3c2402966971fa54540befdc39b58962f7d0cfaa96ff268df02efab32238544ed75fd6586bd93e38934c9d59b037f3cd7f727b38c854e1061de1f68bf43a26d02818100cc7963002015bd593af15276f185cb5a34a76bb36633c85bc86c6640419612a5a8eb2cc1a6ad43e51c2b545f88a7e8c0096a6110b85de7d1f458eca33267f9fde6b4489e346304787d33c8e1033e96b502a53ea6ad2c55299cae973719587d24468f164930f58a56aac2c7eabd68870a1056f06b8bcec5b3d2156c8a1375d89102818048c6df326ba0a6b9897805be68933fa20fe676868023a1cc27d57176f45fcf8918e69c61879449cdb2a041e64f451b6a4af3d1136a5b0c7b9dac42b3736857994d57400c2d3b81c7327c7468c10f9286867012e04ff3bfc47dd3afe70ebf273263f586c381fb85d982b52c4de24c52996cb21abc56818f6e3ae6fa2ddde6b74d028180180e47e1e5a83464d9c209b3a3f19f740631d06f756f80fbbd39ede97120b6e6501baae99b2371663f8ca083b5b966ad2e48c02015b0b1dc77198540604877c3848dae30bade78ff1dc9db65c4257b245aaa075ee732645f3f9c11ca3f37964080c58a26ba773d739b9e71df6193d3a6d4beef1bb618537e912fb26a98e0b01102818100950d7d5ec366f8bca918011359590c6e7d6fe4d3e8922d68468c3e24277f27621db17cb41d0dcddf1f77e289e49dc92101d8544e84281ec7732fbfd4e9194924a2adac4e22ef79c2ad61428f1fa03e6affa3b0de07f857de87a2e758953122b0d693cf49e54ede4eba44dcdc2c5cbd6751af5117fd107fc0e4ffb18f8774d79e +tls-cert = 308202e4308201cc020101300d06092a864886f70d01010505003039310b300906035504061302555331163014060355040a0c0d6c696273616c746963696461653112301006035504030c096c6f63616c686f7374301e170d3139303730323036353535365a170d3139303730323036353535365a3039310b300906035504061302555331163014060355040a0c0d6c696273616c746963696461653112301006035504030c096c6f63616c686f737430820120300d06092a864886f70d01010105000382010d00308201080282010100c5a358cee61ca7592dbe62cd28225426dc3fc65b33432043efb5e8fcfaf334720b2000d10c422172e6f94f82746928a6d51193342a1555684eedb141321170cb02cc7b189f5506cc30cb5c26d9b84123328ed6df61fc1a6582b046def7a662bb15d84e29ffa279f1d853c25ca79fbe3fab0200f8c85566a5eedb98df4a958e8512a647258e55a7a56c1ca8b05607b38b01b6a2669af9a70efa59141f6079341c6044f615687be756d4830ea359139ea35e23f34ce226215a1a2fb8271cc60a037841e44c460e149a71d3e2fa907a48677ad18af2e7348343932f5f29ac5241cd20ce64e6798ada684164cd1109c3a969662d9aaf9897fedc5a4e256eb92bf7bd020111300d06092a864886f70d0101050500038201010009fc34f2835e4c14de1e03202c0f0884acb51e7568b286a9b3a374e8b69f304600a2787303cd382e52923db352cf91587ea7a33da5116c886c67775b5f96357971dddb568948fbb12987523a8be0e2e537284f8ee591af17c6d58410e41d32fc634f99289089915fb4273feaaca45d3442820155f5014fbd5d19fef7954729e4439218cad6a83b9dcd21834aaec379a276f163599cdac6b9513d0c07310852bb4104a58141a158d302908c23761899a4c68c3bf81115f302d41f42ff38150c0b7dc798fd7319abec6bd9365e00bf0a0998c3b97fe4834f0688e95d1eea4df4031274c781c6661cab085d629cb924c5c65b865ae98aa2349875fafe62b7eacbc5 +idx = 0 diff --git a/hotstuff-sec-bls1.conf b/hotstuff-sec-bls1.conf new file mode 100644 index 00000000..7b506379 --- /dev/null +++ b/hotstuff-sec-bls1.conf @@ -0,0 +1,4 @@ +privkey = 6a85834d2de6a711a6cb0e6151123d76d982d274f611a6ad310a018d333bdae5 +tls-privkey = 308204a20201000282010100abfe4a55f831720dd46e2bca05e767aef9838d2069f893f3213bf5a31f5be249c2b356476e01d3fc221581bf4ffa93a6ec41898fbed6119b7981065d07fe476fa12b7da4a22f37d4cfc8a667ff163c05d17762f789df64995a1e80c50ed0d1f7ab8e733fb543d962818ce3ba7b38bf4fe0ca39926b6e99e3fa32eff48f503cf7f66824573e9fb34cb9c4e952f0f584d30c5b7312172facb0439ed5af6d0c6f7382db15315dce8f2fe1704f11bd76e5e3fbffd6f44b240036492187a13e23c0cc8769a52f5bbc90400867093d031483b84fe5c40a7ce66d7dab7a474689de080cc2b6670359f08d5bff53cfa92bf49fc306cccfe0b6fed8c6e4edef86d81638610201110282010100a1e045f68f3d98857ca3ecfa5fe8da0e180357a609626d2110386eb7a50b2f547b032406fe1fd692f2e710b40f09f460de5bccc3866f1fa1634c423970ef524af20ad09af2ff439b1dea060786ab83c93d9d8a5263a5136327a43cf5b3975c34653ac6d28c7c17e43db1c746199ed22d0fcd635ca159094f09995a4f95f12a513ebec6fe1af47c260090fcf8908e04192bb8b9a9c75608d221110d183a80380193b076354b2cb396500c94c8ca33e45559eeadefe217ef04898a2350390fadcf3e4ccb4d1783c619168c9fe7e29701f15476e980408975050d0a8e5df4e4ea35dc6fe3e3f71964952cf600c45d88688b5e92cf5144d869448290e7cefc8f793102818100d5c267d9f5b82ce47e3b7e3fa80fa599b73406b21d240c863bfc4c20d858c729d96e89adc0e51aa6248112fb351bcf5102dada449b5226842d9e7482e65391b8e89a8a0982a1f1b0e75922d416e45f28a06842d4ef00d9c7c8fa43d47487e79121e69d25f5dbbdf49ea85dc7035cb7a92fa79cad5666a2bd4bcd29be9ec31fff02818100cdfb090f4c43c27fdaef5e4b2f4efade96b3271b964036cac4806ba4d68b6cc7fc810deafd09f5ba07e1de013183f3f8499763e0cf986bbd49604d991b2f86676c9d8323f01e9c1479187c828b6fb27f45bf291d4953876084a4cc2e4122e7a26698e7bb2d89d488e0e611118536f905c2a936ed07724630ce66cf7c4cfaa79f0281810096e39499daa01fb0591aefb476a1a21226f78c417dfb542284b2179eb6d5414ab79952204bed03c0923cfe56f84fdda2989a7bf431672a3f2f42ac98a29557cdd15e0715c59f7d6dd07b27a4c4dd7058e9b301ffb7c45d7df7473ef05241d0a2ae84ab29dab93acaca58baaa98f6274a3fc19bc5a66690fe1763a4ff06a7da59028180792a41908736eae1cc145595a35ba2a10d5a533d6771112bfb1e5d7005bb6d2a584bea11c205dbd6d775cde29598e9dd58772bb16b0e5d7e6765d34b00eec78821c610e7f6a8980c0aff584cca7df08719f7fa113a31227502bb4aee0832a65f87a53d04b16022aadea57373b7c5fbe545547aa98be8ddfe9787c5582d48265d02818006385a17426489bc3393300bfec08c440cbfd894d991b1c1e1b672f17809ff150703496fde8df3bfa9d67553f0d6d4bb1bf73706454470479fc4aec0250b0613bd028cc111f61edfeb6ad40e6801fc22afcb67788a7a514c5b3f04a3986dbf063f4277bcf5182763242781f8ba6b2cb3a8cb909332f9b1966601675297a601cf +tls-cert = 308202e4308201cc020101300d06092a864886f70d01010505003039310b300906035504061302555331163014060355040a0c0d6c696273616c746963696461653112301006035504030c096c6f63616c686f7374301e170d3139303730323036353535365a170d3139303730323036353535365a3039310b300906035504061302555331163014060355040a0c0d6c696273616c746963696461653112301006035504030c096c6f63616c686f737430820120300d06092a864886f70d01010105000382010d00308201080282010100abfe4a55f831720dd46e2bca05e767aef9838d2069f893f3213bf5a31f5be249c2b356476e01d3fc221581bf4ffa93a6ec41898fbed6119b7981065d07fe476fa12b7da4a22f37d4cfc8a667ff163c05d17762f789df64995a1e80c50ed0d1f7ab8e733fb543d962818ce3ba7b38bf4fe0ca39926b6e99e3fa32eff48f503cf7f66824573e9fb34cb9c4e952f0f584d30c5b7312172facb0439ed5af6d0c6f7382db15315dce8f2fe1704f11bd76e5e3fbffd6f44b240036492187a13e23c0cc8769a52f5bbc90400867093d031483b84fe5c40a7ce66d7dab7a474689de080cc2b6670359f08d5bff53cfa92bf49fc306cccfe0b6fed8c6e4edef86d8163861020111300d06092a864886f70d0101050500038201010069f87140cc279dfc03b89cd6de3833aa7bb824f522b46943d8ea32c0bf24b2a7d7b77da04a359fe4fa840770552794836dc6cdbf80396ab87edfe5df187915cb94ef4b142b8b20c438b54608059fca91f5792a39bfaea547c6a56fac3ae165ce89d29e7af5f914304da4aabe02961f5dab7dc94124837539958015d89a22eedfd42981819004d1af6342498aa43f58cf84c391e0427835407089d0e95b5fdfe350974cb507dffeca15e55851e03b68ce4ac640ca898ea6a75a7f5469f677f74a14d05ce4bbd44e8a2a70366edb94f6e8706246dd904847e37abe3116320dc1688a4788a8600bf7ae05932541be665efb5b564c3c964504555f09175494517469 +idx = 1 diff --git a/hotstuff-sec-bls2.conf b/hotstuff-sec-bls2.conf new file mode 100644 index 00000000..94df021b --- /dev/null +++ b/hotstuff-sec-bls2.conf @@ -0,0 +1,4 @@ +privkey = 1dc6ba158efa514f46e70f68e8b60a636e04b5994b93569461b754aa34cde814 +tls-privkey = 308204a20201000282010100c1460bf8018ceec075d67405e96e056e2e3acf9c7c2d7d28ee6edfe9ee8fbeef0e978ac874ceff3ee770dafde1d019d9920b2ff334a3ac115bcf95e2bdc0b70faf46b8f13c46335c4815c72d75b488de46b96f8582446e886c6b7fdfb479bc40a0da03b7c4e414fde9ab44b1957e39c5e5c167ba88a233854f29404a1f35aa29994bcd7a62b57fc2000850c37569a8a1bfa75e6e06c54c40633e0fee1672c1f97689aabee650285a41fd6df24f20cd94733aeccdae68debba30a3588b71625f9ec7669d3f4c51317192f5acdee9b968d1a6db4a98a9c0eeef63a969c2ecaba95a9ddfd5841d996977696e41a541393ba40ae44b71c00129a25b30f6c44e89d8d0201110282010071b0bbbf0ff88c713641e9e55c2299c8576de38939fca3f9f5aaa1d4e6aee8c8db683384f96ab4431ebadb2bee3e2d52ce60ef07886047194510b285608f7abdeea2126fc91a3c5466a3661abdb57dafed5e055d97ec04c8b83f3c293cfc509e7cbc7aa855b357a46b55afeffd958b6559f94c135f6e78a8c52752fe6cb627db36195ca7e30537e3a1a2cfd2dfe23c2f6c9c91a45119e8b6c128dce763157d4f21350c7293f4cc7c96201e3b63484e22b6308c2d9351e1c5b833bcc301c68f9111c10c9e79ee6f590ce7cff86e1c8e6bf970d8d0e2d0bc32a6c06997e3cdcad17657cfa6d0300966fd1c0a4ad5e9817ab4d41b5ff0010ce93c08eae7ad053ef102818100e8b87e8ca3a329afedda121b2f005533749b067a3f9b38f43252f760ed18a9cdea42bd14a3b0ac599dc6c00fb873303713e030507fda557ab3de70864de60cba13dde108eedfe57df0a5fcbe3062b0cfce80aab3739e7f83b5534215c01830234bd439afdd02fd0755da8eb9c56466c762fb3c8cec5fa4229c8e94092db7b24102818100d49b649d2389770f18ffdd5b6368b9ea78cef9f60a17a148b558d43700e8c3250706588113e5b9f9a50014173ab2b2225cd50162e750230a693a37507fc4f1fc6d9d268a69cfd6b4f8ff494fcfd526d28a46cc92fbcde915256d076a9ea17e74ae747c4002eb56610c0caa47bca2373bdd7da66d7e050bb7d64885a60aa8004d02818100b1f67ee404a9f2b3b5e2fec97e4b8c72a4768c7b9a0d49abae0335a47912dc340d7e545b13c3569ee21074c0ba39f7b1a5c98e5bad105f7bf2f5651b68befaac698b8df7c5ba46150351c14625002cdb2571737a2b3cf8196c8af64cde309d482aed95867bd51bd86ed44f0687e35da787ed4c6bc3d0aab10e4ee9acaa7d6a31028181008991b992dac25c18d3f0da866d7fffd3f3d13853e869a4987557985fd3696f36139ab1bceec1d2b097f0fdf0e9beebbbe1b700e5a4bb61f7ad8005ac8ee8d8d08329734a80b3a90bb02cb6f7685cbec477973913d01bd30daece13db93d1e8699e0f23387a5c0ab7440831f22ec350ea80423e83154e8f1c99b674989d7bc3f5028180267c5167cd1f8dce4b15611b8ea0220e6be74efbf55e3bf4a775b1edf0e49b377c12f49fbf683f24e1850c455b8b7a96d0c7eff9f47661ec75004a2a435dd741e7d7bb6423fa576053a0677b2a0b714e7fadcc37c03dc9da053069477c1ce0afac316c1c63ffb510d30e11adc0865e94177f3545c0594860c10baa51bc074e4c +tls-cert = 308202e4308201cc020101300d06092a864886f70d01010505003039310b300906035504061302555331163014060355040a0c0d6c696273616c746963696461653112301006035504030c096c6f63616c686f7374301e170d3139303730323036353535365a170d3139303730323036353535365a3039310b300906035504061302555331163014060355040a0c0d6c696273616c746963696461653112301006035504030c096c6f63616c686f737430820120300d06092a864886f70d01010105000382010d00308201080282010100c1460bf8018ceec075d67405e96e056e2e3acf9c7c2d7d28ee6edfe9ee8fbeef0e978ac874ceff3ee770dafde1d019d9920b2ff334a3ac115bcf95e2bdc0b70faf46b8f13c46335c4815c72d75b488de46b96f8582446e886c6b7fdfb479bc40a0da03b7c4e414fde9ab44b1957e39c5e5c167ba88a233854f29404a1f35aa29994bcd7a62b57fc2000850c37569a8a1bfa75e6e06c54c40633e0fee1672c1f97689aabee650285a41fd6df24f20cd94733aeccdae68debba30a3588b71625f9ec7669d3f4c51317192f5acdee9b968d1a6db4a98a9c0eeef63a969c2ecaba95a9ddfd5841d996977696e41a541393ba40ae44b71c00129a25b30f6c44e89d8d020111300d06092a864886f70d01010505000382010100706c7eb29939c38cfcbab592c62a3572e05dcaa4d54e24cce74a244972e74ac8ed6e0b3eb1add0d4de6007d392ac75a7fb9836a9a1d937d0b2c3f01a6b1994ac317328527c763eae26a6ca647752badcd09e73364ac7828d375b4966e510de1cdbd01a5be047e45533f5a3d81df00ffe9d13fe5d54e18584691abb3a9a3d423d348d7714382317547338a8e83d14f404348db41c10a05e57221eda1e220b265ae4237e59ab2db1facbe8cc8d2198ca5fe2ad074bb8c7c4dd675cbe3d60b9e29f6b12ab4c587c6576e1ce2d2512be035e4692100c6c3e47d4d84dbbc865804af1bd0240fb804ef99c7038191dae2fab73a1a1ffa09f536a0fbf49fa1a3234b62a +idx = 2 diff --git a/hotstuff-sec-bls3.conf b/hotstuff-sec-bls3.conf new file mode 100644 index 00000000..feed5f33 --- /dev/null +++ b/hotstuff-sec-bls3.conf @@ -0,0 +1,4 @@ +privkey = 30a444081a5c13cbb9606908caeb7fe6611a4042bb2efb6de71e9f918d36592a +tls-privkey = 308204a20201000282010100de01b461213afa37d4aa68bdc7e1a6de12307440f1de6588e5362450694cbb4ba63b1f992a7dc88b999c7dec9088d17253ac278c33018ea8caa1f96c7d90bcb5a6a3f8568825bafa9a696699a4eaf0c6fcdd8ed7bc91a688ead564fb882a1c25c7f72bbe44eb44fda1d11d6ca090503e36de532f2fededff03da30f8f95f11b6472e9588fd6be69cad285915c68edaa7754c6524017bf08c3c336f04d0246d8e967a4de2824a3ac7486aaf9160540c63f75d36ecba9261ff6b859a7684b023ecfbc5408dc7c59942c76464040770c6097833dd770a7dffc6ed6a8716b1f683379843969f937d859d8f69a21362eda9dabd64dd6fb7131ee46b2654d3aa8dc9df02011102820100414bcba418d51c6ac61400b049d8f4d7e73b6d7c835f8746618865089770ebcaf4a7fa3c1b8e68290f0fe8cd1b7388e563e756ecfff16631a5027689521b82cc03d5dfa0faddebb31e5b3c4b4e9f73fe4a5f48215594400a26f3780dbea2f93849df4919d808f62c7ae326c598a2ea6ca6b9dc3b0e18cd873d5e4aa394a37dad88a49b91b7446343d03d4ea067b72c62ba622d68f7fb97c031a7f9259401318905e092b0aec27e643fb3efd9bf392050941d43fe06a87630412bf765a4800f57561a9fc339ff92a9b33e748efe5c6ddafe4069e99cf039794b4641ab4f199703860b4f8ee3669a04ad664379012650e68debe0ccc4c41a39e6bf8a3de15003f902818100f56482abd14db0f327311b376dc4cfac86cc3379036b6672713d296a0665797de7b115350d77a27193de1f5abd9e2b44eff6c5a323b1209c4aac68c86e3488abab89139a7cbb98a4f0c1e930c2bc276bbcf0efd47cf4dc6614b9c16c332a5f7ef339d5c746780884a66e087236ec784361fda7e72c21528c0427d7abbc9751f502818100e79a68542368e4295b8d3289c4f4da780e6597461952b9592221901b05bae53ece00df87ef7084340f28c71f188d400d0fcfbd504d0ae2bf101082214d9500b1f8480dc1ec3ea7900ece21b9e3e0c2b5279b1f21de585ff7a58eb330d841ef13107ce58c14a8a4a29b6cb438f4e551baac120603878a3ff9f00cda5589800403028181009ec890c9876e818e46892fba74340de81afc99c6c5fa333afdfa66176d8cf44268bde08bbd6b873a6ebce71c98cfc1a513bdcb2d53547e833f60800938401c32d867c163f65b44a6f6231e6ad85ba1097a418c20149e707e49a55f09c6c1109d70347b44b5207dfb7abfab1cba208a0d7ba4215958ca4478b7651314c552daad02818100cc5b10c2b5d5058de75e77e2f914484bd077c1b652944930878706ae6e77bb376a793db42d9f83b576c9a0a2f78bb0fc775cf255e9a0317b68870968adddd36fdb12667dee91a2e88588b458ba028daee6b60c692d99459e46c934b2a0b2a5c58704ca8aa8d109bca741cc32417f0be0f22e054e68890b45f1ed391e4c25a92f02818016d4c0a1d4cc7fadb7033ae8506221a7dde9c2437fe5989175e8de47791b4ff957fb485d6d04c85b9fd1d7734950dc4d032dd3fdf9c14193b04ea179839fb4560282d106b684b5712a9b140afbe4d92ff30c745a7bdca71de9808f6d2a88340e116cc4475e908993c27a27847601ec378d4357dc5e99a147c60d7258e282453e +tls-cert = 308202e4308201cc020101300d06092a864886f70d01010505003039310b300906035504061302555331163014060355040a0c0d6c696273616c746963696461653112301006035504030c096c6f63616c686f7374301e170d3139303730323036353535365a170d3139303730323036353535365a3039310b300906035504061302555331163014060355040a0c0d6c696273616c746963696461653112301006035504030c096c6f63616c686f737430820120300d06092a864886f70d01010105000382010d00308201080282010100de01b461213afa37d4aa68bdc7e1a6de12307440f1de6588e5362450694cbb4ba63b1f992a7dc88b999c7dec9088d17253ac278c33018ea8caa1f96c7d90bcb5a6a3f8568825bafa9a696699a4eaf0c6fcdd8ed7bc91a688ead564fb882a1c25c7f72bbe44eb44fda1d11d6ca090503e36de532f2fededff03da30f8f95f11b6472e9588fd6be69cad285915c68edaa7754c6524017bf08c3c336f04d0246d8e967a4de2824a3ac7486aaf9160540c63f75d36ecba9261ff6b859a7684b023ecfbc5408dc7c59942c76464040770c6097833dd770a7dffc6ed6a8716b1f683379843969f937d859d8f69a21362eda9dabd64dd6fb7131ee46b2654d3aa8dc9df020111300d06092a864886f70d010105050003820101007f9d4f2848059831e5ea7d727d9b09f826027c78fdc86d27ea83d32d727ac4a0484e55ed34851adcc8903a3ef39c1b0c447c28cd84cbc513cdcd607da3fa903495a70b7772e71873e3c8a734d3e8b9f82c7380604ccb8416bd92822e703a3b8839aff411f967d2bcc1cd96d158e7839a2bff6110ffd005808f7047fd57a7150c1e14ddcfd2e1a24a5878f99409b7ede1d5f4a385077b6f55f4818c854c6e64adb4789433667e672b9a615b680301a05852255cef958ff1031a489dd95327d045be0315359644ec51f2fd3cb724382ba2425da519dbf1d89098e10a1091f44c7a8e12733b7d0b1fce7c6d19adfee3cdac89f95ed1ae979093cb2793892724d7d9 +idx = 3 diff --git a/hotstuff.conf b/hotstuff.conf index cadf3aef..5cdd0905 100644 --- a/hotstuff.conf +++ b/hotstuff.conf @@ -3,4 +3,4 @@ pace-maker = rr replica = 127.0.0.1:10000;20000, 039f89215177475ac408d079b45acef4591fc477dd690f2467df052cf0c7baba23, 542865a568784c4e77c172b82e99cb8a1a53b7bee5f86843b04960ea4157f420 replica = 127.0.0.1:10001;20001, 0278740a5bec75e333b3c93965b1609163b15d2e3c2fdef141d4859ec70c238e7a, c261250345ebcd676a0edeea173526608604f626b2e8bc4fd2142d3bde1d44d5 replica = 127.0.0.1:10002;20002, 0269eb606576a315a630c2483deed35cc4bd845abae1c693f97c440c89503fa92e, 065b010aed5629edfb5289e8b22fc6cc6b33c4013bfdd128caba80c3c02d6d78 -replica = 127.0.0.1:10003;20003, 03e6911bf17e632eecdfa0dc9fc6efc9ddca60c0e3100db469a3d3d62008044a53, 6540a0fea67efcb08f53ec3a952df4c3f0e2e07c2778fd92320807717e29a651 +replica = 127.0.0.1:10003;20003, 03e6911bf17e632eecdfa0dc9fc6efc9ddca60c0e3100db469a3d3d62008044a53, 6540a0fea67efcb08f53ec3a952df4c3f0e2e07c2778fd92320807717e29a651 \ No newline at end of file diff --git a/include/hotstuff/consensus.h b/include/hotstuff/consensus.h index e2f7cfca..11726ea6 100644 --- a/include/hotstuff/consensus.h +++ b/include/hotstuff/consensus.h @@ -82,6 +82,9 @@ class HotStuffCore { * functions. */ void on_init(uint32_t nfaulty); + /** Call to initialize the master public key.. */ + void set_master_pub(const pubkey_bt &masterPub); + /* TODO: better name for "delivery" ? */ /** Call to inform the state machine that a block is ready to be handled. * A block is only delivered if itself is fetched, the block for the diff --git a/include/hotstuff/crypto.h b/include/hotstuff/crypto.h index 60e7dfc7..d5e39140 100644 --- a/include/hotstuff/crypto.h +++ b/include/hotstuff/crypto.h @@ -23,6 +23,7 @@ #include "salticidae/crypto.h" #include "hotstuff/type.h" #include "hotstuff/task.h" +#include namespace hotstuff { @@ -141,7 +142,6 @@ class QuorumCertDummy: public QuorumCert { const uint256_t &get_obj_hash() const override { return obj_hash; } }; - class Secp256k1Context { secp256k1_context *ctx; friend class PubKeySecp256k1; @@ -180,7 +180,7 @@ class PubKeySecp256k1: public PubKey { PubKeySecp256k1(const secp256k1_context_t &ctx = secp256k1_default_sign_ctx): PubKey(), ctx(ctx) {} - + PubKeySecp256k1(const bytearray_t &raw_bytes, const secp256k1_context_t &ctx = secp256k1_default_sign_ctx): @@ -425,6 +425,314 @@ class QuorumCertSecp256k1: public QuorumCert { } }; + class PrivKeyBLS; + class PubKeyBLS: public PubKey { + static const auto _olen = bls::PublicKey::PUBLIC_KEY_SIZE; + friend class SigSecBLS; + + bls::PublicKey* data = nullptr; + + public: + PubKeyBLS() : + PubKey() {} + + PubKeyBLS(const bytearray_t &raw_bytes) : + PubKeyBLS() { + data = new bls::PublicKey(bls::PublicKey::FromBytes(&raw_bytes[0])); + } + + PubKeyBLS(const PubKeyBLS &obj) { + data = new bls::PublicKey(*(obj.data)); + } + + ~PubKeyBLS() override { + delete data; + data = nullptr; + } + + inline PubKeyBLS(const PrivKeyBLS &priv_key); + + void serialize(DataStream &s) const override { + static uint8_t output[_olen]; + data->Serialize(output); + s.put_data(output, output + _olen); + } + + void unserialize(DataStream &s) override { + static const auto _exc = std::invalid_argument("ill-formed public key"); + + try { + data = new bls::PublicKey(bls::PublicKey::FromBytes(s.get_data_inplace(_olen))); + } catch (std::ios_base::failure &) { + throw _exc; + } + } + + PubKeyBLS *clone() override { + return new PubKeyBLS(*this); + } + }; + + class PrivKeyBLS: public PrivKey { + static const auto nbytes = bls::PrivateKey::PRIVATE_KEY_SIZE;; + friend class SigSecBLS; + + public: + bls::PrivateKey* data = nullptr; + + PrivKeyBLS(): + PrivKey() {} + + PrivKeyBLS(const bytearray_t &raw_bytes): + PrivKeyBLS() + { + static const auto _exc = std::invalid_argument("ill-formed public key"); + try { + data = new bls::PrivateKey(bls::PrivateKey::FromBytes(&raw_bytes[0])); + } catch (std::ios_base::failure &) { + throw _exc; + } + } + + ~PrivKeyBLS() + { + delete data; + data = nullptr; + } + + void serialize(DataStream &s) const override { + static uint8_t output[nbytes]; + data->Serialize(output); + s.put_data(output, output + nbytes); + } + + void unserialize(DataStream &s) override { + static const auto _exc = std::invalid_argument("ill-formed public key"); + try { + const uint8_t* dat = s.get_data_inplace(bls::PrivateKey::PRIVATE_KEY_SIZE); + data = new bls::PrivateKey(bls::PrivateKey(bls::PrivateKey::FromBytes(dat))); + } catch (std::ios_base::failure &) { + throw _exc; + } + } + + void from_rand() override { + bn_t b; + bn_new(b); + data = new bls::PrivateKey(bls::PrivateKey::FromBN(b)); + } + + inline pubkey_bt get_pubkey() const override; + }; + + pubkey_bt PrivKeyBLS::get_pubkey() const { + return new PubKeyBLS(*this); + } + + PubKeyBLS::PubKeyBLS(const PrivKeyBLS &priv_key): PubKey() { + data = new bls::PublicKey(priv_key.data->GetPublicKey()); + } + + class SigSecBLS: public Serializable { + + static void check_msg_length(const bytearray_t &msg) { + if (msg.size() != 32) + throw std::invalid_argument("the message should be 32-bytes"); + } + + public: + bls::InsecureSignature* data = nullptr; + + SigSecBLS (): + Serializable(){} + SigSecBLS(const uint256_t &digest, + const PrivKeyBLS &priv_key): + Serializable() { + sign(digest, priv_key); + } + + SigSecBLS (const SigSecBLS &obj) + { + data = new bls::InsecureSignature(*(obj.data)); + } + + SigSecBLS (bls::InsecureSignature sig): + Serializable() + { + data = new bls::InsecureSignature(sig); + } + + ~SigSecBLS() override + { + delete data; + data = nullptr; + } + + void serialize(DataStream &s) const override { + static uint8_t output[bls::InsecureSignature::SIGNATURE_SIZE]; + + int i = 0; + for (auto in : data->Serialize()) + { + output[i++] = in; + } + s.put_data(output, output + bls::InsecureSignature::SIGNATURE_SIZE); + } + + void unserialize(DataStream &s) override { + static const auto _exc = std::invalid_argument("ill-formed signature"); + try { + data = new bls::InsecureSignature(bls::InsecureSignature::FromBytes(s.get_data_inplace(bls::InsecureSignature::SIGNATURE_SIZE))); + } catch (std::ios_base::failure &) { + throw _exc; + } + } + + void sign(const bytearray_t &msg, const PrivKeyBLS &priv_key) { + check_msg_length(msg); + uint8_t* arr = (unsigned char *)&*msg.begin(); + data = new bls::InsecureSignature(priv_key.data->SignInsecure(arr, sizeof(arr))); + } + + bool verify(const bytearray_t &msg, const PubKeyBLS &pub_key) const { + check_msg_length(msg); + uint8_t* arr = (unsigned char *)&*msg.begin(); + + uint8_t hash[bls::BLS::MESSAGE_HASH_LEN]; + bls::Util::Hash256(hash, arr, sizeof(arr)); + + return data->Verify({hash}, {*(pub_key.data)}); + } + }; + + class SigVeriTaskBLS: public VeriTask { + uint256_t msg; + PubKeyBLS pubkey; + SigSecBLS sig; + public: + SigVeriTaskBLS(const uint256_t &msg, + const PubKeyBLS &pubkey, + const SigSecBLS &sig): + msg(msg), pubkey(pubkey), sig(sig) {} + virtual ~SigVeriTaskBLS() = default; + + bool verify() override { + return sig.verify(msg, pubkey); + } + }; + + class PartCertBLS: public SigSecBLS, public PartCert { + uint256_t obj_hash; + + public: + PartCertBLS() = default; + PartCertBLS(const PrivKeyBLS &priv_key, const uint256_t &obj_hash): + SigSecBLS(obj_hash, priv_key), + PartCert(), + obj_hash(obj_hash) { } + + bool verify(const PubKey &pub_key) override { + return SigSecBLS::verify(obj_hash, + static_cast(pub_key)); + } + + promise_t verify(const PubKey &pub_key, VeriPool &vpool) override { + return vpool.verify(new SigVeriTaskBLS(obj_hash, + static_cast(pub_key), + static_cast(*this))); + } + + const uint256_t &get_obj_hash() const override { return obj_hash; } + + PartCertBLS *clone() override { + return new PartCertBLS(*this); + } + + void serialize(DataStream &s) const override { + s << obj_hash; + this->SigSecBLS::serialize(s); + } + + void unserialize(DataStream &s) override { + s >> obj_hash; + this->SigSecBLS::unserialize(s); + } + }; + + class QuorumCertBLS: public QuorumCert { + uint256_t obj_hash; + salticidae::Bits rids; + std::unordered_map signatures; + SigSecBLS* theSig = nullptr; + size_t t; + + public: + QuorumCertBLS() = default; + QuorumCertBLS(const ReplicaConfig &config, const uint256_t &obj_hash); + ~QuorumCertBLS() + { + delete theSig; + theSig = nullptr; + } + + void add_part(ReplicaID rid, const PartCert &pc) override { + if (pc.get_obj_hash() != obj_hash) + throw std::invalid_argument("PartCert does match the block hash"); + signatures.insert(std::make_pair( + rid, static_cast(pc))); + rids.set(rid); + } + + void compute() override + { + std::vector sigShareOut; + std::vector players; + players.reserve(signatures.size()); + + for(auto elem : signatures) { + players.push_back(elem.first + 1); + sigShareOut.push_back(*elem.second.data); + } + + uint8_t* arr = (unsigned char *)&*obj_hash.to_bytes().begin(); + theSig = new SigSecBLS(bls::Threshold::AggregateUnitSigs(sigShareOut, arr, sizeof(arr), &players[0], t)); + } + + bool verify(const ReplicaConfig &config) override; + promise_t verify(const ReplicaConfig &config, VeriPool &vpool) override; + + const uint256_t &get_obj_hash() const override { return obj_hash; } + + QuorumCertBLS *clone() override { + return new QuorumCertBLS(*this); + } + + void serialize(DataStream &s) const override { + bool combined = (theSig != nullptr); + s << obj_hash << rids << combined; + if (combined) { + s << *theSig; + } + else { + for (size_t i = 0; i < rids.size(); i++) + if (rids.get(i)) s << signatures.at(i); + } + } + + void unserialize(DataStream &s) override { + bool combined; + s >> obj_hash >> rids >> combined; + if (combined) { + theSig = new SigSecBLS(); + theSig->unserialize(s); + } + else { + for (size_t i = 0; i < rids.size(); i++) + if (rids.get(i)) s >> signatures[i]; + } + } + }; + } #endif diff --git a/include/hotstuff/entity.h b/include/hotstuff/entity.h index dea980d2..59217df5 100644 --- a/include/hotstuff/entity.h +++ b/include/hotstuff/entity.h @@ -63,6 +63,8 @@ class ReplicaConfig { size_t nreplicas; size_t nmajority; + PubKey* globalPub; + ReplicaConfig(): nreplicas(0), nmajority(0) {} void add_replica(ReplicaID rid, const ReplicaInfo &info) { diff --git a/include/hotstuff/hotstuff.h b/include/hotstuff/hotstuff.h index 33b673f8..825ffb54 100644 --- a/include/hotstuff/hotstuff.h +++ b/include/hotstuff/hotstuff.h @@ -304,11 +304,17 @@ class HotStuff: public HotStuffBase { )); HotStuffBase::start(std::move(reps), ec_loop); } + + void set_master_pub(const bytearray_t &data) { + HotStuffBase::set_master_pub(new PubKeyType(data)); + } }; using HotStuffNoSig = HotStuff<>; using HotStuffSecp256k1 = HotStuff; +using HotStuffTH = HotStuff; template FetchContext::FetchContext(FetchContext && other): diff --git a/src/consensus.cpp b/src/consensus.cpp index 9de7cc21..9be204fe 100644 --- a/src/consensus.cpp +++ b/src/consensus.cpp @@ -248,9 +248,10 @@ void HotStuffCore::on_receive_vote(const Vote &vote) { } /*** end HotStuff protocol logic ***/ void HotStuffCore::on_init(uint32_t nfaulty) { + config.nmajority = config.nreplicas - nfaulty; b0->qc = create_quorum_cert(b0->get_hash()); - b0->qc->compute(); + //b0->qc->compute(); b0->self_qc = b0->qc->clone(); b0->qc_ref = b0; hqc = std::make_pair(b0, b0->qc->clone()); @@ -354,4 +355,8 @@ HotStuffCore::operator std::string () const { return s; } +void HotStuffCore::set_master_pub(const pubkey_bt &masterPub) { + config.globalPub = masterPub->clone(); +} + } diff --git a/src/crypto.cpp b/src/crypto.cpp index 7e839ef5..0b484068 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -19,48 +19,78 @@ namespace hotstuff { -secp256k1_context_t secp256k1_default_sign_ctx = new Secp256k1Context(true); -secp256k1_context_t secp256k1_default_verify_ctx = new Secp256k1Context(false); + secp256k1_context_t secp256k1_default_sign_ctx = new Secp256k1Context(true); + secp256k1_context_t secp256k1_default_verify_ctx = new Secp256k1Context(false); -QuorumCertSecp256k1::QuorumCertSecp256k1( - const ReplicaConfig &config, const uint256_t &obj_hash): + QuorumCertSecp256k1::QuorumCertSecp256k1( + const ReplicaConfig &config, const uint256_t &obj_hash) : QuorumCert(), obj_hash(obj_hash), rids(config.nreplicas) { - rids.clear(); -} - -bool QuorumCertSecp256k1::verify(const ReplicaConfig &config) { - if (sigs.size() < config.nmajority) return false; - for (size_t i = 0; i < rids.size(); i++) - if (rids.get(i)) - { - HOTSTUFF_LOG_DEBUG("checking cert(%d), obj_hash=%s", - i, get_hex10(obj_hash).c_str()); - if (!sigs[i].verify(obj_hash, - static_cast(config.get_pubkey(i)), - secp256k1_default_verify_ctx)) - return false; - } - return true; -} + rids.clear(); + } -promise_t QuorumCertSecp256k1::verify(const ReplicaConfig &config, VeriPool &vpool) { - if (sigs.size() < config.nmajority) - return promise_t([](promise_t &pm) { pm.resolve(false); }); - std::vector vpm; - for (size_t i = 0; i < rids.size(); i++) - if (rids.get(i)) - { - HOTSTUFF_LOG_DEBUG("checking cert(%d), obj_hash=%s", - i, get_hex10(obj_hash).c_str()); - vpm.push_back(vpool.verify(new Secp256k1VeriTask(obj_hash, - static_cast(config.get_pubkey(i)), - sigs[i]))); - } - return promise::all(vpm).then([](const promise::values_t &values) { - for (const auto &v: values) - if (!promise::any_cast(v)) return false; + bool QuorumCertSecp256k1::verify(const ReplicaConfig &config) { + if (sigs.size() < config.nmajority) return false; + for (size_t i = 0; i < rids.size(); i++) + if (rids.get(i)) { + HOTSTUFF_LOG_DEBUG("checking cert(%d), obj_hash=%s", + i, get_hex10(obj_hash).c_str()); + if (!sigs[i].verify(obj_hash, + static_cast(config.get_pubkey(i)), + secp256k1_default_verify_ctx)) + return false; + } return true; - }); -} + } + + promise_t QuorumCertSecp256k1::verify(const ReplicaConfig &config, VeriPool &vpool) { + if (sigs.size() < config.nmajority) + return promise_t([](promise_t &pm) { pm.resolve(false); }); + std::vector vpm; + for (size_t i = 0; i < rids.size(); i++) + if (rids.get(i)) { + HOTSTUFF_LOG_DEBUG("checking cert(%d), obj_hash=%s", + i, get_hex10(obj_hash).c_str()); + vpm.push_back(vpool.verify(new Secp256k1VeriTask(obj_hash, + static_cast(config.get_pubkey( + i)), + sigs[i]))); + } + return promise::all(vpm).then([](const promise::values_t &values) { + for (const auto &v: values) + if (!promise::any_cast(v)) return false; + return true; + }); + } + + QuorumCertBLS::QuorumCertBLS( + const ReplicaConfig &config, const uint256_t &obj_hash) : + QuorumCert(), obj_hash(obj_hash), rids(config.nreplicas), t(config.nmajority){ + rids.clear(); + } + + bool QuorumCertBLS::verify(const ReplicaConfig &config) { + if (theSig == nullptr) return false; + HOTSTUFF_LOG_DEBUG("checking cert(%d), obj_hash=%s", + i, get_hex10(obj_hash).c_str()); + return theSig->verify(obj_hash, static_cast(*config.globalPub)); + } + + promise_t QuorumCertBLS::verify(const ReplicaConfig &config, VeriPool &vpool) { + if (theSig == nullptr) + return promise_t([](promise_t &pm) { pm.resolve(false); }); + + std::vector vpm; + + HOTSTUFF_LOG_DEBUG("checking cert(%d), obj_hash=%s", + i, get_hex10(obj_hash).c_str()); + vpm.push_back(vpool.verify(new SigVeriTaskBLS(obj_hash, + static_cast(*config.globalPub), + *theSig))); + return promise::all(vpm).then([](const promise::values_t &values) { + for (const auto &v: values) + if (!promise::any_cast(v)) return false; + return true; + }); + } } diff --git a/src/hotstuff_keygen_bls.cpp b/src/hotstuff_keygen_bls.cpp new file mode 100644 index 00000000..c60444d3 --- /dev/null +++ b/src/hotstuff_keygen_bls.cpp @@ -0,0 +1,94 @@ + +#include "salticidae/util.h" + +#include +#include +#include +#include +#include +#include +#include + +using namespace bls; +using namespace std; + +int main(int argc, char **argv) { + + if (argc != 3) { + throw std::invalid_argument( "Expecting N, K as parameters" ); + } + + char *endptr; + int N = atoi(argv[1]); + int K = atoi(argv[2]); + + std::vector> commits; + std::vector> frags; + for (size_t i = 0; i < N; ++i) { + commits.emplace_back(std::vector()); + frags.emplace_back(std::vector()); + for (size_t j = 0; j < N; ++j) { + if (j < K) { + g1_t g; + commits[i].emplace_back(PublicKey::FromG1(&g)); + } + bn_t b; + bn_new(b); + frags[i].emplace_back(PrivateKey::FromBN(b)); + } + } + + frags[0][0].GetPublicKey(); + + for (int i = 0; i < N; i++) { + Threshold::Create(commits[i], frags[i], K, N); + } + + std::vector keys; + keys.reserve(N); + + std::ofstream myfile; + + myfile.open (((string) "keys").append(std::to_string(N)).append(".cfg")); + + for (int i = 0; i < N; i++) { + keys.push_back(commits[i][0]); + } + + PublicKey masterPubkey = PublicKey::AggregateInsecure(keys); + + uint8_t pkBytes[bls::PublicKey::PUBLIC_KEY_SIZE]; + masterPubkey.Serialize(pkBytes); + string hexkey = bls::Util::HexStr(pkBytes, bls::PublicKey::PUBLIC_KEY_SIZE); + myfile << "master: " << hexkey << "\n\n"; + + std::vector> recvdFrags = {{}}; + for (int i = 0; i < N; ++i) { + recvdFrags.emplace_back(std::vector()); + for (int j = 0; j < N; ++j) { + recvdFrags[i].emplace_back(frags[j][i]); + } + } + + vector privs; + privs.reserve(N); + + for (int x = 0; x < N; x++) { + PrivateKey priv = PrivateKey::AggregateInsecure(recvdFrags[x]); + privs.push_back(priv); + + uint8_t pkBytes[bls::PrivateKey::PRIVATE_KEY_SIZE]; + priv.Serialize(pkBytes); + string hexkey = bls::Util::HexStr(pkBytes, bls::PrivateKey::PRIVATE_KEY_SIZE); + myfile << "priv" << x << ": " << hexkey << "\n"; + } + + for (int x = 0; x < N; x++) { + uint8_t pkBytes[bls::PublicKey::PUBLIC_KEY_SIZE]; + privs[x].GetPublicKey().Serialize(pkBytes); + string hexkey = bls::Util::HexStr(pkBytes, bls::PublicKey::PUBLIC_KEY_SIZE); + myfile << "pub" << x << ": " << hexkey << "\n"; + } + + return 0; +}