├── compat ├── compat.c ├── CMakeLists.txt ├── compat.h └── aligned_alloc.c ├── timing ├── .gitignore ├── nonce-lowmc-128-128-d=1.txt ├── nonce-lowmc-192-192-d=1.txt ├── nonce-lowmc-256-256-d=1.txt ├── nonce-lowmc-384-384-d=1.txt ├── nonce-lowmc-512-512-d=1.txt ├── nonce-lowmc-128.txt ├── lowmc-inst-128-128-128.txt ├── style.json ├── pq-lowmc-inst-256-256-256.txt ├── pq-lowmc-inst-384.txt ├── pq-lowmc-inst-512.txt ├── nonce-lowmc-192.txt ├── lowmc-inst-192-192-192.txt ├── lowmc-inst-256-256-d=1.3.txt ├── nonce-lowmc-256.txt ├── lowmc-inst-256-256-256.txt ├── lowmc-inst-128-128-d=1.txt ├── lowmc-inst-256-256-d=1.txt ├── lowmc-inst-512-512-512.txt ├── pq-lowmc-inst-512-512-512.txt ├── Makefile ├── nonce-lowmc-320.txt ├── nonce-lowmc-384.txt ├── pq-lowmc-inst-384-384-384.txt ├── nonce-lowmc-448.txt ├── timing.py ├── nonce-lowmc-512.txt └── graphs.py ├── .gitignore ├── timing.c ├── mpc_test.h ├── multithreading.h ├── io.h ├── config.h.in ├── lowmc.h ├── .clang-format ├── signature_common.h ├── randomness.h ├── parameters.h ├── README.md.anon ├── COPYING ├── README.md ├── signature_fis.h ├── hashing_util.h ├── cmake └── Findm4ri.cmake ├── signature_common.c ├── mzd_shared.h ├── multithreading.c ├── io.c ├── timing.h ├── randomness.c ├── lowmc_pars.h ├── mzd_shared.c ├── mpc_lowmc.h ├── simd.h ├── hashing_util.c ├── mzd_additional.h ├── main.c ├── CMakeLists.txt ├── mpc_test.c ├── lowmc.c ├── mpc.h ├── lowmc_pars.c ├── signature_fis.c ├── mpc.c └── mpc_lowmc.c /compat/compat.c: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /timing/.gitignore: -------------------------------------------------------------------------------- 1 | timings* 2 | *.png 3 | *.eps 4 | *.mat 5 | *.pdf 6 | -------------------------------------------------------------------------------- /timing/nonce-lowmc-128-128-d=1.txt: -------------------------------------------------------------------------------- 1 | m: 1 blocksize: 128 ANDdepth: 156 2 | -------------------------------------------------------------------------------- /timing/nonce-lowmc-192-192-d=1.txt: -------------------------------------------------------------------------------- 1 | m: 1 blocksize: 192 ANDdepth: 201 2 | -------------------------------------------------------------------------------- /timing/nonce-lowmc-256-256-d=1.txt: -------------------------------------------------------------------------------- 1 | m: 1 blocksize: 256 ANDdepth: 243 2 | -------------------------------------------------------------------------------- /timing/nonce-lowmc-384-384-d=1.txt: -------------------------------------------------------------------------------- 1 | m: 1 blocksize: 384 ANDdepth: 330 2 | -------------------------------------------------------------------------------- /timing/nonce-lowmc-512-512-d=1.txt: -------------------------------------------------------------------------------- 1 | m: 1 blocksize: 512 ANDdepth: 414 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | mpc_lowmc 2 | mpc_lowmc_pq 3 | mpc_lowmc_openmp 4 | mpc_lowmc_pq_openmp 5 | -------------------------------------------------------------------------------- /timing.c: -------------------------------------------------------------------------------- 1 | #include "timing.h" 2 | 3 | static timing_and_size_t storage; 4 | timing_and_size_t* timing_and_size = &storage; 5 | -------------------------------------------------------------------------------- /mpc_test.h: -------------------------------------------------------------------------------- 1 | #ifndef MPC_TEST_H 2 | #define MPC_TEST_H 3 | 4 | /** 5 | * Run tests 6 | */ 7 | void run_tests(void); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /multithreading.h: -------------------------------------------------------------------------------- 1 | #ifndef MULTITHREADING_H 2 | #define MULTITHREADING_H 3 | 4 | void openmp_thread_setup(void); 5 | 6 | void openmp_thread_cleanup(void); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /io.h: -------------------------------------------------------------------------------- 1 | #ifndef IO_H 2 | #define IO_H 3 | 4 | unsigned char* mzd_to_char_array(mzd_t* data, unsigned numbytes); 5 | 6 | mzd_t* mzd_from_char_array(unsigned char* data, unsigned len, unsigned vec_len); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /compat/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(COMPAT_SOURCES compat.c) 2 | if(NOT HAVE_ALIGNED_ALLOC) 3 | set(COMPAT_SOURCES ${COMPAT_SOURCES} aligned_alloc.c) 4 | endif() 5 | 6 | add_library(compat STATIC ${COMPAT_SOURCES}) 7 | target_compile_definitions(compat PRIVATE HAVE_CONFIG_H) 8 | -------------------------------------------------------------------------------- /config.h.in: -------------------------------------------------------------------------------- 1 | #ifndef FISH_CONFIG_H 2 | #define FISH_CONFIG_H 3 | 4 | #cmakedefine HAVE_IMMINTRIN_H 5 | 6 | #cmakedefine HAVE_ALIGNED_ALLOC 7 | #cmakedefine HAVE_POSIX_MEMALIGN 8 | #cmakedefine HAVE_MEMALIGN 9 | 10 | #cmakedefine M4RI_VERSION @M4RI_VERSION_STRING@ 11 | 12 | #include 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /lowmc.h: -------------------------------------------------------------------------------- 1 | #ifndef LOWMC_H 2 | #define LOWMC_H 3 | 4 | #include "lowmc_pars.h" 5 | #include 6 | 7 | /** 8 | * Implements LowMC encryption 9 | * 10 | * \param lowmc the lowmc parameters 11 | * \param p the plaintext 12 | * \return the ciphertext 13 | */ 14 | mzd_t* lowmc_call(lowmc_t const* lowmc, lowmc_key_t const* lowmc_key, mzd_t const* p); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | BasedOnStyle: LLVM 4 | AlignConsecutiveAssignments: true 5 | AllowShortFunctionsOnASingleLine: Empty 6 | AllowShortIfStatementsOnASingleLine: false 7 | AlwaysBreakTemplateDeclarations: true 8 | BreakBeforeBraces: Attach 9 | ConstructorInitializerIndentWidth: 2 10 | NamespaceIndentation: All 11 | PointerAlignment: Left 12 | TabWidth: 2 13 | ColumnLimit: 100 14 | ... 15 | -------------------------------------------------------------------------------- /signature_common.h: -------------------------------------------------------------------------------- 1 | #ifndef SIGNATURE_COMMON_H 2 | #define SIGNATURE_COMMON_H 3 | 4 | #include 5 | #include 6 | 7 | #include "lowmc_pars.h" 8 | #include "mpc_lowmc.h" 9 | 10 | typedef struct { 11 | // The LowMC instance. 12 | mpc_lowmc_t* lowmc; 13 | } public_parameters_t; 14 | 15 | bool create_instance(public_parameters_t* pp, int m, int n, int r, int k); 16 | 17 | void destroy_instance(public_parameters_t* pp); 18 | 19 | void init_view(mpc_lowmc_t const* lowmc, view_t* views[NUM_ROUNDS]); 20 | void free_view(mpc_lowmc_t const* lowmc, view_t* views[NUM_ROUNDS]); 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /compat/compat.h: -------------------------------------------------------------------------------- 1 | #ifndef COMPAT_H 2 | 3 | #ifndef HAVE_ALIGNED_ALLOC 4 | #include 5 | 6 | void* aligned_alloc(size_t alignment, size_t size); 7 | #endif 8 | 9 | /* backwards compatibility macros for GCC 4.8 and 4.9 10 | * 11 | * bs{l,r}i was introduced in GCC 5 and in clang as macros sometime in 2015. 12 | * */ 13 | #if (!defined(__clang__) && defined(__GNUC__) && __GNUC__ < 5) || \ 14 | (defined(__clang__) && !defined(_mm_bslli_si128)) 15 | #define _mm_bslli_si128(a, imm) _mm_slli_si128((a), (imm)) 16 | #define _mm_bsrli_si128(a, imm) _mm_srli_si128((a), (imm)) 17 | #endif 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /randomness.h: -------------------------------------------------------------------------------- 1 | #ifndef RANDOMNESS_H 2 | #define RANDOMNESS_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | void init_EVP(); 11 | void cleanup_EVP(); 12 | 13 | typedef struct { EVP_CIPHER_CTX* ctx; } aes_prng_t; 14 | 15 | void aes_prng_init(aes_prng_t* aes_prng, const unsigned char* key); 16 | void aes_prng_clear(aes_prng_t* aes_prng); 17 | void aes_prng_get_randomness(aes_prng_t* aes_prng, unsigned char* dst, size_t count); 18 | 19 | void init_rand_bytes(void); 20 | void deinit_rand_bytes(void); 21 | int rand_bytes(unsigned char* dst, size_t len); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /parameters.h: -------------------------------------------------------------------------------- 1 | #ifndef PARAMETERS_H 2 | #define PARAMETERS_H 3 | 4 | #include 5 | 6 | // Output of size of the random oracle (\rho) 7 | #define COMMITMENT_LENGTH SHA256_DIGEST_LENGTH 8 | // Size of the randomness for the commitment (\nu) 9 | #define COMMITMENT_RAND_LENGTH 0 10 | 11 | // Repetition count (\gamma) 12 | #ifdef WITH_PQ_PARAMETERS 13 | #define NUM_ROUNDS 438 14 | #else 15 | #define NUM_ROUNDS 219 16 | #endif 17 | 18 | #define FIS_NUM_ROUNDS NUM_ROUNDS 19 | #define BG_NUM_ROUNDS NUM_ROUNDS 20 | 21 | // Share count for proofs 22 | #define SC_PROOF 3 23 | // Share count for verification 24 | #define SC_VERIFY 2 25 | 26 | // Key size for PRNG 27 | #define PRNG_KEYSIZE 16 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /README.md.anon: -------------------------------------------------------------------------------- 1 | Fish and signature schemes 2 | ========================== 3 | 4 | This code represents an implementation of the Fish signature scheme. It uses (a 5 | bit-sliced version of) LowMC [3,4] in the setting of ZKBoo [2]. Some methods for 6 | MPC computations are based on [5]. 7 | 8 | Building 9 | -------- 10 | 11 | To disable optimizations remove `-DWITH_OPT` from `CPPFLAGS` in `Makefile`. 12 | Verbose output can be enabled by adding `-DVERBOSE`. 13 | 14 | Dependencies 15 | ------------ 16 | 17 | * OpenSSL (libssl-dev) 18 | * m4ri (libm4ri-dev) 19 | 20 | References 21 | ---------- 22 | 23 | * [1] https://eprint.iacr.org/2016/163 24 | * [2] https://eprint.iacr.org/2016/687 25 | * [3] https://bitbucket.org/malb/lowmc-helib 26 | * [4] https://github.com/Sobuno/ZKBoo 27 | -------------------------------------------------------------------------------- /compat/aligned_alloc.c: -------------------------------------------------------------------------------- 1 | #ifdef HAVE_CONFIG_H 2 | #include 3 | #endif 4 | 5 | #include 6 | #include 7 | #ifndef HAVE_POSIX_MEMALIGN 8 | #include 9 | #endif 10 | 11 | // aligned_alloc is not available everywhere 12 | void* aligned_alloc(size_t alignment, size_t size) { 13 | if (alignment & (alignment - 1)) 14 | || (size & (alignment - 1)) { 15 | errno = EINVAL; 16 | return NULL; 17 | } 18 | 19 | #if HAVE_POSIX_MEMALIGN 20 | void* ptr = NULL; 21 | const int err = posix_memalign(&ptr, alignment, size); 22 | if (err) { 23 | errno = err; 24 | } 25 | return ptr; 26 | #elif defined(HAVE_MEMALIGN) 27 | return memalign(alignment, size); 28 | #else 29 | if (size > 0) { 30 | errno = ENOMEM; 31 | } 32 | return NULL; 33 | #endif 34 | } 35 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016-2017 Graz University of Technology 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the ""Software""), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Picnic-FS and -UR signature schemes 2 | =================================== 3 | 4 | This code represents an implementation of the Fish signature scheme [1]. It uses 5 | (a bit-sliced version of) LowMC [3,4] in the setting of ZKBoo [2]. Some methods 6 | for MPC computations are based on [5]. 7 | 8 | Building 9 | -------- 10 | 11 | First configure the build cmake and then run make: 12 | 13 | ```sh 14 | mkdir build; cd build 15 | cmake .. 16 | make 17 | ``` 18 | 19 | Dependencies 20 | ------------ 21 | 22 | * OpenSSL (libssl-dev) 23 | * m4ri (libm4ri-dev) 24 | 25 | License 26 | ------- 27 | 28 | The code is licensed under the MIT license. 29 | 30 | Authors 31 | ------- 32 | 33 | The code was written by David Derler and Sebastian Ramacher from [Institute for 34 | Applied Information Processing and Communications, Graz University of 35 | Technology](https://www.iaik.tugraz.at). They can be contacted via 36 | . 37 | 38 | References 39 | ---------- 40 | 41 | * [1] https://eprint.iacr.org/2017/279 42 | * [2] https://eprint.iacr.org/2016/163 43 | * [3] https://eprint.iacr.org/2016/687 44 | * [4] https://bitbucket.org/malb/lowmc-helib 45 | * [5] https://github.com/Sobuno/ZKBoo 46 | -------------------------------------------------------------------------------- /timing/nonce-lowmc-128.txt: -------------------------------------------------------------------------------- 1 | m: 2 blocksize: 128 ANDdepth: 80 ANDs/bit: 3.75 2 | m: 4 blocksize: 128 ANDdepth: 42 ANDs/bit: 3.94 3 | m: 6 blocksize: 128 ANDdepth: 30 ANDs/bit: 4.22 4 | m: 8 blocksize: 128 ANDdepth: 24 ANDs/bit: 4.5 5 | m: 10 blocksize: 128 ANDdepth: 20 ANDs/bit: 4.69 6 | m: 12 blocksize: 128 ANDdepth: 18 ANDs/bit: 5.06 7 | m: 14 blocksize: 128 ANDdepth: 16 ANDs/bit: 5.25 8 | m: 16 blocksize: 128 ANDdepth: 14 ANDs/bit: 5.25 9 | m: 18 blocksize: 128 ANDdepth: 14 ANDs/bit: 5.91 10 | m: 20 blocksize: 128 ANDdepth: 12 ANDs/bit: 5.62 11 | m: 22 blocksize: 128 ANDdepth: 12 ANDs/bit: 6.19 12 | m: 24 blocksize: 128 ANDdepth: 12 ANDs/bit: 6.75 13 | m: 26 blocksize: 128 ANDdepth: 10 ANDs/bit: 6.09 14 | m: 28 blocksize: 128 ANDdepth: 10 ANDs/bit: 6.56 15 | m: 30 blocksize: 128 ANDdepth: 10 ANDs/bit: 7.03 16 | m: 32 blocksize: 128 ANDdepth: 10 ANDs/bit: 7.5 17 | m: 34 blocksize: 128 ANDdepth: 10 ANDs/bit: 7.97 18 | m: 36 blocksize: 128 ANDdepth: 10 ANDs/bit: 8.44 19 | m: 38 blocksize: 128 ANDdepth: 8 ANDs/bit: 7.12 20 | m: 40 blocksize: 128 ANDdepth: 8 ANDs/bit: 7.5 21 | -------------------------------------------------------------------------------- /signature_fis.h: -------------------------------------------------------------------------------- 1 | #ifndef SIGNATURE_FIS_H 2 | #define SIGNATURE_FIS_H 3 | 4 | #include "signature_common.h" 5 | 6 | typedef struct { 7 | // pk = E_k(0) 8 | mzd_t* pk; 9 | } fis_public_key_t; 10 | 11 | typedef struct { lowmc_key_t* k; } fis_private_key_t; 12 | 13 | typedef struct { proof_t* proof; } fis_signature_t; 14 | 15 | unsigned fis_compute_sig_size(unsigned m, unsigned n, unsigned r, unsigned k); 16 | 17 | unsigned char* fis_sig_to_char_array(public_parameters_t* pp, fis_signature_t* sig, unsigned* len); 18 | 19 | fis_signature_t* fis_sig_from_char_array(public_parameters_t* pp, unsigned char* data); 20 | 21 | bool fis_create_key(public_parameters_t* pp, fis_private_key_t* private_key, 22 | fis_public_key_t* public_key); 23 | 24 | void fis_destroy_key(fis_private_key_t* private_key, fis_public_key_t* public_key); 25 | 26 | fis_signature_t* fis_sign(public_parameters_t* pp, fis_private_key_t* private_key, 27 | const uint8_t* msg, size_t msglen); 28 | 29 | int fis_verify(public_parameters_t* pp, fis_public_key_t* public_key, const uint8_t* msg, 30 | size_t msglen, fis_signature_t* sig); 31 | 32 | void fis_free_signature(public_parameters_t* pp, fis_signature_t* signature); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /hashing_util.h: -------------------------------------------------------------------------------- 1 | #ifndef HASHING_UTIL_H 2 | #define HASHING_UTIL_H 3 | 4 | #include "mpc_lowmc.h" 5 | #include "parameters.h" 6 | 7 | /** 8 | * Computes commitments to the view of an execution. 9 | */ 10 | void H(const unsigned char k[PRNG_KEYSIZE], mzd_t* y[SC_PROOF], view_t const* v, unsigned vidx, 11 | unsigned vcnt, const unsigned char r[COMMITMENT_RAND_LENGTH], 12 | unsigned char hash[COMMITMENT_LENGTH]); 13 | 14 | /** 15 | * Computes the challenge for Fish (when signing). 16 | */ 17 | void fis_H3(unsigned char const h[NUM_ROUNDS][SC_PROOF][COMMITMENT_LENGTH], const uint8_t* m, 18 | size_t m_len, unsigned char* ch); 19 | 20 | /** 21 | * Computes the challenge for Fish (when verifying). 22 | */ 23 | void fis_H3_verify(unsigned char const h[NUM_ROUNDS][SC_VERIFY][COMMITMENT_LENGTH], 24 | unsigned char const hp[NUM_ROUNDS][COMMITMENT_LENGTH], 25 | unsigned char const ch_in[(NUM_ROUNDS + 3) / 4], const uint8_t* m, size_t m_len, 26 | unsigned char* ch); 27 | 28 | static inline unsigned int getChAt(unsigned char const* const ch, unsigned int i) { 29 | const unsigned int idx = i >> 2; 30 | const unsigned int offset = (i & 0x3) << 1; 31 | 32 | return (ch[idx] >> offset) & 0x3; 33 | } 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /cmake/Findm4ri.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find m4ri 2 | # Once done this will define 3 | # M4RI_FOUND - System has m4ri 4 | # M4RI_INCLUDE_DIRS - The m4ri include directories 5 | # M4RI_LIBRARIES - The libraries needed to use m4ri 6 | # M4RI_DEFINITIONS - Compiler switches required for using m4ri 7 | 8 | find_package(PkgConfig) 9 | pkg_check_modules(PC_M4RI QUIET m4ri) 10 | set(M4RI_DEFINITIONS ${PC_M4RI_CFLAGS_OTHER}) 11 | set(M4RI_VERSION_STRING ${PC_M4RI_VERSION}) 12 | 13 | find_path(M4RI_INCLUDE_DIR m4ri.h 14 | HINTS ${PC_LIBM4RI_INCLUDEDIR} ${PC_M4RI_INCLUDE_DIRS} 15 | PATH_SUFFIXES m4ri) 16 | 17 | find_library(M4RI_LIBRARY NAMES m4ri libm4ri 18 | HINTS ${PC_M4RI_LIBDIR} ${PC_M4RI_LIBRARY_DIRS} ) 19 | 20 | include(FindPackageHandleStandardArgs) 21 | # handle the QUIETLY and REQUIRED arguments and set M4RI_FOUND to TRUE 22 | # if all listed variables are TRUE 23 | find_package_handle_standard_args(m4ri 24 | FOUND_VAR M4RI_FOUND 25 | REQUIRED_VARS M4RI_LIBRARY M4RI_INCLUDE_DIR 26 | VERSION_VAR M4RI_VERSION_STRING) 27 | 28 | mark_as_advanced(M4RI_INCLUDE_DIR M4RI_LIBRARY M4RI_VERSION_STRING) 29 | 30 | set(M4RI_LIBRARIES ${M4RI_LIBRARY} ) 31 | set(M4RI_INCLUDE_DIRS ${M4RI_INCLUDE_DIR} ) 32 | -------------------------------------------------------------------------------- /signature_common.c: -------------------------------------------------------------------------------- 1 | #include "signature_common.h" 2 | #include "lowmc_pars.h" 3 | #include "timing.h" 4 | 5 | bool create_instance(public_parameters_t* pp, int m, int n, int r, int k) { 6 | TIME_FUNCTION; 7 | 8 | START_TIMING; 9 | pp->lowmc = lowmc_init(m, n, r, k); 10 | END_TIMING(timing_and_size->gen.lowmc_init); 11 | 12 | return pp->lowmc != NULL; 13 | } 14 | 15 | void destroy_instance(public_parameters_t* pp) { 16 | lowmc_free(pp->lowmc); 17 | pp->lowmc = NULL; 18 | } 19 | 20 | void init_view(mpc_lowmc_t const* mpc_lowmc, view_t* views[NUM_ROUNDS]) { 21 | const unsigned int view_count = 2 + mpc_lowmc->r; 22 | 23 | unsigned char* buffer = malloc((view_count * NUM_ROUNDS) * (sizeof(view_t))); 24 | 25 | for (unsigned int i = 0; i < NUM_ROUNDS; i++) { 26 | views[i] = (view_t*)buffer; 27 | buffer += view_count * sizeof(view_t); 28 | 29 | for (unsigned m = 0; m < SC_PROOF; ++m) { 30 | views[i][0].s[m] = mzd_local_init_ex(1, mpc_lowmc->k, false); 31 | } 32 | 33 | for (unsigned n = 1; n < view_count; n++) { 34 | for (unsigned m = 0; m < SC_PROOF; m++) { 35 | views[i][n].s[m] = mzd_local_init(1, mpc_lowmc->n); 36 | } 37 | } 38 | } 39 | } 40 | 41 | void free_view(mpc_lowmc_t const* mpc_lowmc, view_t* views[NUM_ROUNDS]) { 42 | (void)mpc_lowmc; 43 | free(views[0]); 44 | } 45 | -------------------------------------------------------------------------------- /mzd_shared.h: -------------------------------------------------------------------------------- 1 | #ifndef MZD_SHARED_H 2 | #define MZD_SHARED_H 3 | 4 | #include "mzd_additional.h" 5 | #include "randomness.h" 6 | 7 | typedef struct { 8 | unsigned int share_count; 9 | mzd_t* shared[3]; 10 | } mzd_shared_t; 11 | 12 | #define MZD_SHARED_EMPTY \ 13 | { \ 14 | 0, { \ 15 | NULL \ 16 | } \ 17 | } 18 | 19 | void mzd_shared_init(mzd_shared_t* shared_value, mzd_t const* value); 20 | void mzd_shared_copy(mzd_shared_t* dst, mzd_shared_t const* src); 21 | void mzd_shared_share_from_keys(mzd_shared_t* shared_value, const unsigned char keys[2][16]); 22 | void mzd_shared_from_shares(mzd_shared_t* shared_value, mzd_t* const* shares, 23 | unsigned int share_count); 24 | void mzd_shared_share(mzd_shared_t* shared_value); 25 | void mzd_shared_share_prng(mzd_shared_t* shared_value, aes_prng_t* aes_prng); 26 | void mzd_shared_clear(mzd_shared_t* shared_value); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /timing/lowmc-inst-128-128-128.txt: -------------------------------------------------------------------------------- 1 | m: 1 blocksize: 128 ANDdepth: 252 ANDs/bit: 2 | m: 2 blocksize: 128 ANDdepth: 128 ANDs/bit: 6.0 3 | m: 4 blocksize: 128 ANDdepth: 67 ANDs/bit: 6.28 4 | m: 6 blocksize: 128 ANDdepth: 47 ANDs/bit: 6.61 5 | m: 8 blocksize: 128 ANDdepth: 36 ANDs/bit: 6.75 6 | m: 10 blocksize: 128 ANDdepth: 30 ANDs/bit: 7.03 7 | m: 12 blocksize: 128 ANDdepth: 26 ANDs/bit: 7.31 8 | m: 14 blocksize: 128 ANDdepth: 24 ANDs/bit: 7.88 9 | m: 16 blocksize: 128 ANDdepth: 23 ANDs/bit: 8.62 10 | m: 18 blocksize: 128 ANDdepth: 22 ANDs/bit: 9.28 11 | m: 20 blocksize: 128 ANDdepth: 22 ANDs/bit: 10.31 12 | m: 22 blocksize: 128 ANDdepth: 21 ANDs/bit: 10.83 13 | m: 24 blocksize: 128 ANDdepth: 21 ANDs/bit: 11.81 14 | m: 26 blocksize: 128 ANDdepth: 20 ANDs/bit: 12.19 15 | m: 28 blocksize: 128 ANDdepth: 20 ANDs/bit: 13.12 16 | m: 30 blocksize: 128 ANDdepth: 20 ANDs/bit: 14.06 17 | m: 32 blocksize: 128 ANDdepth: 19 ANDs/bit: 14.25 18 | m: 34 blocksize: 128 ANDdepth: 19 ANDs/bit: 15.14 19 | m: 36 blocksize: 128 ANDdepth: 19 ANDs/bit: 16.03 20 | m: 38 blocksize: 128 ANDdepth: 19 ANDs/bit: 16.92 21 | m: 40 blocksize: 128 ANDdepth: 19 ANDs/bit: 17.81 22 | 23 | -------------------------------------------------------------------------------- /multithreading.c: -------------------------------------------------------------------------------- 1 | #include "multithreading.h" 2 | 3 | #include 4 | 5 | /** 6 | * OpenMP integration of OpenSSL is based on 7 | * https://github.com/Sobuno/ZKBoo/blob/master/MPC_SHA256/shared.h. 8 | */ 9 | 10 | #if defined(WITH_OPENMP) && OPENSSL_VERSION_NUMBER < 0x10100000 11 | #include 12 | 13 | static omp_lock_t* locks = NULL; 14 | 15 | static void openmp_locking_callback(int mode, int type, const char* file, int line) { 16 | (void)file; 17 | (void)line; 18 | if (mode & CRYPTO_LOCK) { 19 | omp_set_lock(&locks[type]); 20 | } else { 21 | omp_unset_lock(&locks[type]); 22 | } 23 | } 24 | 25 | #if OPENSSL_VERSION_NUMBER < 0x10000000 26 | static unsigned long openmp_thread_id(void) { 27 | return (unsigned long)omp_get_thread_num(); 28 | } 29 | #endif 30 | 31 | void openmp_thread_setup(void) { 32 | locks = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(omp_lock_t)); 33 | for (int i = 0; i < CRYPTO_num_locks(); i++) { 34 | omp_init_lock(&locks[i]); 35 | } 36 | 37 | #if OPENSSL_VERSION_NUMBER < 0x10000000 38 | CRYPTO_set_id_callback(openmp_thread_id); 39 | #endif 40 | CRYPTO_set_locking_callback(openmp_locking_callback); 41 | } 42 | 43 | void openmp_thread_cleanup(void) { 44 | CRYPTO_set_id_callback(NULL); 45 | CRYPTO_set_locking_callback(NULL); 46 | for (int i = 0; i < CRYPTO_num_locks(); i++) 47 | omp_destroy_lock(&locks[i]); 48 | OPENSSL_free(locks); 49 | } 50 | 51 | #else 52 | void openmp_thread_setup(void) {} 53 | 54 | void openmp_thread_cleanup(void) {} 55 | #endif 56 | -------------------------------------------------------------------------------- /timing/style.json: -------------------------------------------------------------------------------- 1 | { 2 | "legend": { 3 | "n=256": { 4 | "size": 6 5 | } 6 | }, 7 | "default": { 8 | "Fish": { 9 | "256-256-1-243": { 10 | "horizontalalignment": "left", 11 | "xytext": [5,-2] 12 | }, 13 | "256-256-1-316": { 14 | "horizontalalignment": "left", 15 | "xytext": [5,-2] 16 | } 17 | 18 | } 19 | }, 20 | "omp": { 21 | "BG": { 22 | "256-256-2-232": { 23 | "horizontalalignment": "left", 24 | "xytext": [5,0] 25 | }, 26 | "256-256-20-31": { 27 | "horizontalalignment": "center", 28 | "xytext": [0,-12] 29 | } 30 | }, 31 | "FS": { 32 | "128-128-12-26": { 33 | "horizontalalignment": "left", 34 | "xytext": [0,5] 35 | }, 36 | "256-256-26-18": { 37 | "horizontalalignment": "left", 38 | "xytext": [0,5] 39 | }, 40 | "512-512-34-37": { 41 | "horizontalalignment": "left", 42 | "xytext": [0,5] 43 | }, 44 | "384-384-30-33": { 45 | "horizontalalignment": "center", 46 | "xytext": [0,-12] 47 | }, 48 | "384-384-4-172": { 49 | "horizontalalignment": "right", 50 | "xytext": [0,5] 51 | }, 52 | "512-512-34-37": { 53 | "horizontalalignment": "left", 54 | "xytext": [0,5] 55 | }, 56 | "512-512-6-152": { 57 | "horizontalalignment": "center", 58 | "xytext": [0,5] 59 | }, 60 | "512-512-170-25": { 61 | "horizontalalignment": "center", 62 | "xytext": [0,5] 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /timing/pq-lowmc-inst-256-256-256.txt: -------------------------------------------------------------------------------- 1 | m: 1 blocksize: 256 ANDdepth: 458 ANDs/bit: 2 | m: 2 blocksize: 256 ANDdepth: 232 ANDs/bit: 5.44 3 | m: 3 blocksize: 256 ANDdepth: 157 ANDs/bit: 5.52 4 | m: 4 blocksize: 256 ANDdepth: 119 ANDs/bit: 5.58 5 | m: 5 blocksize: 256 ANDdepth: 97 ANDs/bit: 5.68 6 | m: 6 blocksize: 256 ANDdepth: 82 ANDs/bit: 5.77 7 | m: 7 blocksize: 256 ANDdepth: 71 ANDs/bit: 5.82 8 | m: 8 blocksize: 256 ANDdepth: 63 ANDs/bit: 5.91 9 | m: 9 blocksize: 256 ANDdepth: 57 ANDs/bit: 6.01 10 | m: 10 blocksize: 256 ANDdepth: 52 ANDs/bit: 6.09 11 | m: 11 blocksize: 256 ANDdepth: 48 ANDs/bit: 6.19 12 | m: 12 blocksize: 256 ANDdepth: 44 ANDs/bit: 6.19 13 | m: 13 blocksize: 256 ANDdepth: 41 ANDs/bit: 6.25 14 | m: 14 blocksize: 256 ANDdepth: 39 ANDs/bit: 6.4 15 | m: 15 blocksize: 256 ANDdepth: 37 ANDs/bit: 6.5 16 | m: 16 blocksize: 256 ANDdepth: 35 ANDs/bit: 6.56 17 | m: 17 blocksize: 256 ANDdepth: 34 ANDs/bit: 6.77 18 | m: 18 blocksize: 256 ANDdepth: 33 ANDs/bit: 6.96 19 | m: 19 blocksize: 256 ANDdepth: 33 ANDs/bit: 7.35 20 | m: 20 blocksize: 256 ANDdepth: 31 ANDs/bit: 7.27 21 | m: 40 blocksize: 256 ANDdepth: 25 ANDs/bit: 11.72 22 | m: 60 blocksize: 256 ANDdepth: 23 ANDs/bit: 16.17 23 | m: 80 blocksize: 256 ANDdepth: 22 ANDs/bit: 20.62 24 | -------------------------------------------------------------------------------- /timing/pq-lowmc-inst-384.txt: -------------------------------------------------------------------------------- 1 | m: 2 blocksize: 384 ANDdepth: 263 ANDs/bit: 4.11 2 | m: 3 blocksize: 384 ANDdepth: 178 ANDs/bit: 4.17 3 | m: 4 blocksize: 384 ANDdepth: 135 ANDs/bit: 4.22 4 | m: 5 blocksize: 384 ANDdepth: 110 ANDs/bit: 4.3 5 | m: 6 blocksize: 384 ANDdepth: 92 ANDs/bit: 4.31 6 | m: 7 blocksize: 384 ANDdepth: 80 ANDs/bit: 4.38 7 | m: 8 blocksize: 384 ANDdepth: 71 ANDs/bit: 4.44 8 | m: 9 blocksize: 384 ANDdepth: 64 ANDs/bit: 4.5 9 | m: 10 blocksize: 384 ANDdepth: 58 ANDs/bit: 4.53 10 | m: 11 blocksize: 384 ANDdepth: 53 ANDs/bit: 4.55 11 | m: 12 blocksize: 384 ANDdepth: 49 ANDs/bit: 4.59 12 | m: 13 blocksize: 384 ANDdepth: 46 ANDs/bit: 4.67 13 | m: 14 blocksize: 384 ANDdepth: 43 ANDs/bit: 4.7 14 | m: 15 blocksize: 384 ANDdepth: 41 ANDs/bit: 4.8 15 | m: 16 blocksize: 384 ANDdepth: 39 ANDs/bit: 4.88 16 | m: 17 blocksize: 384 ANDdepth: 37 ANDs/bit: 4.91 17 | m: 18 blocksize: 384 ANDdepth: 35 ANDs/bit: 4.92 18 | m: 19 blocksize: 384 ANDdepth: 33 ANDs/bit: 4.9 19 | m: 20 blocksize: 384 ANDdepth: 32 ANDs/bit: 5.0 20 | m: 40 blocksize: 384 ANDdepth: 21 ANDs/bit: 6.56 21 | m: 60 blocksize: 384 ANDdepth: 19 ANDs/bit: 8.91 22 | m: 80 blocksize: 384 ANDdepth: 17 ANDs/bit: 10.62 23 | m: 100 blocksize: 384 ANDdepth: 17 ANDs/bit: 13.28 24 | m: 120 blocksize: 384 ANDdepth: 17 ANDs/bit: 15.94 25 | -------------------------------------------------------------------------------- /timing/pq-lowmc-inst-512.txt: -------------------------------------------------------------------------------- 1 | m: 4 blocksize: 512 ANDdepth: 158 ANDs/bit: 3.7 2 | m: 5 blocksize: 512 ANDdepth: 128 ANDs/bit: 3.75 3 | m: 6 blocksize: 512 ANDdepth: 107 ANDs/bit: 3.76 4 | m: 7 blocksize: 512 ANDdepth: 93 ANDs/bit: 3.81 5 | m: 8 blocksize: 512 ANDdepth: 82 ANDs/bit: 3.84 6 | m: 9 blocksize: 512 ANDdepth: 74 ANDs/bit: 3.9 7 | m: 10 blocksize: 512 ANDdepth: 67 ANDs/bit: 3.93 8 | m: 11 blocksize: 512 ANDdepth: 62 ANDs/bit: 4.0 9 | m: 12 blocksize: 512 ANDdepth: 57 ANDs/bit: 4.01 10 | m: 13 blocksize: 512 ANDdepth: 53 ANDs/bit: 4.04 11 | m: 14 blocksize: 512 ANDdepth: 50 ANDs/bit: 4.1 12 | m: 15 blocksize: 512 ANDdepth: 47 ANDs/bit: 4.13 13 | m: 16 blocksize: 512 ANDdepth: 44 ANDs/bit: 4.12 14 | m: 17 blocksize: 512 ANDdepth: 42 ANDs/bit: 4.18 15 | m: 18 blocksize: 512 ANDdepth: 40 ANDs/bit: 4.22 16 | m: 19 blocksize: 512 ANDdepth: 38 ANDs/bit: 4.23 17 | m: 20 blocksize: 512 ANDdepth: 37 ANDs/bit: 4.34 18 | m: 40 blocksize: 512 ANDdepth: 22 ANDs/bit: 5.16 19 | m: 60 blocksize: 512 ANDdepth: 20 ANDs/bit: 7.03 20 | m: 80 blocksize: 512 ANDdepth: 18 ANDs/bit: 8.44 21 | m: 100 blocksize: 512 ANDdepth: 17 ANDs/bit: 9.96 22 | m: 120 blocksize: 512 ANDdepth: 17 ANDs/bit: 11.95 23 | m: 140 blocksize: 512 ANDdepth: 16 ANDs/bit: 13.12 24 | m: 160 blocksize: 512 ANDdepth: 16 ANDs/bit: 15.0 25 | -------------------------------------------------------------------------------- /io.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "io.h" 4 | #include "mzd_additional.h" 5 | 6 | unsigned char* mzd_to_char_array(mzd_t* data, unsigned numbytes) { 7 | if (!numbytes) 8 | return 0; 9 | 10 | const unsigned vec_len = data->ncols; 11 | const unsigned word_count = vec_len / (8 * sizeof(word)); 12 | const unsigned num_full_words = numbytes / 8; 13 | const unsigned bytes_last_word = numbytes - (num_full_words * 8); 14 | unsigned char* result = (unsigned char*)malloc(numbytes * sizeof(unsigned char)); 15 | 16 | word* d = data->rows[0]; 17 | unsigned char* temp = result; 18 | int i = word_count - 1; 19 | int j = i - num_full_words; 20 | for (; i > j; i--) { 21 | memcpy(temp, &d[i], sizeof(word)); 22 | temp += sizeof(word); 23 | } 24 | if (bytes_last_word) { 25 | unsigned char* in = ((unsigned char*)&d[i]) + (sizeof(word) - bytes_last_word); 26 | memcpy(temp, in, bytes_last_word); 27 | } 28 | return result; 29 | } 30 | 31 | mzd_t* mzd_from_char_array(unsigned char* data, unsigned len, unsigned vec_len) { 32 | mzd_t* result = mzd_local_init(1, vec_len); 33 | 34 | const unsigned word_count = vec_len / (8 * sizeof(word)); 35 | const unsigned num_full_words = len / 8; 36 | const unsigned bytes_last_word = len - (num_full_words * 8); 37 | 38 | word* d = result->rows[0]; 39 | word* in = (word*)data; 40 | unsigned idx = word_count - 1; 41 | for (unsigned i = 0; i < num_full_words; i++) { 42 | memcpy(&d[idx], in, sizeof(word)); 43 | in++; 44 | idx--; 45 | } 46 | if (bytes_last_word) { 47 | unsigned char* out = ((unsigned char*)&d[idx]) + (sizeof(word) - bytes_last_word); 48 | memcpy(out, in, bytes_last_word); 49 | } 50 | return result; 51 | } 52 | -------------------------------------------------------------------------------- /timing.h: -------------------------------------------------------------------------------- 1 | #ifndef TIMING_H 2 | #define TIMING_H 3 | 4 | #include 5 | #include 6 | 7 | typedef union { 8 | struct { 9 | struct { 10 | uint64_t lowmc_init, keygen, pubkey; 11 | } gen; 12 | struct { 13 | uint64_t rand, secret_sharing, lowmc_enc, views, challenge; 14 | } sign; 15 | struct { 16 | uint64_t challenge, output_shares, output_views, verify; 17 | } verify; 18 | uint64_t size; 19 | }; 20 | uint64_t data[13]; 21 | } timing_and_size_t; 22 | 23 | extern timing_and_size_t* timing_and_size; 24 | 25 | #ifdef WITH_DETAILED_TIMING 26 | 27 | #define gettime gettime_clock 28 | #define TIME_FUNCTION uint64_t start_time 29 | #define START_TIMING start_time = gettime() 30 | #define END_TIMING(dst) dst = gettime() - start_time 31 | 32 | #define TIMING_SCALE (1000000 / CLOCKS_PER_SEC); 33 | 34 | #ifdef WITH_OPENMP 35 | #include 36 | 37 | static inline uint64_t gettime_clock() { 38 | return omp_get_wtime() * 1000 * 1000; 39 | } 40 | #else 41 | static inline uint64_t gettime_clock() { 42 | return clock() * TIMING_SCALE; 43 | } 44 | #endif 45 | 46 | #else 47 | 48 | #define TIME_FUNCTION \ 49 | do { \ 50 | } while (0) 51 | #define START_TIMING \ 52 | do { \ 53 | } while (0) 54 | #define END_TIMING(dst) \ 55 | do { \ 56 | } while (0) 57 | 58 | #endif 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /timing/nonce-lowmc-192.txt: -------------------------------------------------------------------------------- 1 | m: 2 blocksize: 192 ANDdepth: 102 ANDs/bit: 3.19 2 | m: 4 blocksize: 192 ANDdepth: 54 ANDs/bit: 3.38 3 | m: 6 blocksize: 192 ANDdepth: 38 ANDs/bit: 3.56 4 | m: 8 blocksize: 192 ANDdepth: 30 ANDs/bit: 3.75 5 | m: 10 blocksize: 192 ANDdepth: 24 ANDs/bit: 3.75 6 | m: 12 blocksize: 192 ANDdepth: 22 ANDs/bit: 4.12 7 | m: 14 blocksize: 192 ANDdepth: 18 ANDs/bit: 3.94 8 | m: 16 blocksize: 192 ANDdepth: 18 ANDs/bit: 4.5 9 | m: 18 blocksize: 192 ANDdepth: 16 ANDs/bit: 4.5 10 | m: 20 blocksize: 192 ANDdepth: 14 ANDs/bit: 4.38 11 | m: 22 blocksize: 192 ANDdepth: 14 ANDs/bit: 4.81 12 | m: 24 blocksize: 192 ANDdepth: 14 ANDs/bit: 5.25 13 | m: 26 blocksize: 192 ANDdepth: 12 ANDs/bit: 4.88 14 | m: 28 blocksize: 192 ANDdepth: 12 ANDs/bit: 5.25 15 | m: 30 blocksize: 192 ANDdepth: 12 ANDs/bit: 5.62 16 | m: 32 blocksize: 192 ANDdepth: 12 ANDs/bit: 6.0 17 | m: 34 blocksize: 192 ANDdepth: 10 ANDs/bit: 5.31 18 | m: 36 blocksize: 192 ANDdepth: 10 ANDs/bit: 5.62 19 | m: 38 blocksize: 192 ANDdepth: 10 ANDs/bit: 5.94 20 | m: 40 blocksize: 192 ANDdepth: 10 ANDs/bit: 6.25 21 | m: 42 blocksize: 192 ANDdepth: 10 ANDs/bit: 6.56 22 | m: 44 blocksize: 192 ANDdepth: 10 ANDs/bit: 6.88 23 | m: 46 blocksize: 192 ANDdepth: 10 ANDs/bit: 7.19 24 | m: 48 blocksize: 192 ANDdepth: 10 ANDs/bit: 7.5 25 | m: 50 blocksize: 192 ANDdepth: 8 ANDs/bit: 6.25 26 | m: 52 blocksize: 192 ANDdepth: 8 ANDs/bit: 6.5 27 | m: 54 blocksize: 192 ANDdepth: 8 ANDs/bit: 6.75 28 | m: 56 blocksize: 192 ANDdepth: 8 ANDs/bit: 7.0 29 | m: 58 blocksize: 192 ANDdepth: 8 ANDs/bit: 7.25 30 | m: 60 blocksize: 192 ANDdepth: 8 ANDs/bit: 7.5 31 | m: 62 blocksize: 192 ANDdepth: 8 ANDs/bit: 7.75 32 | -------------------------------------------------------------------------------- /timing/lowmc-inst-192-192-192.txt: -------------------------------------------------------------------------------- 1 | m: 2 blocksize: 192 ANDdepth: 152 ANDs/bit: 4.75 2 | m: 4 blocksize: 192 ANDdepth: 78 ANDs/bit: 4.88 3 | m: 6 blocksize: 192 ANDdepth: 54 ANDs/bit: 5.06 4 | m: 8 blocksize: 192 ANDdepth: 42 ANDs/bit: 5.25 5 | m: 10 blocksize: 192 ANDdepth: 35 ANDs/bit: 5.47 6 | m: 12 blocksize: 192 ANDdepth: 30 ANDs/bit: 5.62 7 | m: 14 blocksize: 192 ANDdepth: 26 ANDs/bit: 5.69 8 | m: 16 blocksize: 192 ANDdepth: 24 ANDs/bit: 6.0 9 | m: 18 blocksize: 192 ANDdepth: 22 ANDs/bit: 6.19 10 | m: 20 blocksize: 192 ANDdepth: 20 ANDs/bit: 6.25 11 | m: 22 blocksize: 192 ANDdepth: 19 ANDs/bit: 6.53 12 | m: 24 blocksize: 192 ANDdepth: 18 ANDs/bit: 6.75 13 | m: 26 blocksize: 192 ANDdepth: 17 ANDs/bit: 6.91 14 | m: 28 blocksize: 192 ANDdepth: 17 ANDs/bit: 7.44 15 | m: 30 blocksize: 192 ANDdepth: 17 ANDs/bit: 7.97 16 | m: 32 blocksize: 192 ANDdepth: 16 ANDs/bit: 8.0 17 | m: 34 blocksize: 192 ANDdepth: 16 ANDs/bit: 8.5 18 | m: 36 blocksize: 192 ANDdepth: 16 ANDs/bit: 9.0 19 | m: 38 blocksize: 192 ANDdepth: 15 ANDs/bit: 8.91 20 | m: 40 blocksize: 192 ANDdepth: 15 ANDs/bit: 9.38 21 | m: 42 blocksize: 192 ANDdepth: 15 ANDs/bit: 9.84 22 | m: 44 blocksize: 192 ANDdepth: 15 ANDs/bit: 10.31 23 | m: 46 blocksize: 192 ANDdepth: 15 ANDs/bit: 10.78 24 | m: 48 blocksize: 192 ANDdepth: 15 ANDs/bit: 11.25 25 | m: 50 blocksize: 192 ANDdepth: 15 ANDs/bit: 11.72 26 | m: 52 blocksize: 192 ANDdepth: 15 ANDs/bit: 12.19 27 | m: 54 blocksize: 192 ANDdepth: 15 ANDs/bit: 12.66 28 | m: 56 blocksize: 192 ANDdepth: 15 ANDs/bit: 13.12 29 | m: 58 blocksize: 192 ANDdepth: 15 ANDs/bit: 13.59 30 | m: 60 blocksize: 192 ANDdepth: 15 ANDs/bit: 14.06 31 | m: 62 blocksize: 192 ANDdepth: 15 ANDs/bit: 14.53 32 | -------------------------------------------------------------------------------- /timing/lowmc-inst-256-256-d=1.3.txt: -------------------------------------------------------------------------------- 1 | m: 42 blocksize: 256 ANDdepth: 14 2 | m: 41 blocksize: 256 ANDdepth: 14 3 | m: 40 blocksize: 256 ANDdepth: 14 4 | m: 39 blocksize: 256 ANDdepth: 17 5 | m: 38 blocksize: 256 ANDdepth: 17 6 | m: 37 blocksize: 256 ANDdepth: 17 7 | m: 36 blocksize: 256 ANDdepth: 17 8 | m: 35 blocksize: 256 ANDdepth: 17 9 | m: 34 blocksize: 256 ANDdepth: 17 10 | m: 33 blocksize: 256 ANDdepth: 17 11 | m: 32 blocksize: 256 ANDdepth: 17 12 | m: 31 blocksize: 256 ANDdepth: 17 13 | m: 30 blocksize: 256 ANDdepth: 17 14 | m: 29 blocksize: 256 ANDdepth: 20 15 | m: 28 blocksize: 256 ANDdepth: 20 16 | m: 27 blocksize: 256 ANDdepth: 20 17 | m: 26 blocksize: 256 ANDdepth: 20 18 | m: 25 blocksize: 256 ANDdepth: 20 19 | m: 24 blocksize: 256 ANDdepth: 20 20 | m: 23 blocksize: 256 ANDdepth: 23 21 | m: 22 blocksize: 256 ANDdepth: 22 22 | m: 21 blocksize: 256 ANDdepth: 22 23 | m: 20 blocksize: 256 ANDdepth: 22 24 | m: 19 blocksize: 256 ANDdepth: 24 25 | m: 18 blocksize: 256 ANDdepth: 24 26 | m: 17 blocksize: 256 ANDdepth: 24 27 | m: 16 blocksize: 256 ANDdepth: 27 28 | m: 15 blocksize: 256 ANDdepth: 27 29 | m: 14 blocksize: 256 ANDdepth: 30 30 | m: 13 blocksize: 256 ANDdepth: 33 31 | m: 12 blocksize: 256 ANDdepth: 33 32 | m: 11 blocksize: 256 ANDdepth: 35 33 | m: 10 blocksize: 256 ANDdepth: 38 34 | m: 9 blocksize: 256 ANDdepth: 42 35 | m: 8 blocksize: 256 ANDdepth: 46 36 | m: 7 blocksize: 256 ANDdepth: 51 37 | m: 6 blocksize: 256 ANDdepth: 59 38 | m: 5 blocksize: 256 ANDdepth: 69 39 | m: 4 blocksize: 256 ANDdepth: 85 40 | m: 3 blocksize: 256 ANDdepth: 111 41 | m: 2 blocksize: 256 ANDdepth: 163 42 | m: 1 blocksize: 256 ANDdepth: 316 43 | -------------------------------------------------------------------------------- /randomness.c: -------------------------------------------------------------------------------- 1 | #include "randomness.h" 2 | #include "parameters.h" 3 | 4 | #include 5 | 6 | void init_EVP() { 7 | #if OPENSSL_VERSION_NUMBER >= 0x10100000 8 | OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS | OPENSSL_INIT_ADD_ALL_CIPHERS | 9 | OPENSSL_INIT_ADD_ALL_DIGESTS, 10 | NULL); 11 | #else 12 | ERR_load_crypto_strings(); 13 | OpenSSL_add_all_algorithms(); 14 | OPENSSL_config(NULL); 15 | #endif 16 | } 17 | 18 | void cleanup_EVP() { 19 | #if OPENSSL_VERSION_NUMBER >= 0x10100000 20 | OPENSSL_cleanup(); 21 | #else 22 | EVP_cleanup(); 23 | ERR_free_strings(); 24 | #endif 25 | } 26 | 27 | void aes_prng_init(aes_prng_t* aes_prng, const unsigned char* key) { 28 | aes_prng->ctx = EVP_CIPHER_CTX_new(); 29 | 30 | /* A 128 bit IV */ 31 | static const unsigned char iv[16] = {'0', '1', '2', '3', '4', '5', '6', '7', 32 | '8', '9', '0', '1', '2', '3', '4', '5'}; 33 | EVP_EncryptInit_ex(aes_prng->ctx, EVP_aes_128_ctr(), NULL, key, iv); 34 | } 35 | 36 | void aes_prng_clear(aes_prng_t* aes_prng) { 37 | EVP_CIPHER_CTX_free(aes_prng->ctx); 38 | } 39 | 40 | void aes_prng_get_randomness(aes_prng_t* aes_prng, unsigned char* dst, size_t count) { 41 | static const unsigned char plaintext[16] = {'0'}; 42 | 43 | EVP_CIPHER_CTX* ctx = aes_prng->ctx; 44 | 45 | int len = 0; 46 | for (; count >= 16; count -= 16, dst += 16) { 47 | EVP_EncryptUpdate(ctx, dst, &len, plaintext, sizeof(plaintext)); 48 | } 49 | 50 | if (count) { 51 | EVP_EncryptUpdate(ctx, dst, &len, plaintext, count); 52 | } 53 | } 54 | 55 | // maybe seed with data from /dev/urandom 56 | 57 | static aes_prng_t aes_prng; 58 | 59 | void init_rand_bytes(void) { 60 | unsigned char key[PRNG_KEYSIZE]; 61 | RAND_bytes(key, sizeof(key)); 62 | 63 | aes_prng_init(&aes_prng, key); 64 | } 65 | 66 | int rand_bytes(unsigned char* dst, size_t len) { 67 | aes_prng_get_randomness(&aes_prng, dst, len); 68 | return 1; 69 | } 70 | 71 | void deinit_rand_bytes(void) { 72 | aes_prng_clear(&aes_prng); 73 | } 74 | -------------------------------------------------------------------------------- /lowmc_pars.h: -------------------------------------------------------------------------------- 1 | #ifndef LOWMC_PARS_H 2 | #define LOWMC_PARS_H 3 | 4 | #include "mzd_additional.h" 5 | #include 6 | 7 | typedef mzd_t lowmc_key_t; 8 | 9 | typedef struct { 10 | mzd_t* x0; 11 | mzd_t* x1; 12 | mzd_t* x2; 13 | mzd_t* mask; 14 | } mask_t; 15 | 16 | typedef struct { 17 | mzd_t* k_matrix; 18 | mzd_t* l_matrix; 19 | mzd_t* constant; 20 | 21 | #ifdef NOSCR 22 | mzd_t* k_lookup; 23 | mzd_t* l_lookup; 24 | #endif 25 | } lowmc_round_t; 26 | 27 | /** 28 | * Represents the LowMC parameters as in https://bitbucket.org/malb/lowmc-helib/src, 29 | * with the difference that key in a separate struct 30 | */ 31 | typedef struct { 32 | size_t m; 33 | size_t n; 34 | size_t r; 35 | size_t k; 36 | 37 | mask_t mask; 38 | 39 | mzd_t* k0_matrix; 40 | #ifdef NOSCR 41 | mzd_t* k0_lookup; 42 | #endif 43 | lowmc_round_t* rounds; 44 | } lowmc_t; 45 | 46 | /** 47 | * Generates a new LowMC instance (also including a key) 48 | * 49 | * \param m the number of sboxes 50 | * \param n the blocksize 51 | * \param r the number of rounds 52 | * \param k the keysize 53 | * 54 | * \return parameters defining a LowMC instance (including a key) 55 | */ 56 | lowmc_t* lowmc_init(size_t m, size_t n, size_t r, size_t k); 57 | 58 | lowmc_key_t* lowmc_keygen(lowmc_t* lowmc); 59 | 60 | /** 61 | * Frees the allocated LowMC parameters 62 | * 63 | * \param lowmc the LowMC parameters to be freed 64 | */ 65 | void lowmc_free(lowmc_t* lowmc); 66 | 67 | /** 68 | * Frees the allocated LowMC key. 69 | * 70 | * \param lowmc_key the LowMC key to be freed 71 | */ 72 | void lowmc_key_free(lowmc_key_t* lowmc_key); 73 | 74 | /** 75 | * Updates a given LowMC parameter instance so that the key is 76 | * split into three components representing the additive secret 77 | * sharing of LowMC 78 | * 79 | * \param lowmc the LowMC parameters 80 | */ 81 | void lowmc_secret_share(lowmc_t* lowmc, lowmc_key_t* lowmc_key); 82 | 83 | lowmc_t* readFile(size_t m, size_t n, size_t r, size_t k); 84 | bool writeFile(lowmc_t* lowmc); 85 | void writeMZD_TStructToFile(mzd_t* matrix, FILE* file); 86 | mzd_t* readMZD_TStructFromFile(FILE* file); 87 | #endif 88 | -------------------------------------------------------------------------------- /timing/nonce-lowmc-256.txt: -------------------------------------------------------------------------------- 1 | m: 2 blocksize: 256 ANDdepth: 124 ANDs/bit: 2.91 2 | m: 4 blocksize: 256 ANDdepth: 64 ANDs/bit: 3.0 3 | m: 6 blocksize: 256 ANDdepth: 44 ANDs/bit: 3.09 4 | m: 8 blocksize: 256 ANDdepth: 34 ANDs/bit: 3.19 5 | m: 10 blocksize: 256 ANDdepth: 28 ANDs/bit: 3.28 6 | m: 12 blocksize: 256 ANDdepth: 24 ANDs/bit: 3.38 7 | m: 14 blocksize: 256 ANDdepth: 22 ANDs/bit: 3.61 8 | m: 16 blocksize: 256 ANDdepth: 20 ANDs/bit: 3.75 9 | m: 18 blocksize: 256 ANDdepth: 18 ANDs/bit: 3.8 10 | m: 20 blocksize: 256 ANDdepth: 16 ANDs/bit: 3.75 11 | m: 22 blocksize: 256 ANDdepth: 16 ANDs/bit: 4.12 12 | m: 24 blocksize: 256 ANDdepth: 14 ANDs/bit: 3.94 13 | m: 26 blocksize: 256 ANDdepth: 14 ANDs/bit: 4.27 14 | m: 28 blocksize: 256 ANDdepth: 14 ANDs/bit: 4.59 15 | m: 30 blocksize: 256 ANDdepth: 12 ANDs/bit: 4.22 16 | m: 32 blocksize: 256 ANDdepth: 12 ANDs/bit: 4.5 17 | m: 34 blocksize: 256 ANDdepth: 12 ANDs/bit: 4.78 18 | m: 36 blocksize: 256 ANDdepth: 12 ANDs/bit: 5.06 19 | m: 38 blocksize: 256 ANDdepth: 12 ANDs/bit: 5.34 20 | m: 40 blocksize: 256 ANDdepth: 10 ANDs/bit: 4.69 21 | m: 42 blocksize: 256 ANDdepth: 10 ANDs/bit: 4.92 22 | m: 44 blocksize: 256 ANDdepth: 10 ANDs/bit: 5.16 23 | m: 46 blocksize: 256 ANDdepth: 10 ANDs/bit: 5.39 24 | m: 48 blocksize: 256 ANDdepth: 10 ANDs/bit: 5.62 25 | m: 50 blocksize: 256 ANDdepth: 10 ANDs/bit: 5.86 26 | m: 52 blocksize: 256 ANDdepth: 10 ANDs/bit: 6.09 27 | m: 54 blocksize: 256 ANDdepth: 10 ANDs/bit: 6.33 28 | m: 56 blocksize: 256 ANDdepth: 10 ANDs/bit: 6.56 29 | m: 58 blocksize: 256 ANDdepth: 10 ANDs/bit: 6.8 30 | m: 60 blocksize: 256 ANDdepth: 8 ANDs/bit: 5.62 31 | m: 62 blocksize: 256 ANDdepth: 8 ANDs/bit: 5.81 32 | m: 64 blocksize: 256 ANDdepth: 8 ANDs/bit: 6.0 33 | m: 66 blocksize: 256 ANDdepth: 8 ANDs/bit: 6.19 34 | m: 68 blocksize: 256 ANDdepth: 8 ANDs/bit: 6.38 35 | m: 70 blocksize: 256 ANDdepth: 8 ANDs/bit: 6.56 36 | m: 72 blocksize: 256 ANDdepth: 8 ANDs/bit: 6.75 37 | m: 74 blocksize: 256 ANDdepth: 8 ANDs/bit: 6.94 38 | m: 76 blocksize: 256 ANDdepth: 8 ANDs/bit: 7.12 39 | m: 78 blocksize: 256 ANDdepth: 8 ANDs/bit: 7.31 40 | m: 80 blocksize: 256 ANDdepth: 8 ANDs/bit: 7.5 41 | m: 82 blocksize: 256 ANDdepth: 8 ANDs/bit: 7.69 42 | m: 84 blocksize: 256 ANDdepth: 8 ANDs/bit: 7.88 43 | -------------------------------------------------------------------------------- /timing/lowmc-inst-256-256-256.txt: -------------------------------------------------------------------------------- 1 | m: 2 blocksize: 256 ANDdepth: 174 ANDs/bit: 4.08 2 | m: 4 blocksize: 256 ANDdepth: 90 ANDs/bit: 4.22 3 | m: 6 blocksize: 256 ANDdepth: 62 ANDs/bit: 4.36 4 | m: 8 blocksize: 256 ANDdepth: 48 ANDs/bit: 4.5 5 | m: 10 blocksize: 256 ANDdepth: 39 ANDs/bit: 4.57 6 | m: 12 blocksize: 256 ANDdepth: 34 ANDs/bit: 4.78 7 | m: 14 blocksize: 256 ANDdepth: 30 ANDs/bit: 4.92 8 | m: 16 blocksize: 256 ANDdepth: 27 ANDs/bit: 5.06 9 | m: 18 blocksize: 256 ANDdepth: 24 ANDs/bit: 5.06 10 | m: 20 blocksize: 256 ANDdepth: 22 ANDs/bit: 5.16 11 | m: 22 blocksize: 256 ANDdepth: 21 ANDs/bit: 5.41 12 | m: 24 blocksize: 256 ANDdepth: 20 ANDs/bit: 5.62 13 | m: 26 blocksize: 256 ANDdepth: 18 ANDs/bit: 5.48 14 | m: 28 blocksize: 256 ANDdepth: 18 ANDs/bit: 5.91 15 | m: 30 blocksize: 256 ANDdepth: 18 ANDs/bit: 6.33 16 | m: 32 blocksize: 256 ANDdepth: 17 ANDs/bit: 6.38 17 | m: 34 blocksize: 256 ANDdepth: 16 ANDs/bit: 6.38 18 | m: 36 blocksize: 256 ANDdepth: 16 ANDs/bit: 6.75 19 | m: 38 blocksize: 256 ANDdepth: 16 ANDs/bit: 7.12 20 | m: 40 blocksize: 256 ANDdepth: 16 ANDs/bit: 7.5 21 | m: 42 blocksize: 256 ANDdepth: 16 ANDs/bit: 7.88 22 | m: 44 blocksize: 256 ANDdepth: 16 ANDs/bit: 8.25 23 | m: 46 blocksize: 256 ANDdepth: 16 ANDs/bit: 8.62 24 | m: 48 blocksize: 256 ANDdepth: 16 ANDs/bit: 9.0 25 | m: 50 blocksize: 256 ANDdepth: 15 ANDs/bit: 8.79 26 | m: 52 blocksize: 256 ANDdepth: 15 ANDs/bit: 9.14 27 | m: 54 blocksize: 256 ANDdepth: 15 ANDs/bit: 9.49 28 | m: 56 blocksize: 256 ANDdepth: 15 ANDs/bit: 9.84 29 | m: 58 blocksize: 256 ANDdepth: 15 ANDs/bit: 10.2 30 | m: 60 blocksize: 256 ANDdepth: 15 ANDs/bit: 10.55 31 | m: 62 blocksize: 256 ANDdepth: 15 ANDs/bit: 10.9 32 | m: 64 blocksize: 256 ANDdepth: 14 ANDs/bit: 10.5 33 | m: 66 blocksize: 256 ANDdepth: 14 ANDs/bit: 10.83 34 | m: 68 blocksize: 256 ANDdepth: 14 ANDs/bit: 11.16 35 | m: 70 blocksize: 256 ANDdepth: 14 ANDs/bit: 11.48 36 | m: 72 blocksize: 256 ANDdepth: 14 ANDs/bit: 11.81 37 | m: 74 blocksize: 256 ANDdepth: 14 ANDs/bit: 12.14 38 | m: 76 blocksize: 256 ANDdepth: 14 ANDs/bit: 12.47 39 | m: 78 blocksize: 256 ANDdepth: 14 ANDs/bit: 12.8 40 | m: 80 blocksize: 256 ANDdepth: 14 ANDs/bit: 13.12 41 | m: 82 blocksize: 256 ANDdepth: 14 ANDs/bit: 13.45 42 | m: 84 blocksize: 256 ANDdepth: 14 ANDs/bit: 13.78 43 | -------------------------------------------------------------------------------- /timing/lowmc-inst-128-128-d=1.txt: -------------------------------------------------------------------------------- 1 | m: 42 blocksize: 128 ANDdepth: 8 ANDs/bit: 7.88 2 | m: 41 blocksize: 128 ANDdepth: 8 ANDs/bit: 7.69 3 | m: 40 blocksize: 128 ANDdepth: 8 ANDs/bit: 7.5 4 | m: 39 blocksize: 128 ANDdepth: 8 ANDs/bit: 7.31 5 | m: 38 blocksize: 128 ANDdepth: 8 ANDs/bit: 7.12 6 | m: 37 blocksize: 128 ANDdepth: 10 ANDs/bit: 8.67 7 | m: 36 blocksize: 128 ANDdepth: 10 ANDs/bit: 8.44 8 | m: 35 blocksize: 128 ANDdepth: 10 ANDs/bit: 8.2 9 | m: 34 blocksize: 128 ANDdepth: 10 ANDs/bit: 7.97 10 | m: 33 blocksize: 128 ANDdepth: 10 ANDs/bit: 7.73 11 | m: 32 blocksize: 128 ANDdepth: 10 ANDs/bit: 7.5 12 | m: 31 blocksize: 128 ANDdepth: 10 ANDs/bit: 7.27 13 | m: 30 blocksize: 128 ANDdepth: 10 ANDs/bit: 7.03 14 | m: 29 blocksize: 128 ANDdepth: 10 ANDs/bit: 6.8 15 | m: 28 blocksize: 128 ANDdepth: 10 ANDs/bit: 6.56 16 | m: 27 blocksize: 128 ANDdepth: 10 ANDs/bit: 6.33 17 | m: 26 blocksize: 128 ANDdepth: 10 ANDs/bit: 6.09 18 | m: 25 blocksize: 128 ANDdepth: 12 ANDs/bit: 7.03 19 | m: 24 blocksize: 128 ANDdepth: 12 ANDs/bit: 6.75 20 | m: 23 blocksize: 128 ANDdepth: 12 ANDs/bit: 6.47 21 | m: 22 blocksize: 128 ANDdepth: 12 ANDs/bit: 6.19 22 | m: 21 blocksize: 128 ANDdepth: 12 ANDs/bit: 5.91 23 | m: 20 blocksize: 128 ANDdepth: 12 ANDs/bit: 5.62 24 | m: 19 blocksize: 128 ANDdepth: 12 ANDs/bit: 5.34 25 | m: 18 blocksize: 128 ANDdepth: 14 ANDs/bit: 5.91 26 | m: 17 blocksize: 128 ANDdepth: 14 ANDs/bit: 5.58 27 | m: 16 blocksize: 128 ANDdepth: 14 ANDs/bit: 5.25 28 | m: 15 blocksize: 128 ANDdepth: 16 ANDs/bit: 5.62 29 | m: 14 blocksize: 128 ANDdepth: 16 ANDs/bit: 5.25 30 | m: 13 blocksize: 128 ANDdepth: 16 ANDs/bit: 4.88 31 | m: 12 blocksize: 128 ANDdepth: 18 ANDs/bit: 5.06 32 | m: 11 blocksize: 128 ANDdepth: 18 ANDs/bit: 4.64 33 | m: 10 blocksize: 128 ANDdepth: 20 ANDs/bit: 4.69 34 | m: 9 blocksize: 128 ANDdepth: 22 ANDs/bit: 4.64 35 | m: 8 blocksize: 128 ANDdepth: 24 ANDs/bit: 4.5 36 | m: 7 blocksize: 128 ANDdepth: 26 ANDs/bit: 4.27 37 | m: 6 blocksize: 128 ANDdepth: 30 ANDs/bit: 4.22 38 | m: 5 blocksize: 128 ANDdepth: 36 ANDs/bit: 4.22 39 | m: 4 blocksize: 128 ANDdepth: 42 ANDs/bit: 3.94 40 | m: 3 blocksize: 128 ANDdepth: 56 ANDs/bit: 3.94 41 | m: 2 blocksize: 128 ANDdepth: 80 ANDs/bit: 3.75 42 | m: 1 blocksize: 128 ANDdepth: 156 ANDs/bit: 3.66 43 | -------------------------------------------------------------------------------- /timing/lowmc-inst-256-256-d=1.txt: -------------------------------------------------------------------------------- 1 | m: 42 blocksize: 256 ANDdepth: 11 ANDs/bit: 5.41 2 | m: 41 blocksize: 256 ANDdepth: 11 ANDs/bit: 5.29 3 | m: 40 blocksize: 256 ANDdepth: 11 ANDs/bit: 5.16 4 | m: 39 blocksize: 256 ANDdepth: 13 ANDs/bit: 5.94 5 | m: 38 blocksize: 256 ANDdepth: 13 ANDs/bit: 5.79 6 | m: 37 blocksize: 256 ANDdepth: 13 ANDs/bit: 5.64 7 | m: 36 blocksize: 256 ANDdepth: 13 ANDs/bit: 5.48 8 | m: 35 blocksize: 256 ANDdepth: 13 ANDs/bit: 5.33 9 | m: 34 blocksize: 256 ANDdepth: 13 ANDs/bit: 5.18 10 | m: 33 blocksize: 256 ANDdepth: 13 ANDs/bit: 5.03 11 | m: 32 blocksize: 256 ANDdepth: 13 ANDs/bit: 4.88 12 | m: 31 blocksize: 256 ANDdepth: 13 ANDs/bit: 4.72 13 | m: 30 blocksize: 256 ANDdepth: 13 ANDs/bit: 4.57 14 | m: 29 blocksize: 256 ANDdepth: 15 ANDs/bit: 5.1 15 | m: 28 blocksize: 256 ANDdepth: 15 ANDs/bit: 4.92 16 | m: 27 blocksize: 256 ANDdepth: 15 ANDs/bit: 4.75 17 | m: 26 blocksize: 256 ANDdepth: 15 ANDs/bit: 4.57 18 | m: 25 blocksize: 256 ANDdepth: 15 ANDs/bit: 4.39 19 | m: 24 blocksize: 256 ANDdepth: 15 ANDs/bit: 4.22 20 | m: 23 blocksize: 256 ANDdepth: 17 ANDs/bit: 4.58 21 | m: 22 blocksize: 256 ANDdepth: 17 ANDs/bit: 4.38 22 | m: 21 blocksize: 256 ANDdepth: 17 ANDs/bit: 4.18 23 | m: 20 blocksize: 256 ANDdepth: 17 ANDs/bit: 3.98 24 | m: 19 blocksize: 256 ANDdepth: 19 ANDs/bit: 4.23 25 | m: 18 blocksize: 256 ANDdepth: 19 ANDs/bit: 4.01 26 | m: 17 blocksize: 256 ANDdepth: 19 ANDs/bit: 3.79 27 | m: 16 blocksize: 256 ANDdepth: 21 ANDs/bit: 3.94 28 | m: 15 blocksize: 256 ANDdepth: 21 ANDs/bit: 3.69 29 | m: 14 blocksize: 256 ANDdepth: 23 ANDs/bit: 3.77 30 | m: 13 blocksize: 256 ANDdepth: 25 ANDs/bit: 3.81 31 | m: 12 blocksize: 256 ANDdepth: 25 ANDs/bit: 3.52 32 | m: 11 blocksize: 256 ANDdepth: 27 ANDs/bit: 3.48 33 | m: 10 blocksize: 256 ANDdepth: 29 ANDs/bit: 3.4 34 | m: 9 blocksize: 256 ANDdepth: 33 ANDs/bit: 3.48 35 | m: 8 blocksize: 256 ANDdepth: 35 ANDs/bit: 3.28 36 | m: 7 blocksize: 256 ANDdepth: 39 ANDs/bit: 3.2 37 | m: 6 blocksize: 256 ANDdepth: 45 ANDs/bit: 3.16 38 | m: 5 blocksize: 256 ANDdepth: 53 ANDs/bit: 3.11 39 | m: 4 blocksize: 256 ANDdepth: 65 ANDs/bit: 3.05 40 | m: 3 blocksize: 256 ANDdepth: 85 ANDs/bit: 2.99 41 | m: 2 blocksize: 256 ANDdepth: 125 ANDs/bit: 2.93 42 | m: 1 blocksize: 256 ANDdepth: 243 ANDs/bit: 2.85 43 | -------------------------------------------------------------------------------- /mzd_shared.c: -------------------------------------------------------------------------------- 1 | #include "mzd_shared.h" 2 | 3 | void mzd_shared_init(mzd_shared_t* shared_value, mzd_t const* value) { 4 | shared_value->share_count = 1; 5 | 6 | mzd_local_init_multiple(shared_value->shared, 3, value->nrows, value->ncols); 7 | mzd_local_copy(shared_value->shared[2], value); 8 | } 9 | 10 | void mzd_shared_copy(mzd_shared_t* dst, mzd_shared_t const* src) { 11 | mzd_shared_clear(dst); 12 | mzd_shared_from_shares(dst, src->shared, src->share_count); 13 | } 14 | 15 | void mzd_shared_from_shares(mzd_shared_t* shared_value, mzd_t* const* shares, 16 | unsigned int share_count) { 17 | shared_value->share_count = share_count; 18 | mzd_local_init_multiple_ex(shared_value->shared, 3, shares[0]->nrows, shares[0]->ncols, false); 19 | 20 | for (unsigned int i = 0; i < share_count; ++i) { 21 | mzd_local_copy(shared_value->shared[i], shares[i]); 22 | } 23 | } 24 | 25 | void mzd_shared_share_from_keys(mzd_shared_t* shared_value, const unsigned char keys[2][16]) { 26 | shared_value->share_count = 3; 27 | 28 | // shared_value->shared[2] = shared_value->shared[0]; 29 | 30 | mzd_randomize_from_seed(shared_value->shared[0], keys[0]); 31 | mzd_randomize_from_seed(shared_value->shared[1], keys[1]); 32 | 33 | mzd_xor(shared_value->shared[2], shared_value->shared[0], shared_value->shared[2]); 34 | mzd_xor(shared_value->shared[2], shared_value->shared[1], shared_value->shared[2]); 35 | } 36 | 37 | #if 0 38 | void mzd_shared_share(mzd_shared_t* shared_value) { 39 | shared_value->share_count = 3; 40 | 41 | shared_value->shared[1] = mzd_init_random_vector(shared_value->shared[0]->ncols); 42 | shared_value->shared[2] = mzd_init_random_vector(shared_value->shared[0]->ncols); 43 | 44 | mzd_xor(shared_value->shared[0], shared_value->shared[0], shared_value->shared[1]); 45 | mzd_xor(shared_value->shared[0], shared_value->shared[0], shared_value->shared[2]); 46 | } 47 | 48 | void mzd_shared_share_prng(mzd_shared_t* shared_value, aes_prng_t* aes_prng) { 49 | shared_value->share_count = 3; 50 | 51 | shared_value->shared[1] = mzd_init_random_vector_prng(shared_value->shared[0]->ncols, aes_prng); 52 | shared_value->shared[2] = mzd_init_random_vector_prng(shared_value->shared[0]->ncols, aes_prng); 53 | 54 | mzd_xor(shared_value->shared[0], shared_value->shared[0], shared_value->shared[1]); 55 | mzd_xor(shared_value->shared[0], shared_value->shared[0], shared_value->shared[2]); 56 | } 57 | #endif 58 | 59 | void mzd_shared_clear(mzd_shared_t* shared_value) { 60 | mzd_local_free_multiple(shared_value->shared); 61 | for (unsigned int i = 0; i < shared_value->share_count; ++i) { 62 | shared_value->shared[i] = NULL; 63 | } 64 | shared_value->share_count = 0; 65 | } 66 | -------------------------------------------------------------------------------- /timing/lowmc-inst-512-512-512.txt: -------------------------------------------------------------------------------- 1 | m: 170 blocksize: 512 ANDdepth: 25 ANDs/bit: 24.9 2 | m: 166 blocksize: 512 ANDdepth: 25 ANDs/bit: 24.32 3 | m: 162 blocksize: 512 ANDdepth: 25 ANDs/bit: 23.73 4 | m: 158 blocksize: 512 ANDdepth: 25 ANDs/bit: 23.14 5 | m: 154 blocksize: 512 ANDdepth: 25 ANDs/bit: 22.56 6 | m: 150 blocksize: 512 ANDdepth: 25 ANDs/bit: 21.97 7 | m: 146 blocksize: 512 ANDdepth: 25 ANDs/bit: 21.39 8 | m: 142 blocksize: 512 ANDdepth: 25 ANDs/bit: 20.8 9 | m: 138 blocksize: 512 ANDdepth: 25 ANDs/bit: 20.21 10 | m: 134 blocksize: 512 ANDdepth: 25 ANDs/bit: 19.63 11 | m: 130 blocksize: 512 ANDdepth: 25 ANDs/bit: 19.04 12 | m: 126 blocksize: 512 ANDdepth: 26 ANDs/bit: 19.2 13 | m: 122 blocksize: 512 ANDdepth: 26 ANDs/bit: 18.59 14 | m: 118 blocksize: 512 ANDdepth: 26 ANDs/bit: 17.98 15 | m: 114 blocksize: 512 ANDdepth: 26 ANDs/bit: 17.37 16 | m: 110 blocksize: 512 ANDdepth: 26 ANDs/bit: 16.76 17 | m: 106 blocksize: 512 ANDdepth: 26 ANDs/bit: 16.15 18 | m: 102 blocksize: 512 ANDdepth: 26 ANDs/bit: 15.54 19 | m: 98 blocksize: 512 ANDdepth: 26 ANDs/bit: 14.93 20 | m: 94 blocksize: 512 ANDdepth: 27 ANDs/bit: 14.87 21 | m: 90 blocksize: 512 ANDdepth: 27 ANDs/bit: 14.24 22 | m: 86 blocksize: 512 ANDdepth: 27 ANDs/bit: 13.61 23 | m: 82 blocksize: 512 ANDdepth: 28 ANDs/bit: 13.45 24 | m: 78 blocksize: 512 ANDdepth: 28 ANDs/bit: 12.8 25 | m: 74 blocksize: 512 ANDdepth: 28 ANDs/bit: 12.14 26 | m: 70 blocksize: 512 ANDdepth: 28 ANDs/bit: 11.48 27 | m: 66 blocksize: 512 ANDdepth: 28 ANDs/bit: 10.83 28 | m: 62 blocksize: 512 ANDdepth: 30 ANDs/bit: 10.9 29 | m: 58 blocksize: 512 ANDdepth: 30 ANDs/bit: 10.2 30 | m: 54 blocksize: 512 ANDdepth: 31 ANDs/bit: 9.81 31 | m: 50 blocksize: 512 ANDdepth: 31 ANDs/bit: 9.08 32 | m: 46 blocksize: 512 ANDdepth: 33 ANDs/bit: 8.89 33 | m: 42 blocksize: 512 ANDdepth: 34 ANDs/bit: 8.37 34 | m: 38 blocksize: 512 ANDdepth: 36 ANDs/bit: 8.02 35 | m: 34 blocksize: 512 ANDdepth: 37 ANDs/bit: 7.37 36 | m: 30 blocksize: 512 ANDdepth: 39 ANDs/bit: 6.86 37 | m: 26 blocksize: 512 ANDdepth: 43 ANDs/bit: 6.55 38 | m: 22 blocksize: 512 ANDdepth: 47 ANDs/bit: 6.06 39 | m: 18 blocksize: 512 ANDdepth: 56 ANDs/bit: 5.91 40 | m: 14 blocksize: 512 ANDdepth: 69 ANDs/bit: 5.66 41 | m: 10 blocksize: 512 ANDdepth: 94 ANDs/bit: 5.51 42 | m: 6 blocksize: 512 ANDdepth: 152 ANDs/bit: 5.34 43 | -------------------------------------------------------------------------------- /timing/pq-lowmc-inst-512-512-512.txt: -------------------------------------------------------------------------------- 1 | m: 170 blocksize: 512 ANDdepth: 25 ANDs/bit: 24.9 2 | m: 166 blocksize: 512 ANDdepth: 25 ANDs/bit: 24.32 3 | m: 162 blocksize: 512 ANDdepth: 25 ANDs/bit: 23.73 4 | m: 158 blocksize: 512 ANDdepth: 25 ANDs/bit: 23.14 5 | m: 154 blocksize: 512 ANDdepth: 25 ANDs/bit: 22.56 6 | m: 150 blocksize: 512 ANDdepth: 25 ANDs/bit: 21.97 7 | m: 146 blocksize: 512 ANDdepth: 25 ANDs/bit: 21.39 8 | m: 142 blocksize: 512 ANDdepth: 25 ANDs/bit: 20.8 9 | m: 138 blocksize: 512 ANDdepth: 25 ANDs/bit: 20.21 10 | m: 134 blocksize: 512 ANDdepth: 25 ANDs/bit: 19.63 11 | m: 130 blocksize: 512 ANDdepth: 25 ANDs/bit: 19.04 12 | m: 126 blocksize: 512 ANDdepth: 26 ANDs/bit: 19.2 13 | m: 122 blocksize: 512 ANDdepth: 26 ANDs/bit: 18.59 14 | m: 118 blocksize: 512 ANDdepth: 26 ANDs/bit: 17.98 15 | m: 114 blocksize: 512 ANDdepth: 26 ANDs/bit: 17.37 16 | m: 110 blocksize: 512 ANDdepth: 26 ANDs/bit: 16.76 17 | m: 106 blocksize: 512 ANDdepth: 26 ANDs/bit: 16.15 18 | m: 102 blocksize: 512 ANDdepth: 26 ANDs/bit: 15.54 19 | m: 98 blocksize: 512 ANDdepth: 26 ANDs/bit: 14.93 20 | m: 94 blocksize: 512 ANDdepth: 27 ANDs/bit: 14.87 21 | m: 90 blocksize: 512 ANDdepth: 27 ANDs/bit: 14.24 22 | m: 86 blocksize: 512 ANDdepth: 27 ANDs/bit: 13.61 23 | m: 82 blocksize: 512 ANDdepth: 28 ANDs/bit: 13.45 24 | m: 78 blocksize: 512 ANDdepth: 28 ANDs/bit: 12.8 25 | m: 74 blocksize: 512 ANDdepth: 28 ANDs/bit: 12.14 26 | m: 70 blocksize: 512 ANDdepth: 28 ANDs/bit: 11.48 27 | m: 66 blocksize: 512 ANDdepth: 28 ANDs/bit: 10.83 28 | m: 62 blocksize: 512 ANDdepth: 30 ANDs/bit: 10.9 29 | m: 58 blocksize: 512 ANDdepth: 30 ANDs/bit: 10.2 30 | m: 54 blocksize: 512 ANDdepth: 31 ANDs/bit: 9.81 31 | m: 50 blocksize: 512 ANDdepth: 31 ANDs/bit: 9.08 32 | m: 46 blocksize: 512 ANDdepth: 33 ANDs/bit: 8.89 33 | m: 42 blocksize: 512 ANDdepth: 34 ANDs/bit: 8.37 34 | m: 38 blocksize: 512 ANDdepth: 36 ANDs/bit: 8.02 35 | m: 34 blocksize: 512 ANDdepth: 37 ANDs/bit: 7.37 36 | m: 30 blocksize: 512 ANDdepth: 39 ANDs/bit: 6.86 37 | m: 26 blocksize: 512 ANDdepth: 43 ANDs/bit: 6.55 38 | m: 22 blocksize: 512 ANDdepth: 47 ANDs/bit: 6.06 39 | m: 18 blocksize: 512 ANDdepth: 56 ANDs/bit: 5.91 40 | m: 14 blocksize: 512 ANDdepth: 69 ANDs/bit: 5.66 41 | m: 10 blocksize: 512 ANDdepth: 94 ANDs/bit: 5.51 42 | m: 6 blocksize: 512 ANDdepth: 152 ANDs/bit: 5.34 43 | -------------------------------------------------------------------------------- /mpc_lowmc.h: -------------------------------------------------------------------------------- 1 | #ifndef MPC_LOWMC_H 2 | #define MPC_LOWMC_H 3 | 4 | #include 5 | #include 6 | 7 | #include "lowmc_pars.h" 8 | #include "mzd_shared.h" 9 | #include "parameters.h" 10 | 11 | typedef mzd_shared_t mpc_lowmc_key_t; 12 | 13 | typedef lowmc_t mpc_lowmc_t; 14 | 15 | typedef struct { mzd_t* s[SC_PROOF]; } view_t; 16 | 17 | typedef struct { 18 | view_t* views[NUM_ROUNDS]; 19 | unsigned char keys[NUM_ROUNDS][SC_VERIFY][PRNG_KEYSIZE]; 20 | unsigned char r[NUM_ROUNDS][SC_VERIFY][COMMITMENT_RAND_LENGTH]; 21 | unsigned char hashes[NUM_ROUNDS][COMMITMENT_LENGTH]; 22 | unsigned char ch[(NUM_ROUNDS + 3) / 4]; 23 | } proof_t; 24 | 25 | proof_t* proof_from_char_array(mpc_lowmc_t* lowmc, proof_t* proof, unsigned char* data, 26 | unsigned* len, bool contains_ch); 27 | 28 | unsigned char* proof_to_char_array(mpc_lowmc_t* lowmc, proof_t* proof, unsigned* len, 29 | bool store_ch); 30 | 31 | proof_t* create_proof(proof_t* proof, mpc_lowmc_t const* lowmc, 32 | unsigned char hashes[NUM_ROUNDS][SC_PROOF][COMMITMENT_LENGTH], 33 | unsigned char ch[NUM_ROUNDS], 34 | unsigned char r[NUM_ROUNDS][SC_PROOF][COMMITMENT_RAND_LENGTH], 35 | unsigned char keys[NUM_ROUNDS][SC_PROOF][PRNG_KEYSIZE], 36 | view_t* const views[NUM_ROUNDS]); 37 | 38 | void clear_proof(mpc_lowmc_t const* lowmc, proof_t const* proof); 39 | void free_proof(mpc_lowmc_t const* lowmc, proof_t* proof); 40 | 41 | /** 42 | * Implements MPC LowMC encryption according to 43 | * https://eprint.iacr.org/2016/163.pdf 44 | * 45 | * \param lowmc the lowmc parameters 46 | * \param lowmc_key the lowmc key 47 | * \param p the plaintext 48 | * \param views the views 49 | * \param rvec the randomness vector 50 | * \return the ciphertext 51 | */ 52 | mzd_t** mpc_lowmc_call(mpc_lowmc_t const* lowmc, mpc_lowmc_key_t* lowmc_key, mzd_t const* p, 53 | view_t* views, mzd_t*** rvec); 54 | 55 | /** 56 | * Verifies a ZKBoo execution of a LowMC encryption 57 | * 58 | * \param lowmc the lowmc parameters 59 | * \param p the plaintext 60 | * \param views the views 61 | * \param rvec the randomness vector 62 | * \return 0 on success and a value != 0 otherwise 63 | */ 64 | int mpc_lowmc_verify(mpc_lowmc_t const* lowmc, mzd_t const* p, view_t const* views, 65 | mzd_t*** rvec, int c); 66 | 67 | /** 68 | * Verifies a ZKBoo execution of a LowMC encryption 69 | * 70 | * \param lowmc the lowmc parameters 71 | * \param p the plaintext 72 | * \param views the views 73 | * \param rvec the randomness vector 74 | * \return 0 on success and a value != 0 otherwise 75 | */ 76 | int mpc_lowmc_verify_keys(mpc_lowmc_t const* lowmc, mzd_t const* p, view_t const* views, 77 | mzd_t*** rvec, int c, const unsigned char keys[2][16]); 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /timing/Makefile: -------------------------------------------------------------------------------- 1 | ITER?=100 2 | MAXTHREADS?=$(shell grep "^processor" /proc/cpuinfo | wc -l) 3 | 4 | PQEX=-x ../mpc_lowmc_pq 5 | 6 | timings-preq: 7 | # python3 timing.py lowmc-inst-128-128-128.txt -k 128 -i $(ITER) 8 | # python3 timing.py lowmc-inst-192-192-192.txt -k 192 -i $(ITER) 9 | python3 timing.py lowmc-inst-256-256-256.txt -k 256 -i $(ITER) 10 | # python3 timing.py lowmc-inst-512-512-512.txt -k 512 -i $(ITER) 11 | 12 | timings-postq: 13 | python3 timing.py pq-lowmc-inst-256-256-256.txt -k 256 -i $(ITER) $(PQEX) -p pq-timings 14 | python3 timing.py lowmc-inst-256-256-d=1.txt -k 256 -i $(ITER) $(PQEX) -p pq-timings-d1 15 | python3 timing.py lowmc-inst-256-256-d=1.3.txt -k 256 -i $(ITER) $(PQEX) -p pq-timings-d1.3 16 | # python3 timing.py pq-lowmc-inst-384-384-384.txt -k 384 -i $(ITER) $(PQOPTS) 17 | # python3 timing.py pq-lowmc-inst-512-512-512.txt -k 512 -i $(ITER) $(PQOPTS) 18 | 19 | timings-omp: 20 | # before running this benchmark, make sure to disable HyperThreading as it 21 | # adds a lot of noise. 22 | set -ex && for n in $(shell seq 1 $(MAXTHREADS)) ; do \ 23 | env OMP_NUM_THREADS=$$n \ 24 | python3 timing.py lowmc-inst-256-256-256.txt -k 256 -i $(ITER) \ 25 | -p omp-timings-$$n -x ../mpc_lowmc_openmp; \ 26 | done 27 | 28 | timings: timings-preq timings-postq timings-omp 29 | 30 | graphs-preq: 31 | # python3 graphs.py -p timings default \ 32 | --fs-blocksize 128 --fs-keysize 128 --fs-annotate 12-26 \ 33 | --bg-blocksize 128 --bg-keysize 128 --bg-annotate 12-26 34 | python3 graphs.py -p timings default \ 35 | --fs-blocksize 256 --fs-keysize 256 --fs-annotate 20-31 \ 36 | --bg-blocksize 256 --bg-keysize 256 --bg-annotate 20-31 37 | 38 | graphs-postq: 39 | python3 graphs.py -p pq-timings default \ 40 | --fs-blocksize 256 --fs-keysize 256 --fs-annotate 20-31 \ 41 | --bg-blocksize 256 --bg-keysize 256 --bg-annotate 20-31 \ 42 | --sha-proof 237 --sha-verify 137 --sha-size 2672.484375 43 | python3 graphs.py -p pq-timings-d1 default \ 44 | --fs-blocksize 256 --fs-keysize 256 --fs-annotate 10-29 \ 45 | --bg-blocksize 256 --bg-keysize 256 --bg-annotate 10-29 \ 46 | --sha-proof 237 --sha-verify 137 --sha-size 2672.484375 \ 47 | --no-sha-annotation 48 | python3 graphs.py -p pq-timings-d1.3 default \ 49 | --fs-blocksize 256 --fs-keysize 256 --fs-annotate 10-38 \ 50 | --bg-blocksize 256 --bg-keysize 256 --bg-annotate 10-38 \ 51 | --sha-proof 237 --sha-verify 137 --sha-size 2672.484375 \ 52 | --no-sha-annotation 53 | 54 | 55 | graphs-omp: 56 | python3 graphs.py -p omp-timings omp --bg-blocksize 256 --bg-keysize 256 -t $(MAXTHREADS) 57 | 58 | graphs-qh: 59 | python3 graphs.py -p timings qH \ 60 | --bg-blocksize 128 --bg-keysize 128 --bg-annotate 12-26 \ 61 | --fs-annotate "128-128-12-26 256-256-26-18 512-512-34-37" \ 62 | --annotate-extreme \ 63 | 128 256 512 64 | python3 graphs.py -p pq-timings qH \ 65 | --bg-blocksize 256 --bg-keysize 256 --bg-annotate 20-31 \ 66 | --fs-annotate "256-256-20-31 384-384-30-33 512-512-34-37" \ 67 | --annotate-extreme \ 68 | 256 384 512 69 | 70 | graphs: graphs-preq graphs-postq graphs-omp graphs-qh 71 | 72 | all: timings-plain graphs-plain 73 | -------------------------------------------------------------------------------- /timing/nonce-lowmc-320.txt: -------------------------------------------------------------------------------- 1 | m: 2 blocksize: 320 ANDdepth: 144 ANDs/bit: 2.7 2 | m: 4 blocksize: 320 ANDdepth: 74 ANDs/bit: 2.77 3 | m: 6 blocksize: 320 ANDdepth: 52 ANDs/bit: 2.92 4 | m: 8 blocksize: 320 ANDdepth: 40 ANDs/bit: 3.0 5 | m: 10 blocksize: 320 ANDdepth: 32 ANDs/bit: 3.0 6 | m: 12 blocksize: 320 ANDdepth: 28 ANDs/bit: 3.15 7 | m: 14 blocksize: 320 ANDdepth: 24 ANDs/bit: 3.15 8 | m: 16 blocksize: 320 ANDdepth: 22 ANDs/bit: 3.3 9 | m: 18 blocksize: 320 ANDdepth: 20 ANDs/bit: 3.38 10 | m: 20 blocksize: 320 ANDdepth: 18 ANDs/bit: 3.38 11 | m: 22 blocksize: 320 ANDdepth: 18 ANDs/bit: 3.71 12 | m: 24 blocksize: 320 ANDdepth: 16 ANDs/bit: 3.6 13 | m: 26 blocksize: 320 ANDdepth: 16 ANDs/bit: 3.9 14 | m: 28 blocksize: 320 ANDdepth: 14 ANDs/bit: 3.67 15 | m: 30 blocksize: 320 ANDdepth: 14 ANDs/bit: 3.94 16 | m: 32 blocksize: 320 ANDdepth: 14 ANDs/bit: 4.2 17 | m: 34 blocksize: 320 ANDdepth: 14 ANDs/bit: 4.46 18 | m: 36 blocksize: 320 ANDdepth: 12 ANDs/bit: 4.05 19 | m: 38 blocksize: 320 ANDdepth: 12 ANDs/bit: 4.28 20 | m: 40 blocksize: 320 ANDdepth: 12 ANDs/bit: 4.5 21 | m: 42 blocksize: 320 ANDdepth: 12 ANDs/bit: 4.72 22 | m: 44 blocksize: 320 ANDdepth: 12 ANDs/bit: 4.95 23 | m: 46 blocksize: 320 ANDdepth: 12 ANDs/bit: 5.17 24 | m: 48 blocksize: 320 ANDdepth: 10 ANDs/bit: 4.5 25 | m: 50 blocksize: 320 ANDdepth: 10 ANDs/bit: 4.69 26 | m: 52 blocksize: 320 ANDdepth: 10 ANDs/bit: 4.88 27 | m: 54 blocksize: 320 ANDdepth: 10 ANDs/bit: 5.06 28 | m: 56 blocksize: 320 ANDdepth: 10 ANDs/bit: 5.25 29 | m: 58 blocksize: 320 ANDdepth: 10 ANDs/bit: 5.44 30 | m: 60 blocksize: 320 ANDdepth: 10 ANDs/bit: 5.62 31 | m: 62 blocksize: 320 ANDdepth: 10 ANDs/bit: 5.81 32 | m: 64 blocksize: 320 ANDdepth: 10 ANDs/bit: 6.0 33 | m: 66 blocksize: 320 ANDdepth: 10 ANDs/bit: 6.19 34 | m: 68 blocksize: 320 ANDdepth: 10 ANDs/bit: 6.38 35 | m: 70 blocksize: 320 ANDdepth: 8 ANDs/bit: 5.25 36 | m: 72 blocksize: 320 ANDdepth: 8 ANDs/bit: 5.4 37 | m: 74 blocksize: 320 ANDdepth: 8 ANDs/bit: 5.55 38 | m: 76 blocksize: 320 ANDdepth: 8 ANDs/bit: 5.7 39 | m: 78 blocksize: 320 ANDdepth: 8 ANDs/bit: 5.85 40 | m: 80 blocksize: 320 ANDdepth: 8 ANDs/bit: 6.0 41 | m: 82 blocksize: 320 ANDdepth: 8 ANDs/bit: 6.15 42 | m: 84 blocksize: 320 ANDdepth: 8 ANDs/bit: 6.3 43 | m: 86 blocksize: 320 ANDdepth: 8 ANDs/bit: 6.45 44 | m: 88 blocksize: 320 ANDdepth: 8 ANDs/bit: 6.6 45 | m: 90 blocksize: 320 ANDdepth: 8 ANDs/bit: 6.75 46 | m: 92 blocksize: 320 ANDdepth: 8 ANDs/bit: 6.9 47 | m: 94 blocksize: 320 ANDdepth: 8 ANDs/bit: 7.05 48 | m: 96 blocksize: 320 ANDdepth: 8 ANDs/bit: 7.2 49 | m: 98 blocksize: 320 ANDdepth: 8 ANDs/bit: 7.35 50 | m: 100 blocksize: 320 ANDdepth: 8 ANDs/bit: 7.5 51 | m: 102 blocksize: 320 ANDdepth: 8 ANDs/bit: 7.65 52 | m: 104 blocksize: 320 ANDdepth: 8 ANDs/bit: 7.8 53 | -------------------------------------------------------------------------------- /timing/nonce-lowmc-384.txt: -------------------------------------------------------------------------------- 1 | m: 2 blocksize: 384 ANDdepth: 166 ANDs/bit: 2.59 2 | m: 4 blocksize: 384 ANDdepth: 86 ANDs/bit: 2.69 3 | m: 6 blocksize: 384 ANDdepth: 58 ANDs/bit: 2.72 4 | m: 8 blocksize: 384 ANDdepth: 46 ANDs/bit: 2.88 5 | m: 10 blocksize: 384 ANDdepth: 38 ANDs/bit: 2.97 6 | m: 12 blocksize: 384 ANDdepth: 32 ANDs/bit: 3.0 7 | m: 14 blocksize: 384 ANDdepth: 28 ANDs/bit: 3.06 8 | m: 16 blocksize: 384 ANDdepth: 26 ANDs/bit: 3.25 9 | m: 18 blocksize: 384 ANDdepth: 22 ANDs/bit: 3.09 10 | m: 20 blocksize: 384 ANDdepth: 22 ANDs/bit: 3.44 11 | m: 22 blocksize: 384 ANDdepth: 20 ANDs/bit: 3.44 12 | m: 24 blocksize: 384 ANDdepth: 18 ANDs/bit: 3.38 13 | m: 26 blocksize: 384 ANDdepth: 18 ANDs/bit: 3.66 14 | m: 28 blocksize: 384 ANDdepth: 16 ANDs/bit: 3.5 15 | m: 30 blocksize: 384 ANDdepth: 16 ANDs/bit: 3.75 16 | m: 32 blocksize: 384 ANDdepth: 16 ANDs/bit: 4.0 17 | m: 34 blocksize: 384 ANDdepth: 14 ANDs/bit: 3.72 18 | m: 36 blocksize: 384 ANDdepth: 14 ANDs/bit: 3.94 19 | m: 38 blocksize: 384 ANDdepth: 14 ANDs/bit: 4.16 20 | m: 40 blocksize: 384 ANDdepth: 14 ANDs/bit: 4.38 21 | m: 42 blocksize: 384 ANDdepth: 12 ANDs/bit: 3.94 22 | m: 44 blocksize: 384 ANDdepth: 12 ANDs/bit: 4.12 23 | m: 46 blocksize: 384 ANDdepth: 12 ANDs/bit: 4.31 24 | m: 48 blocksize: 384 ANDdepth: 12 ANDs/bit: 4.5 25 | m: 50 blocksize: 384 ANDdepth: 12 ANDs/bit: 4.69 26 | m: 52 blocksize: 384 ANDdepth: 12 ANDs/bit: 4.88 27 | m: 54 blocksize: 384 ANDdepth: 10 ANDs/bit: 4.22 28 | m: 56 blocksize: 384 ANDdepth: 10 ANDs/bit: 4.38 29 | m: 58 blocksize: 384 ANDdepth: 10 ANDs/bit: 4.53 30 | m: 60 blocksize: 384 ANDdepth: 10 ANDs/bit: 4.69 31 | m: 62 blocksize: 384 ANDdepth: 10 ANDs/bit: 4.84 32 | m: 64 blocksize: 384 ANDdepth: 10 ANDs/bit: 5.0 33 | m: 66 blocksize: 384 ANDdepth: 10 ANDs/bit: 5.16 34 | m: 68 blocksize: 384 ANDdepth: 10 ANDs/bit: 5.31 35 | m: 70 blocksize: 384 ANDdepth: 10 ANDs/bit: 5.47 36 | m: 72 blocksize: 384 ANDdepth: 10 ANDs/bit: 5.62 37 | m: 74 blocksize: 384 ANDdepth: 10 ANDs/bit: 5.78 38 | m: 76 blocksize: 384 ANDdepth: 10 ANDs/bit: 5.94 39 | m: 78 blocksize: 384 ANDdepth: 10 ANDs/bit: 6.09 40 | m: 80 blocksize: 384 ANDdepth: 10 ANDs/bit: 6.25 41 | m: 82 blocksize: 384 ANDdepth: 8 ANDs/bit: 5.12 42 | m: 84 blocksize: 384 ANDdepth: 8 ANDs/bit: 5.25 43 | m: 86 blocksize: 384 ANDdepth: 8 ANDs/bit: 5.38 44 | m: 88 blocksize: 384 ANDdepth: 8 ANDs/bit: 5.5 45 | m: 90 blocksize: 384 ANDdepth: 8 ANDs/bit: 5.62 46 | m: 92 blocksize: 384 ANDdepth: 8 ANDs/bit: 5.75 47 | m: 94 blocksize: 384 ANDdepth: 8 ANDs/bit: 5.88 48 | m: 96 blocksize: 384 ANDdepth: 8 ANDs/bit: 6.0 49 | m: 98 blocksize: 384 ANDdepth: 8 ANDs/bit: 6.12 50 | m: 100 blocksize: 384 ANDdepth: 8 ANDs/bit: 6.25 51 | m: 102 blocksize: 384 ANDdepth: 8 ANDs/bit: 6.38 52 | m: 104 blocksize: 384 ANDdepth: 8 ANDs/bit: 6.5 53 | m: 106 blocksize: 384 ANDdepth: 8 ANDs/bit: 6.62 54 | m: 108 blocksize: 384 ANDdepth: 8 ANDs/bit: 6.75 55 | m: 110 blocksize: 384 ANDdepth: 8 ANDs/bit: 6.88 56 | m: 112 blocksize: 384 ANDdepth: 8 ANDs/bit: 7.0 57 | m: 114 blocksize: 384 ANDdepth: 8 ANDs/bit: 7.12 58 | m: 116 blocksize: 384 ANDdepth: 8 ANDs/bit: 7.25 59 | m: 118 blocksize: 384 ANDdepth: 8 ANDs/bit: 7.38 60 | m: 120 blocksize: 384 ANDdepth: 8 ANDs/bit: 7.5 61 | m: 122 blocksize: 384 ANDdepth: 8 ANDs/bit: 7.62 62 | m: 124 blocksize: 384 ANDdepth: 8 ANDs/bit: 7.75 63 | m: 126 blocksize: 384 ANDdepth: 8 ANDs/bit: 7.88 64 | -------------------------------------------------------------------------------- /simd.h: -------------------------------------------------------------------------------- 1 | #ifndef SIMD_H 2 | #define SIMD_H 3 | 4 | #ifdef HAVE_CONFIG_H 5 | #include 6 | #endif 7 | 8 | #include 9 | 10 | #define FN_ATTRIBUTES_AVX2 __attribute__((__always_inline__, target("avx2"), pure)) 11 | #define FN_ATTRIBUTES_SSE2 __attribute__((__always_inline__, target("sse2"), pure)) 12 | 13 | #define FN_ATTRIBUTES_AVX2_NP __attribute__((__always_inline__, target("avx2"))) 14 | #define FN_ATTRIBUTES_SSE2_NP __attribute__((__always_inline__, target("sse2"))) 15 | 16 | #define CPU_SUPPORTS_AVX2 __builtin_cpu_supports("avx2") 17 | #define CPU_SUPPORTS_SSE4_1 __builtin_cpu_supports("sse4.1") 18 | 19 | #ifdef __x86_64__ 20 | #define CPU_SUPPORTS_SSE2 1 21 | #else 22 | #define CPU_SUPPORTS_SSE2 __builtin_cpu_supports("sse2") 23 | #endif 24 | 25 | #ifdef WITH_AVX2 26 | /** 27 | * \brief Perform a left shift on a 256 bit value. 28 | */ 29 | static inline __m256i FN_ATTRIBUTES_AVX2 mm256_shift_left(__m256i data, unsigned int count) { 30 | if (!count) { 31 | return data; 32 | } 33 | 34 | __m256i carry = _mm256_srli_epi64(data, 64 - count); 35 | __m256i rotate = _mm256_permute4x64_epi64(carry, _MM_SHUFFLE(2, 1, 0, 3)); 36 | carry = _mm256_blend_epi32(_mm256_setzero_si256(), rotate, _MM_SHUFFLE(3, 3, 3, 0)); 37 | data = _mm256_slli_epi64(data, count); 38 | return _mm256_or_si256(data, carry); 39 | } 40 | 41 | /** 42 | * \brief Perform a right shift on a 256 bit value. 43 | */ 44 | static inline __m256i FN_ATTRIBUTES_AVX2 mm256_shift_right(__m256i data, unsigned int count) { 45 | if (!count) { 46 | return data; 47 | } 48 | 49 | __m256i carry = _mm256_slli_epi64(data, 64 - count); 50 | __m256i rotate = _mm256_permute4x64_epi64(carry, _MM_SHUFFLE(0, 3, 2, 1)); 51 | carry = _mm256_blend_epi32(_mm256_setzero_si256(), rotate, _MM_SHUFFLE(0, 3, 3, 3)); 52 | data = _mm256_srli_epi64(data, count); 53 | return _mm256_or_si256(data, carry); 54 | } 55 | 56 | /** 57 | * \brief xor multiple 256 bit values. 58 | */ 59 | static inline void FN_ATTRIBUTES_AVX2_NP mm256_xor_region(__m256i* restrict dst, 60 | __m256i const* restrict src, 61 | unsigned int count) { 62 | for (unsigned int i = count; i; --i, ++dst, ++src) { 63 | *dst = _mm256_xor_si256(*dst, *src); 64 | } 65 | } 66 | #endif 67 | 68 | #ifdef WITH_SSE2 69 | /** 70 | * \brief Perform a left shift on a 128 bit value. 71 | */ 72 | static inline __m128i FN_ATTRIBUTES_SSE2 mm128_shift_left(__m128i data, unsigned int count) { 73 | if (!count) { 74 | return data; 75 | } 76 | 77 | __m128i carry = _mm_bslli_si128(data, 8); 78 | /* if (count >= 64) { 79 | return _mm_slli_epi64(carry, count - 64); 80 | } */ 81 | carry = _mm_srli_epi64(carry, 64 - count); 82 | data = _mm_slli_epi64(data, count); 83 | return _mm_or_si128(data, carry); 84 | } 85 | 86 | /** 87 | * \brief Perform a right shift on a 128 bit value. 88 | */ 89 | static inline __m128i FN_ATTRIBUTES_SSE2 mm128_shift_right(__m128i data, unsigned int count) { 90 | if (!count) { 91 | return data; 92 | } 93 | 94 | __m128i carry = _mm_bsrli_si128(data, 8); 95 | /* if (count >= 64) { 96 | return _mm_srli_epi64(carry, count - 64); 97 | } */ 98 | carry = _mm_slli_epi64(carry, 64 - count); 99 | data = _mm_srli_epi64(data, count); 100 | return _mm_or_si128(data, carry); 101 | } 102 | 103 | /** 104 | * \brief Computes dst ^= src for multiple 128 values and stores the result again. 105 | */ 106 | static inline void FN_ATTRIBUTES_SSE2_NP mm128_xor_region(__m128i* restrict dst, 107 | __m128i const* restrict src, 108 | unsigned int count) { 109 | for (unsigned int i = count; i; --i, ++dst, ++src) { 110 | *dst = _mm_xor_si128(*dst, *src); 111 | } 112 | } 113 | #endif 114 | 115 | #endif 116 | -------------------------------------------------------------------------------- /hashing_util.c: -------------------------------------------------------------------------------- 1 | #include "hashing_util.h" 2 | #include "mpc_lowmc.h" 3 | 4 | #include 5 | 6 | #if COMMITMENT_LENGTH == SHA256_DIGEST_LENGTH 7 | typedef SHA256_CTX commitment_ctx; 8 | #define commitment_init SHA256_Init 9 | #define commitment_update SHA256_Update 10 | #define commitment_final SHA256_Final 11 | #elif COMMITMENT_LENGTH == SHA368_DIGEST_LENGTH 12 | typedef SHA386_CTX commitment_ctx; 13 | #define commitment_init SHA386_Init 14 | #define commitment_update SHA386_Update 15 | #define commitment_final SHA386_Final 16 | #elif COMMITMENT_LENGTH == SHA512_DIGEST_LENGTH 17 | typedef SHA512_CTX commitment_ctx; 18 | #define commitment_init SHA512_Init 19 | #define commitment_update SHA512_Update 20 | #define commitment_final SHA512_Final 21 | #endif 22 | 23 | static void commit_mzd(commitment_ctx* ctx, mzd_t const* v) { 24 | commitment_update(ctx, CONST_FIRST_ROW(v), sizeof(word) * v->width * v->nrows); 25 | } 26 | 27 | #if COMMITMENT_LENGTH == SHA256_DIGEST_LENGTH 28 | #define hash_mzd commit_mzd 29 | #else 30 | static void hash_mzd(SHA256_CTX* ctx, mzd_t const* v) { 31 | SHA256_Update(ctx, CONST_FIRST_ROW(v), sizeof(word) * v->width * v->nrows); 32 | } 33 | #endif 34 | 35 | void H(const unsigned char k[PRNG_KEYSIZE], mzd_t* y[SC_PROOF], const view_t* v, unsigned vidx, 36 | unsigned vcnt, const unsigned char r[COMMITMENT_RAND_LENGTH], 37 | unsigned char hash[COMMITMENT_LENGTH]) { 38 | commitment_ctx ctx; 39 | commitment_init(&ctx); 40 | commitment_update(&ctx, k, PRNG_KEYSIZE); 41 | 42 | for (unsigned i = 0; i < SC_PROOF; ++i) { 43 | commit_mzd(&ctx, y[i]); 44 | } 45 | for (unsigned i = 0; i < vcnt; ++i) { 46 | commit_mzd(&ctx, v[i].s[vidx]); 47 | } 48 | 49 | commitment_update(&ctx, r, COMMITMENT_RAND_LENGTH); 50 | commitment_final(hash, &ctx); 51 | } 52 | 53 | static void H3_compute(unsigned char hash[SHA256_DIGEST_LENGTH], unsigned char* ch) { 54 | // Pick bits from hash 55 | unsigned char* eof = ch + NUM_ROUNDS; 56 | unsigned int bitTracker = 0; 57 | while (ch < eof) { 58 | if (bitTracker >= SHA256_DIGEST_LENGTH * 8) { 59 | SHA256_CTX ctx; 60 | SHA256_Init(&ctx); 61 | SHA256_Update(&ctx, hash, SHA256_DIGEST_LENGTH); 62 | SHA256_Final(hash, &ctx); 63 | bitTracker = 0; 64 | } 65 | 66 | unsigned char twobits = (hash[bitTracker >> 3] >> (bitTracker & 0x7)) & 0x3; 67 | if (twobits != 0x3) { 68 | *ch++ = twobits; 69 | } 70 | bitTracker += 2; 71 | } 72 | } 73 | 74 | void fis_H3_verify(unsigned char const h[NUM_ROUNDS][2][COMMITMENT_LENGTH], 75 | unsigned char const hp[NUM_ROUNDS][COMMITMENT_LENGTH], 76 | unsigned char const ch_in[(NUM_ROUNDS + 3) / 4], const uint8_t* m, size_t m_len, 77 | unsigned char* ch) { 78 | SHA256_CTX ctx; 79 | SHA256_Init(&ctx); 80 | 81 | for (unsigned i = 0; i < NUM_ROUNDS; i++) { 82 | switch (getChAt(ch_in, i)) { 83 | case 0: { 84 | SHA256_Update(&ctx, h[i], 2 * COMMITMENT_LENGTH); 85 | SHA256_Update(&ctx, hp[i], COMMITMENT_LENGTH); 86 | break; 87 | } 88 | case 1: { 89 | SHA256_Update(&ctx, hp[i], COMMITMENT_LENGTH); 90 | SHA256_Update(&ctx, h[i], 2 * COMMITMENT_LENGTH); 91 | break; 92 | } 93 | default: { 94 | SHA256_Update(&ctx, h[i][1], COMMITMENT_LENGTH); 95 | SHA256_Update(&ctx, hp[i], COMMITMENT_LENGTH); 96 | SHA256_Update(&ctx, h[i][0], COMMITMENT_LENGTH); 97 | break; 98 | } 99 | } 100 | } 101 | SHA256_Update(&ctx, m, m_len); 102 | 103 | unsigned char hash[SHA256_DIGEST_LENGTH]; 104 | SHA256_Final(hash, &ctx); 105 | H3_compute(hash, ch); 106 | } 107 | 108 | void fis_H3(unsigned char const h[NUM_ROUNDS][SC_PROOF][COMMITMENT_LENGTH], const uint8_t* m, 109 | size_t m_len, unsigned char* ch) { 110 | 111 | unsigned char hash[SHA256_DIGEST_LENGTH]; 112 | SHA256_CTX ctx; 113 | SHA256_Init(&ctx); 114 | SHA256_Update(&ctx, h, SC_PROOF * COMMITMENT_LENGTH * NUM_ROUNDS); 115 | SHA256_Update(&ctx, m, m_len); 116 | SHA256_Final(hash, &ctx); 117 | 118 | H3_compute(hash, ch); 119 | } 120 | -------------------------------------------------------------------------------- /timing/pq-lowmc-inst-384-384-384.txt: -------------------------------------------------------------------------------- 1 | m: 126 blocksize: 384 ANDdepth: 25 ANDs/bit: 24.61 2 | m: 124 blocksize: 384 ANDdepth: 25 ANDs/bit: 24.22 3 | m: 122 blocksize: 384 ANDdepth: 25 ANDs/bit: 23.83 4 | m: 120 blocksize: 384 ANDdepth: 25 ANDs/bit: 23.44 5 | m: 118 blocksize: 384 ANDdepth: 25 ANDs/bit: 23.05 6 | m: 116 blocksize: 384 ANDdepth: 25 ANDs/bit: 22.66 7 | m: 114 blocksize: 384 ANDdepth: 25 ANDs/bit: 22.27 8 | m: 112 blocksize: 384 ANDdepth: 25 ANDs/bit: 21.88 9 | m: 110 blocksize: 384 ANDdepth: 25 ANDs/bit: 21.48 10 | m: 108 blocksize: 384 ANDdepth: 25 ANDs/bit: 21.09 11 | m: 106 blocksize: 384 ANDdepth: 25 ANDs/bit: 20.7 12 | m: 104 blocksize: 384 ANDdepth: 25 ANDs/bit: 20.31 13 | m: 102 blocksize: 384 ANDdepth: 25 ANDs/bit: 19.92 14 | m: 100 blocksize: 384 ANDdepth: 25 ANDs/bit: 19.53 15 | m: 98 blocksize: 384 ANDdepth: 25 ANDs/bit: 19.14 16 | m: 96 blocksize: 384 ANDdepth: 25 ANDs/bit: 18.75 17 | m: 94 blocksize: 384 ANDdepth: 25 ANDs/bit: 18.36 18 | m: 92 blocksize: 384 ANDdepth: 25 ANDs/bit: 17.97 19 | m: 90 blocksize: 384 ANDdepth: 25 ANDs/bit: 17.58 20 | m: 88 blocksize: 384 ANDdepth: 25 ANDs/bit: 17.19 21 | m: 86 blocksize: 384 ANDdepth: 25 ANDs/bit: 16.8 22 | m: 84 blocksize: 384 ANDdepth: 25 ANDs/bit: 16.41 23 | m: 82 blocksize: 384 ANDdepth: 25 ANDs/bit: 16.02 24 | m: 80 blocksize: 384 ANDdepth: 25 ANDs/bit: 15.62 25 | m: 78 blocksize: 384 ANDdepth: 25 ANDs/bit: 15.23 26 | m: 76 blocksize: 384 ANDdepth: 25 ANDs/bit: 14.84 27 | m: 74 blocksize: 384 ANDdepth: 25 ANDs/bit: 14.45 28 | m: 72 blocksize: 384 ANDdepth: 26 ANDs/bit: 14.62 29 | m: 70 blocksize: 384 ANDdepth: 26 ANDs/bit: 14.22 30 | m: 68 blocksize: 384 ANDdepth: 26 ANDs/bit: 13.81 31 | m: 66 blocksize: 384 ANDdepth: 26 ANDs/bit: 13.41 32 | m: 64 blocksize: 384 ANDdepth: 26 ANDs/bit: 13.0 33 | m: 62 blocksize: 384 ANDdepth: 27 ANDs/bit: 13.08 34 | m: 60 blocksize: 384 ANDdepth: 27 ANDs/bit: 12.66 35 | m: 58 blocksize: 384 ANDdepth: 27 ANDs/bit: 12.23 36 | m: 56 blocksize: 384 ANDdepth: 27 ANDs/bit: 11.81 37 | m: 54 blocksize: 384 ANDdepth: 27 ANDs/bit: 11.39 38 | m: 52 blocksize: 384 ANDdepth: 27 ANDs/bit: 10.97 39 | m: 50 blocksize: 384 ANDdepth: 28 ANDs/bit: 10.94 40 | m: 48 blocksize: 384 ANDdepth: 29 ANDs/bit: 10.88 41 | m: 46 blocksize: 384 ANDdepth: 29 ANDs/bit: 10.42 42 | m: 44 blocksize: 384 ANDdepth: 29 ANDs/bit: 9.97 43 | m: 42 blocksize: 384 ANDdepth: 30 ANDs/bit: 9.84 44 | m: 40 blocksize: 384 ANDdepth: 30 ANDs/bit: 9.38 45 | m: 38 blocksize: 384 ANDdepth: 30 ANDs/bit: 8.91 46 | m: 36 blocksize: 384 ANDdepth: 32 ANDs/bit: 9.0 47 | m: 34 blocksize: 384 ANDdepth: 32 ANDs/bit: 8.5 48 | m: 32 blocksize: 384 ANDdepth: 32 ANDs/bit: 8.0 49 | m: 30 blocksize: 384 ANDdepth: 33 ANDs/bit: 7.73 50 | m: 28 blocksize: 384 ANDdepth: 35 ANDs/bit: 7.66 51 | m: 26 blocksize: 384 ANDdepth: 36 ANDs/bit: 7.31 52 | m: 24 blocksize: 384 ANDdepth: 38 ANDs/bit: 7.12 53 | m: 22 blocksize: 384 ANDdepth: 39 ANDs/bit: 6.7 54 | m: 20 blocksize: 384 ANDdepth: 41 ANDs/bit: 6.41 55 | m: 18 blocksize: 384 ANDdepth: 44 ANDs/bit: 6.19 56 | m: 16 blocksize: 384 ANDdepth: 49 ANDs/bit: 6.12 57 | m: 14 blocksize: 384 ANDdepth: 55 ANDs/bit: 6.02 58 | m: 12 blocksize: 384 ANDdepth: 62 ANDs/bit: 5.81 59 | m: 10 blocksize: 384 ANDdepth: 73 ANDs/bit: 5.7 60 | m: 8 blocksize: 384 ANDdepth: 90 ANDs/bit: 5.62 61 | m: 6 blocksize: 384 ANDdepth: 117 ANDs/bit: 5.48 62 | m: 4 blocksize: 384 ANDdepth: 172 ANDs/bit: 5.38 63 | -------------------------------------------------------------------------------- /mzd_additional.h: -------------------------------------------------------------------------------- 1 | #ifndef MZD_ADDITIONAL_H 2 | #define MZD_ADDITIONAL_H 3 | 4 | #include "parameters.h" 5 | #include "randomness.h" 6 | 7 | #include 8 | #include 9 | 10 | /** 11 | * Modified mzd_init calling malloc less often. Do not pass mzd_t instances 12 | * initialized with this function to mzd_free. 13 | */ 14 | mzd_t* mzd_local_init_ex(rci_t r, rci_t c, bool clear) __attribute__((assume_aligned(32))); 15 | 16 | #define mzd_local_init(r, c) mzd_local_init_ex(r, c, true) 17 | 18 | /** 19 | * Modified mzd_free for mzd_local_init. 20 | */ 21 | void mzd_local_free(mzd_t* v); 22 | /** 23 | * Initialize multiple mzd_t instances using one large enough memory block. 24 | */ 25 | void mzd_local_init_multiple_ex(mzd_t** dst, size_t n, rci_t r, rci_t c, bool clear) 26 | __attribute__((nonnull(1))); 27 | 28 | #define mzd_local_init_multiple(dst, n, r, c) mzd_local_init_multiple_ex(dst, n, r, c, true) 29 | 30 | /** 31 | * mzd_free for mzd_local_init_multiple. 32 | */ 33 | void mzd_local_free_multiple(mzd_t** vs); 34 | /** 35 | * Improved mzd_copy for specific memory layouts. 36 | */ 37 | mzd_t* mzd_local_copy(mzd_t* dst, mzd_t const* src) __attribute__((nonnull(2))); 38 | 39 | void mzd_local_clear(mzd_t* c) __attribute__((nonnull)); 40 | 41 | /** 42 | * Initializes a random vector 43 | * 44 | * \param n the length of the vector 45 | */ 46 | mzd_t* mzd_init_random_vector(rci_t n); 47 | 48 | mzd_t* mzd_init_random_vector_prng(rci_t n, aes_prng_t* aes_prng); 49 | 50 | void mzd_randomize_ssl(mzd_t* val) __attribute__((nonnull(1))); 51 | 52 | void mzd_randomize_from_seed(mzd_t* vector, const unsigned char key[16]) __attribute__((nonnull)); 53 | 54 | mzd_t* mzd_init_random_vector_from_seed(const unsigned char key[16], rci_t n); 55 | 56 | void mzd_randomize_multiple_from_seed(mzd_t** vectors, unsigned int count, 57 | const unsigned char key[PRNG_KEYSIZE]); 58 | 59 | mzd_t** mzd_init_random_vectors_from_seed(const unsigned char key[PRNG_KEYSIZE], rci_t n, 60 | unsigned count); 61 | 62 | void mzd_shift_right(mzd_t* res, mzd_t const* val, unsigned count) __attribute__((nonnull)); 63 | 64 | void mzd_shift_left(mzd_t* res, mzd_t const* val, unsigned count) __attribute__((nonnull)); 65 | 66 | mzd_t* mzd_and(mzd_t* res, mzd_t const* first, mzd_t const* second) __attribute__((nonnull)); 67 | 68 | mzd_t* mzd_xor(mzd_t* res, mzd_t const* first, mzd_t const* second) __attribute__((nonnull)); 69 | 70 | /** 71 | * Compare two vectors for equality. Note that this version is optimized for 72 | * vectors with a multiple of sizeof(word) * 8 columns. 73 | * 74 | * \param first 75 | * first vector 76 | * \param second 77 | * second vector 78 | * \returns true if both vectors are equal, false otherwise. 79 | */ 80 | bool mzd_local_equal(mzd_t const* first, mzd_t const* second) __attribute__((nonnull)); 81 | 82 | /** 83 | * Compute v * A optimized for v being a vector. 84 | */ 85 | mzd_t* mzd_mul_v(mzd_t* c, mzd_t const* v, mzd_t const* At) __attribute__((nonnull)); 86 | 87 | /** 88 | * Compute c + v * A optimized for c and v being vectors. 89 | */ 90 | mzd_t* mzd_addmul_v(mzd_t* c, mzd_t const* v, mzd_t const* At) __attribute__((nonnull)); 91 | 92 | /** 93 | * Compute v * A optimized for v being a vector. 94 | */ 95 | mzd_t* mzd_mul_vl(mzd_t* c, mzd_t const* v, mzd_t const* At) __attribute__((nonnull)); 96 | 97 | /** 98 | * Compute c + v * A optimized for c and v being vectors. 99 | */ 100 | mzd_t* mzd_addmul_vl(mzd_t* c, mzd_t const* v, mzd_t const* At) __attribute__((nonnull)); 101 | 102 | /** 103 | * Compute v * A optimized for v being a vector. 104 | */ 105 | void mzd_mul_vlm(mzd_t** c, mzd_t const* const* v, mzd_t const* At, unsigned int sc) 106 | __attribute__((nonnull)); 107 | 108 | /** 109 | * Compute c + v * A optimized for c and v being vectors. 110 | */ 111 | void mzd_addmul_vlm(mzd_t** c, mzd_t const* const* v, mzd_t const* At, unsigned int sc) 112 | __attribute__((nonnull)); 113 | 114 | /** 115 | * Pre-compute matrices for faster mzd_addmul_v computions. 116 | * 117 | */ 118 | mzd_t* mzd_precompute_matrix_lookup(mzd_t const* A) __attribute__((nonnull)); 119 | 120 | #define FIRST_ROW(v) ((word*)(((void*)(v)) + 64)) 121 | #define CONST_FIRST_ROW(v) ((word const*)(((void const*)(v)) + 64)) 122 | 123 | #endif 124 | -------------------------------------------------------------------------------- /timing/nonce-lowmc-448.txt: -------------------------------------------------------------------------------- 1 | m: 2 blocksize: 448 ANDdepth: 188 ANDs/bit: 2.52 2 | m: 4 blocksize: 448 ANDdepth: 96 ANDs/bit: 2.57 3 | m: 6 blocksize: 448 ANDdepth: 66 ANDs/bit: 2.65 4 | m: 8 blocksize: 448 ANDdepth: 50 ANDs/bit: 2.68 5 | m: 10 blocksize: 448 ANDdepth: 42 ANDs/bit: 2.81 6 | m: 12 blocksize: 448 ANDdepth: 36 ANDs/bit: 2.89 7 | m: 14 blocksize: 448 ANDdepth: 32 ANDs/bit: 3.0 8 | m: 16 blocksize: 448 ANDdepth: 28 ANDs/bit: 3.0 9 | m: 18 blocksize: 448 ANDdepth: 26 ANDs/bit: 3.13 10 | m: 20 blocksize: 448 ANDdepth: 24 ANDs/bit: 3.21 11 | m: 22 blocksize: 448 ANDdepth: 22 ANDs/bit: 3.24 12 | m: 24 blocksize: 448 ANDdepth: 20 ANDs/bit: 3.21 13 | m: 26 blocksize: 448 ANDdepth: 20 ANDs/bit: 3.48 14 | m: 28 blocksize: 448 ANDdepth: 18 ANDs/bit: 3.38 15 | m: 30 blocksize: 448 ANDdepth: 18 ANDs/bit: 3.62 16 | m: 32 blocksize: 448 ANDdepth: 16 ANDs/bit: 3.43 17 | m: 34 blocksize: 448 ANDdepth: 16 ANDs/bit: 3.64 18 | m: 36 blocksize: 448 ANDdepth: 16 ANDs/bit: 3.86 19 | m: 38 blocksize: 448 ANDdepth: 14 ANDs/bit: 3.56 20 | m: 40 blocksize: 448 ANDdepth: 14 ANDs/bit: 3.75 21 | m: 42 blocksize: 448 ANDdepth: 14 ANDs/bit: 3.94 22 | m: 44 blocksize: 448 ANDdepth: 14 ANDs/bit: 4.12 23 | m: 46 blocksize: 448 ANDdepth: 12 ANDs/bit: 3.7 24 | m: 48 blocksize: 448 ANDdepth: 12 ANDs/bit: 3.86 25 | m: 50 blocksize: 448 ANDdepth: 12 ANDs/bit: 4.02 26 | m: 52 blocksize: 448 ANDdepth: 12 ANDs/bit: 4.18 27 | m: 54 blocksize: 448 ANDdepth: 12 ANDs/bit: 4.34 28 | m: 56 blocksize: 448 ANDdepth: 12 ANDs/bit: 4.5 29 | m: 58 blocksize: 448 ANDdepth: 12 ANDs/bit: 4.66 30 | m: 60 blocksize: 448 ANDdepth: 12 ANDs/bit: 4.82 31 | m: 62 blocksize: 448 ANDdepth: 10 ANDs/bit: 4.15 32 | m: 64 blocksize: 448 ANDdepth: 10 ANDs/bit: 4.29 33 | m: 66 blocksize: 448 ANDdepth: 10 ANDs/bit: 4.42 34 | m: 68 blocksize: 448 ANDdepth: 10 ANDs/bit: 4.55 35 | m: 70 blocksize: 448 ANDdepth: 10 ANDs/bit: 4.69 36 | m: 72 blocksize: 448 ANDdepth: 10 ANDs/bit: 4.82 37 | m: 74 blocksize: 448 ANDdepth: 10 ANDs/bit: 4.96 38 | m: 76 blocksize: 448 ANDdepth: 10 ANDs/bit: 5.09 39 | m: 78 blocksize: 448 ANDdepth: 10 ANDs/bit: 5.22 40 | m: 80 blocksize: 448 ANDdepth: 10 ANDs/bit: 5.36 41 | m: 82 blocksize: 448 ANDdepth: 10 ANDs/bit: 5.49 42 | m: 84 blocksize: 448 ANDdepth: 10 ANDs/bit: 5.62 43 | m: 86 blocksize: 448 ANDdepth: 10 ANDs/bit: 5.76 44 | m: 88 blocksize: 448 ANDdepth: 10 ANDs/bit: 5.89 45 | m: 90 blocksize: 448 ANDdepth: 10 ANDs/bit: 6.03 46 | m: 92 blocksize: 448 ANDdepth: 8 ANDs/bit: 4.93 47 | m: 94 blocksize: 448 ANDdepth: 8 ANDs/bit: 5.04 48 | m: 96 blocksize: 448 ANDdepth: 8 ANDs/bit: 5.14 49 | m: 98 blocksize: 448 ANDdepth: 8 ANDs/bit: 5.25 50 | m: 100 blocksize: 448 ANDdepth: 8 ANDs/bit: 5.36 51 | m: 102 blocksize: 448 ANDdepth: 8 ANDs/bit: 5.46 52 | m: 104 blocksize: 448 ANDdepth: 8 ANDs/bit: 5.57 53 | m: 106 blocksize: 448 ANDdepth: 8 ANDs/bit: 5.68 54 | m: 108 blocksize: 448 ANDdepth: 8 ANDs/bit: 5.79 55 | m: 110 blocksize: 448 ANDdepth: 8 ANDs/bit: 5.89 56 | m: 112 blocksize: 448 ANDdepth: 8 ANDs/bit: 6.0 57 | m: 114 blocksize: 448 ANDdepth: 8 ANDs/bit: 6.11 58 | m: 116 blocksize: 448 ANDdepth: 8 ANDs/bit: 6.21 59 | m: 118 blocksize: 448 ANDdepth: 8 ANDs/bit: 6.32 60 | m: 120 blocksize: 448 ANDdepth: 8 ANDs/bit: 6.43 61 | m: 122 blocksize: 448 ANDdepth: 8 ANDs/bit: 6.54 62 | m: 124 blocksize: 448 ANDdepth: 8 ANDs/bit: 6.64 63 | m: 126 blocksize: 448 ANDdepth: 8 ANDs/bit: 6.75 64 | m: 128 blocksize: 448 ANDdepth: 8 ANDs/bit: 6.86 65 | m: 130 blocksize: 448 ANDdepth: 8 ANDs/bit: 6.96 66 | m: 132 blocksize: 448 ANDdepth: 8 ANDs/bit: 7.07 67 | m: 134 blocksize: 448 ANDdepth: 8 ANDs/bit: 7.18 68 | m: 136 blocksize: 448 ANDdepth: 8 ANDs/bit: 7.29 69 | m: 138 blocksize: 448 ANDdepth: 8 ANDs/bit: 7.39 70 | m: 140 blocksize: 448 ANDdepth: 8 ANDs/bit: 7.5 71 | m: 142 blocksize: 448 ANDdepth: 8 ANDs/bit: 7.61 72 | m: 144 blocksize: 448 ANDdepth: 8 ANDs/bit: 7.71 73 | m: 146 blocksize: 448 ANDdepth: 8 ANDs/bit: 7.82 74 | m: 148 blocksize: 448 ANDdepth: 8 ANDs/bit: 7.93 75 | -------------------------------------------------------------------------------- /timing/timing.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import argparse 4 | import subprocess 5 | import os 6 | import numpy as np 7 | import h5py 8 | 9 | 10 | def fix_h5py_strings(strings): 11 | return [s.encode('utf-8') for s in strings] 12 | 13 | 14 | def compute_size(data): 15 | return data[:, 12] / 1024.0 16 | 17 | 18 | def compute_gen(data): 19 | return np.sum(data[:, 0:3], axis=1) / 1000.0 20 | 21 | 22 | def compute_sign(data): 23 | return np.sum(data[:, 3:8], axis=1) / 1000.0 24 | 25 | 26 | def compute_verify(data): 27 | return np.sum(data[:, 8:12], axis=1) / 1000.0 28 | 29 | 30 | def main(): 31 | args = parse_args() 32 | k = args.keysize 33 | with open(args.filename) as f: 34 | all_timings_fs = [] 35 | all_timings_bg = [] 36 | all_timings_fs_median = [] 37 | all_timings_bg_median = [] 38 | all_timings_fs_mean = [] 39 | all_timings_bg_mean = [] 40 | 41 | labels = [] 42 | 43 | for line in f.readlines(): 44 | if line.rstrip(): 45 | m, n, r = get_params(line) 46 | fname = '{0}-{1}'.format(m, r) 47 | labels.append(fname) 48 | 49 | with open(fname, 'w') as timings: 50 | subprocess.Popen([args.executable, str(m), str(n), str(r), str(k), 51 | str(args.iterations)], stdout=timings).wait() 52 | 53 | with open(fname, 'r') as timings: 54 | data = timings.read() 55 | os.unlink(fname) 56 | 57 | mat = [] 58 | for line in data.split('\n'): 59 | line = line.replace('{', '') 60 | line = line.replace('}', '') 61 | if not len(line): 62 | continue 63 | 64 | mat.append(list(map(int, line.split(',')))) 65 | 66 | if args.begol: 67 | fs = np.array(mat[:len(mat) / 2]) 68 | bg = np.array(mat[len(mat) / 2:]) 69 | else: 70 | fs = np.array(mat) 71 | 72 | all_timings_fs.append(np.mean(fs, axis=0)) 73 | 74 | if args.begol: 75 | all_timings_bg.append(np.mean(bg, axis=0)) 76 | 77 | fs_size = compute_size(fs) 78 | fs_gen = compute_gen(fs) 79 | fs_sign = compute_sign(fs) 80 | fs_verify = compute_verify(fs) 81 | all_timings_fs_median.append(list(map(np.median, [fs_gen, fs_sign, fs_verify, 82 | fs_size]))) 83 | all_timings_fs_mean.append(list(map(np.mean, [fs_gen, fs_sign, fs_verify, 84 | fs_size]))) 85 | 86 | if args.begol: 87 | bg_size = compute_size(bg) 88 | bg_gen = compute_gen(bg) 89 | bg_sign = compute_sign(bg) 90 | bg_verify = compute_verify(bg) 91 | all_timings_bg_median.append(list(map(np.median, [bg_gen, bg_sign, bg_verify, 92 | bg_size]))) 93 | all_timings_bg_mean.append(list(map(np.mean, [bg_gen, bg_sign, bg_verify, 94 | bg_size]))) 95 | 96 | with h5py.File('{0}-{1}-{2}.mat'.format(args.prefix, n, k), 'w') as timings: 97 | timings.create_dataset('fis_sum', data=np.array(all_timings_fs)) 98 | timings.create_dataset('fis_median', data=np.array(all_timings_fs_median)) 99 | timings.create_dataset('fis_mean', data=np.array(all_timings_fs_mean)) 100 | if args.begol: 101 | timings.create_dataset('bg_sum', data=np.array(all_timings_bg)) 102 | timings.create_dataset('bg_median', data=np.array(all_timings_bg_median)) 103 | timings.create_dataset('bg_mean', data=np.array(all_timings_bg_mean)) 104 | timings.create_dataset('labels', data=fix_h5py_strings(labels)) 105 | 106 | 107 | def get_params(line): 108 | l = line.split() 109 | d = dict(zip(l[::2], l[1::2])) 110 | m = d['m:'] 111 | n = d['blocksize:'] 112 | r = d['ANDdepth:'] 113 | return m, n, r 114 | 115 | 116 | def parse_args(): 117 | parser = argparse.ArgumentParser(description='Process LowMC Timing Args.') 118 | parser.add_argument('filename', help='the filename of the lowmc instances') 119 | parser.add_argument('-k', '--keysize', help='the LowMC keysize', type=int, 120 | choices=[128, 192, 256, 384, 448, 512], default=128) 121 | parser.add_argument('-x', '--executable', help='the LowMC MPC executable', 122 | default='../mpc_lowmc') 123 | parser.add_argument('-i', '--iterations', help='number of iterations', 124 | default='100') 125 | parser.add_argument('-p', '--prefix', help='prefix of mat files', 126 | default='timings') 127 | parser.add_argument('-b', '--begol', help='alsp time Begol', default=False, 128 | action='store_true') 129 | args = parser.parse_args() 130 | return args 131 | 132 | 133 | if __name__ == '__main__': 134 | main() 135 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #include "hashing_util.h" 2 | #include "io.h" 3 | #include "lowmc.h" 4 | #include "lowmc_pars.h" 5 | #include "mpc.h" 6 | #include "mpc_lowmc.h" 7 | #include "multithreading.h" 8 | #include "mzd_additional.h" 9 | #include "randomness.h" 10 | #include "signature_fis.h" 11 | #include "timing.h" 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #ifndef VERBOSE 18 | static void print_timings(timing_and_size_t* timings, unsigned int iter, unsigned int numt) { 19 | for (unsigned i = 0; i < iter; i++) { 20 | for (unsigned j = 0; j < numt; j++) { 21 | printf("%" PRIu64, timings[i].data[j]); 22 | if (j < numt - 1) 23 | printf(","); 24 | } 25 | printf("\n"); 26 | } 27 | } 28 | #else 29 | static void print_detailed_timings(timing_and_size_t* timings, unsigned int iter) { 30 | for (unsigned int i = 0; i != iter; ++i, ++timings) { 31 | printf("Setup:\n"); 32 | printf("LowMC setup %6" PRIu64 "\n", timings->gen.lowmc_init); 33 | printf("LowMC key generation %6" PRIu64 "\n", timings->gen.keygen); 34 | printf("Public key computation %6" PRIu64 "\n", timings->gen.pubkey); 35 | printf("\n"); 36 | printf("Prove:\n"); 37 | printf("MPC randomess generation %6" PRIu64 "\n", timings->sign.rand); 38 | printf("MPC secret sharing %6" PRIu64 "\n", timings->sign.secret_sharing); 39 | printf("MPC LowMC encryption %6" PRIu64 "\n", timings->sign.lowmc_enc); 40 | printf("Hashing views %6" PRIu64 "\n", timings->sign.views); 41 | printf("Generating challenge %6" PRIu64 "\n", timings->sign.challenge); 42 | printf("\n"); 43 | printf("Verify:\n"); 44 | printf("Recomputing challenge %6" PRIu64 "\n", timings->verify.challenge); 45 | printf("Verifying output shares %6" PRIu64 "\n", timings->verify.output_shares); 46 | printf("Comparing output views %6" PRIu64 "\n", timings->verify.output_views); 47 | printf("Verifying views %6" PRIu64 "\n", timings->verify.verify); 48 | printf("\n"); 49 | } 50 | } 51 | 52 | #endif 53 | 54 | static void parse_args(int params[5], int argc, char** argv) { 55 | if (argc != 6) { 56 | printf("Usage ./mpc_lowmc [Number of SBoxes] [Blocksize] [Rounds] [Keysize] [Numiter]\n"); 57 | exit(-1); 58 | } 59 | params[0] = atoi(argv[1]); 60 | params[1] = atoi(argv[2]); 61 | params[2] = atoi(argv[3]); 62 | params[3] = atoi(argv[4]); 63 | params[4] = atoi(argv[5]); 64 | 65 | if (params[0] * 3 > params[1]) { 66 | printf("Number of S-boxes * 3 exceeds block size!"); 67 | exit(-1); 68 | } 69 | } 70 | 71 | static void fis_sign_verify(int args[5]) { 72 | static const uint8_t m[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 73 | 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}; 74 | 75 | timing_and_size_t* timings_fis = calloc(args[4], sizeof(timing_and_size_t)); 76 | 77 | for (int i = 0; i != args[4]; ++i) { 78 | timing_and_size = &timings_fis[i]; 79 | 80 | public_parameters_t pp; 81 | fis_private_key_t private_key; 82 | fis_public_key_t public_key; 83 | 84 | if (!create_instance(&pp, args[0], args[1], args[2], args[3])) { 85 | printf("Failed to create LowMC instance.\n"); 86 | break; 87 | } 88 | 89 | if (!fis_create_key(&pp, &private_key, &public_key)) { 90 | printf("Failed to create keys.\n"); 91 | destroy_instance(&pp); 92 | break; 93 | } 94 | 95 | fis_signature_t* sig = fis_sign(&pp, &private_key, m, sizeof(m)); 96 | if (sig) { 97 | unsigned len = 0; 98 | unsigned char* data = fis_sig_to_char_array(&pp, sig, &len); 99 | timing_and_size->size = 100 | fis_compute_sig_size(pp.lowmc->m, pp.lowmc->n, pp.lowmc->r, pp.lowmc->k); 101 | fis_free_signature(&pp, sig); 102 | sig = fis_sig_from_char_array(&pp, data); 103 | free(data); 104 | 105 | if (fis_verify(&pp, &public_key, m, sizeof(m), sig)) { 106 | printf("fis_verify: failed\n"); 107 | } 108 | 109 | fis_free_signature(&pp, sig); 110 | } else { 111 | printf("fis_sign: failed\n"); 112 | } 113 | 114 | destroy_instance(&pp); 115 | fis_destroy_key(&private_key, &public_key); 116 | } 117 | 118 | #ifndef VERBOSE 119 | print_timings(timings_fis, args[4], 13); 120 | #else 121 | printf("Fish Signature:\n\n"); 122 | print_detailed_timings(timings_fis, args[4]); 123 | #endif 124 | 125 | free(timings_fis); 126 | } 127 | 128 | int main(int argc, char** argv) { 129 | init_rand_bytes(); 130 | init_EVP(); 131 | openmp_thread_setup(); 132 | 133 | int args[5]; 134 | parse_args(args, argc, argv); 135 | 136 | fis_sign_verify(args); 137 | 138 | openmp_thread_cleanup(); 139 | cleanup_EVP(); 140 | deinit_rand_bytes(); 141 | 142 | return 0; 143 | } 144 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1 FATAL_ERROR) 2 | 3 | # cmake setup 4 | set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") 5 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 6 | 7 | project(picnic C) 8 | 9 | if(NOT CMAKE_BUILD_TYPE) 10 | set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Choose the type of build." FORCE) 11 | endif() 12 | 13 | # set required C standard version 14 | set(CMAKE_C_STANDARD 11) 15 | set(CMAKE_C_STANDARD_REQUIRED ON) 16 | 17 | # required fuctions 18 | include(CheckFunctionExists) 19 | include(CheckCCompilerFlag) 20 | include(CheckIncludeFiles) 21 | include(CheckSymbolExists) 22 | 23 | # required libraries 24 | find_package(OpenSSL REQUIRED) 25 | find_package(m4ri REQUIRED) 26 | set(M4RI_VERSION M4RI_VERSION_STRING) 27 | 28 | # check headers 29 | check_include_files(immintrin.h HAVE_IMMINTRIN_H) 30 | 31 | # check availability of some functions 32 | check_symbol_exists(aligned_alloc stdlib.h HAVE_ALIGNED_ALLOC) 33 | check_symbol_exists(posix_memalign stdlib.h HAVE_POSIX_MEMALIGN) 34 | check_symbol_exists(memalign malloc.h HAVE_MEMALIGN) 35 | 36 | # check supported compiler flags 37 | check_c_compiler_flag(-march=native CC_SUPPORTS_MARCH_NATIVE) 38 | check_c_compiler_flag(-mtune=native CC_SUPPORTS_MTUNE_NATIVE) 39 | check_c_compiler_flag(-O3 CC_SUPPORTS_03) 40 | 41 | # user-settable options 42 | set(WITH_SIMD_OPT ON CACHE BOOL "Enable optimizations via SIMD.") 43 | set(WITH_AVX2 ON CACHE BOOL "Use AVX2 if available.") 44 | set(WITH_SSE2 ON CACHE BOOL "Use SSE2 if available.") 45 | set(WITH_SSE4_1 ON CACHE BOOL "Use SSE4.1 if available.") 46 | set(WITH_MARCH_NATIVE ON CACHE BOOL "Build with -march=native -mtune=native (if supported).") 47 | set(WITH_LTO ON CACHE BOOL "Enable link-time optimization (if supported).") 48 | set(WITH_PQ_PARAMETERS ON CACHE BOOL "Use PQ parameters.") 49 | set(WITH_OPENMP OFF CACHE BOOL "Use OpenMP.") 50 | set(ENABLE_VERBOSE_OUTPUT OFF CACHE BOOL "Enable verbose output.") 51 | 52 | # enable -march=native -mtune=native if supported 53 | if(WITH_MARCH_NATIVE) 54 | if (CC_SUPPORTS_MARCH_NATIVE) 55 | add_compile_options("-march=native") 56 | endif() 57 | if (CC_SUPPORTS_MTUNE_NATIVE) 58 | add_compile_options("-mtune=native") 59 | endif() 60 | endif() 61 | 62 | # enable LTO if supported 63 | if(WITH_LTO) 64 | if ("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_LESS 3.9) 65 | if(CMAKE_COMPILER_IS_GNUCC) 66 | set(CMAKE_AR "gcc-ar") 67 | set(CMAKE_C_ARCHIVE_CREATE " qcs ") 68 | set(CMAKE_C_ARCHIVE_FINISH true) 69 | endif() 70 | 71 | check_c_compiler_flag(-flto CC_SUPPORTS_FLTO) 72 | if(CC_SUPPORTS_FLTO) 73 | add_compile_options(-flto) 74 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto") 75 | endif() 76 | else() 77 | include(CheckIPOSupprt) 78 | check_ipo_support(RESULT LTO_SUPPORTED) 79 | if (LTO_SUPPORTED) 80 | set(CMAKE_INTINTERPROCEDURAL_OPTIMIZATION TRUE) 81 | endif() 82 | endif() 83 | endif() 84 | 85 | # enable OpenMP if supported 86 | if(WITH_OPENMP) 87 | include(FindOpenMP) 88 | if(NOT OPENMP_FOUND) 89 | message(WARNING "OpenMP requested, but not supported.") 90 | else() 91 | add_compile_options("${OpenMP_C_FLAGS}") 92 | endif() 93 | endif() 94 | 95 | # enable -O3 96 | if(WITH_SIMD_OPT AND CC_SUPPORTS_03) 97 | add_compile_options(-O3) 98 | endif() 99 | 100 | configure_file(config.h.in config.h) 101 | include_directories(${CMAKE_CURRENT_BINARY_DIR} compat) 102 | 103 | add_subdirectory(compat) 104 | 105 | set(PICNIC_SOURCES 106 | hashing_util.c 107 | io.c 108 | lowmc.c 109 | lowmc_pars.c 110 | mpc.c 111 | mpc_lowmc.c 112 | multithreading.c 113 | mzd_additional.c 114 | mzd_shared.c 115 | randomness.c 116 | signature_common.c 117 | signature_fis.c 118 | timing.c) 119 | add_library(picnic STATIC ${PICNIC_SOURCES}) 120 | target_link_libraries(picnic OpenSSL::Crypto ${M4RI_LIBRARY} compat) 121 | 122 | target_compile_definitions(picnic PRIVATE HAVE_CONFIG_H) 123 | target_compile_definitions(picnic PRIVATE WITH_DETAILED_TIMING) 124 | if(WITH_SIMD_OPT AND HAVE_IMMINTRIN_H) 125 | target_compile_definitions(picnic PRIVATE WITH_OPT) 126 | target_compile_definitions(picnic PRIVATE NOSCR) 127 | if(WITH_SSE2) 128 | target_compile_definitions(picnic PRIVATE WITH_SSE2) 129 | if(WITH_SSE4_1) 130 | target_compile_definitions(picnic PRIVATE WITH_SSE4_1) 131 | endif() 132 | endif() 133 | if(WITH_AVX2) 134 | target_compile_definitions(picnic PRIVATE WITH_AVX2) 135 | endif() 136 | endif() 137 | if(WITH_PQ_PARAMETERS) 138 | target_compile_definitions(picnic PRIVATE WITH_PQ_PARAMETERS) 139 | endif() 140 | 141 | add_executable(bench main.c) 142 | target_link_libraries(bench picnic) 143 | target_compile_definitions(bench PRIVATE HAVE_CONFIG_H) 144 | if(ENABLE_VERBOSE_OUTPUT) 145 | target_compile_definitions(bench PRIVATE VERBOSE) 146 | endif() 147 | 148 | add_executable(mpc_test mpc_test.c) 149 | target_link_libraries(mpc_test picnic) 150 | target_compile_definitions(mpc_test PRIVATE HAVE_CONFIG_H) 151 | -------------------------------------------------------------------------------- /timing/nonce-lowmc-512.txt: -------------------------------------------------------------------------------- 1 | m: 2 blocksize: 512 ANDdepth: 208 ANDs/bit: 2.44 2 | m: 4 blocksize: 512 ANDdepth: 106 ANDs/bit: 2.48 3 | m: 6 blocksize: 512 ANDdepth: 72 ANDs/bit: 2.53 4 | m: 8 blocksize: 512 ANDdepth: 56 ANDs/bit: 2.62 5 | m: 10 blocksize: 512 ANDdepth: 46 ANDs/bit: 2.7 6 | m: 12 blocksize: 512 ANDdepth: 38 ANDs/bit: 2.67 7 | m: 14 blocksize: 512 ANDdepth: 34 ANDs/bit: 2.79 8 | m: 16 blocksize: 512 ANDdepth: 30 ANDs/bit: 2.81 9 | m: 18 blocksize: 512 ANDdepth: 28 ANDs/bit: 2.95 10 | m: 20 blocksize: 512 ANDdepth: 26 ANDs/bit: 3.05 11 | m: 22 blocksize: 512 ANDdepth: 24 ANDs/bit: 3.09 12 | m: 24 blocksize: 512 ANDdepth: 22 ANDs/bit: 3.09 13 | m: 26 blocksize: 512 ANDdepth: 20 ANDs/bit: 3.05 14 | m: 28 blocksize: 512 ANDdepth: 20 ANDs/bit: 3.28 15 | m: 30 blocksize: 512 ANDdepth: 18 ANDs/bit: 3.16 16 | m: 32 blocksize: 512 ANDdepth: 18 ANDs/bit: 3.38 17 | m: 34 blocksize: 512 ANDdepth: 16 ANDs/bit: 3.19 18 | m: 36 blocksize: 512 ANDdepth: 16 ANDs/bit: 3.38 19 | m: 38 blocksize: 512 ANDdepth: 16 ANDs/bit: 3.56 20 | m: 40 blocksize: 512 ANDdepth: 16 ANDs/bit: 3.75 21 | m: 42 blocksize: 512 ANDdepth: 14 ANDs/bit: 3.45 22 | m: 44 blocksize: 512 ANDdepth: 14 ANDs/bit: 3.61 23 | m: 46 blocksize: 512 ANDdepth: 14 ANDs/bit: 3.77 24 | m: 48 blocksize: 512 ANDdepth: 14 ANDs/bit: 3.94 25 | m: 50 blocksize: 512 ANDdepth: 14 ANDs/bit: 4.1 26 | m: 52 blocksize: 512 ANDdepth: 12 ANDs/bit: 3.66 27 | m: 54 blocksize: 512 ANDdepth: 12 ANDs/bit: 3.8 28 | m: 56 blocksize: 512 ANDdepth: 12 ANDs/bit: 3.94 29 | m: 58 blocksize: 512 ANDdepth: 12 ANDs/bit: 4.08 30 | m: 60 blocksize: 512 ANDdepth: 12 ANDs/bit: 4.22 31 | m: 62 blocksize: 512 ANDdepth: 12 ANDs/bit: 4.36 32 | m: 64 blocksize: 512 ANDdepth: 12 ANDs/bit: 4.5 33 | m: 66 blocksize: 512 ANDdepth: 12 ANDs/bit: 4.64 34 | m: 68 blocksize: 512 ANDdepth: 10 ANDs/bit: 3.98 35 | m: 70 blocksize: 512 ANDdepth: 10 ANDs/bit: 4.1 36 | m: 72 blocksize: 512 ANDdepth: 10 ANDs/bit: 4.22 37 | m: 74 blocksize: 512 ANDdepth: 10 ANDs/bit: 4.34 38 | m: 76 blocksize: 512 ANDdepth: 10 ANDs/bit: 4.45 39 | m: 78 blocksize: 512 ANDdepth: 10 ANDs/bit: 4.57 40 | m: 80 blocksize: 512 ANDdepth: 10 ANDs/bit: 4.69 41 | m: 82 blocksize: 512 ANDdepth: 10 ANDs/bit: 4.8 42 | m: 84 blocksize: 512 ANDdepth: 10 ANDs/bit: 4.92 43 | m: 86 blocksize: 512 ANDdepth: 10 ANDs/bit: 5.04 44 | m: 88 blocksize: 512 ANDdepth: 10 ANDs/bit: 5.16 45 | m: 90 blocksize: 512 ANDdepth: 10 ANDs/bit: 5.27 46 | m: 92 blocksize: 512 ANDdepth: 10 ANDs/bit: 5.39 47 | m: 94 blocksize: 512 ANDdepth: 10 ANDs/bit: 5.51 48 | m: 96 blocksize: 512 ANDdepth: 10 ANDs/bit: 5.62 49 | m: 98 blocksize: 512 ANDdepth: 10 ANDs/bit: 5.74 50 | m: 100 blocksize: 512 ANDdepth: 10 ANDs/bit: 5.86 51 | m: 102 blocksize: 512 ANDdepth: 8 ANDs/bit: 4.78 52 | m: 104 blocksize: 512 ANDdepth: 8 ANDs/bit: 4.88 53 | m: 106 blocksize: 512 ANDdepth: 8 ANDs/bit: 4.97 54 | m: 108 blocksize: 512 ANDdepth: 8 ANDs/bit: 5.06 55 | m: 110 blocksize: 512 ANDdepth: 8 ANDs/bit: 5.16 56 | m: 112 blocksize: 512 ANDdepth: 8 ANDs/bit: 5.25 57 | m: 114 blocksize: 512 ANDdepth: 8 ANDs/bit: 5.34 58 | m: 116 blocksize: 512 ANDdepth: 8 ANDs/bit: 5.44 59 | m: 118 blocksize: 512 ANDdepth: 8 ANDs/bit: 5.53 60 | m: 120 blocksize: 512 ANDdepth: 8 ANDs/bit: 5.62 61 | m: 122 blocksize: 512 ANDdepth: 8 ANDs/bit: 5.72 62 | m: 124 blocksize: 512 ANDdepth: 8 ANDs/bit: 5.81 63 | m: 126 blocksize: 512 ANDdepth: 8 ANDs/bit: 5.91 64 | m: 128 blocksize: 512 ANDdepth: 8 ANDs/bit: 6.0 65 | m: 130 blocksize: 512 ANDdepth: 8 ANDs/bit: 6.09 66 | m: 132 blocksize: 512 ANDdepth: 8 ANDs/bit: 6.19 67 | m: 134 blocksize: 512 ANDdepth: 8 ANDs/bit: 6.28 68 | m: 136 blocksize: 512 ANDdepth: 8 ANDs/bit: 6.38 69 | m: 138 blocksize: 512 ANDdepth: 8 ANDs/bit: 6.47 70 | m: 140 blocksize: 512 ANDdepth: 8 ANDs/bit: 6.56 71 | m: 142 blocksize: 512 ANDdepth: 8 ANDs/bit: 6.66 72 | m: 144 blocksize: 512 ANDdepth: 8 ANDs/bit: 6.75 73 | m: 146 blocksize: 512 ANDdepth: 8 ANDs/bit: 6.84 74 | m: 148 blocksize: 512 ANDdepth: 8 ANDs/bit: 6.94 75 | m: 150 blocksize: 512 ANDdepth: 8 ANDs/bit: 7.03 76 | m: 152 blocksize: 512 ANDdepth: 8 ANDs/bit: 7.12 77 | m: 154 blocksize: 512 ANDdepth: 8 ANDs/bit: 7.22 78 | m: 156 blocksize: 512 ANDdepth: 8 ANDs/bit: 7.31 79 | m: 158 blocksize: 512 ANDdepth: 8 ANDs/bit: 7.41 80 | m: 160 blocksize: 512 ANDdepth: 8 ANDs/bit: 7.5 81 | m: 162 blocksize: 512 ANDdepth: 8 ANDs/bit: 7.59 82 | m: 164 blocksize: 512 ANDdepth: 8 ANDs/bit: 7.69 83 | m: 166 blocksize: 512 ANDdepth: 8 ANDs/bit: 7.78 84 | m: 168 blocksize: 512 ANDdepth: 8 ANDs/bit: 7.88 85 | -------------------------------------------------------------------------------- /mpc_test.c: -------------------------------------------------------------------------------- 1 | #ifdef HAVE_CONFIG_H 2 | #include 3 | #endif 4 | 5 | #include 6 | 7 | #include "mpc_test.h" 8 | 9 | #include "mpc.h" 10 | #include "mzd_additional.h" 11 | #include "multithreading.h" 12 | 13 | static void test_mpc_share(void) { 14 | mzd_t* t1 = mzd_init_random_vector(10); 15 | mzd_t** s1 = mpc_init_share_vector(t1); 16 | mzd_t* t1cmb = mpc_reconstruct_from_share(NULL, s1); 17 | 18 | if (mzd_cmp(t1, t1cmb) == 0) 19 | printf("Share test successful.\n"); 20 | 21 | mzd_local_free(t1); 22 | mzd_local_free_multiple(s1); 23 | mzd_local_free(t1cmb); 24 | } 25 | 26 | static void test_mpc_add(void) { 27 | mzd_t* t1 = mzd_init_random_vector(10); 28 | mzd_t* t2 = mzd_init_random_vector(10); 29 | mzd_t* res = mzd_add(0, t1, t2); 30 | 31 | mzd_t** s1 = mpc_init_share_vector(t1); 32 | mzd_t** s2 = mpc_init_share_vector(t2); 33 | mzd_t** ress = mpc_init_empty_share_vector(10, 3); 34 | mpc_add(ress, s1, s2, 3); 35 | 36 | mzd_t* cmp = mpc_reconstruct_from_share(NULL, ress); 37 | 38 | if (mzd_cmp(res, cmp) == 0) 39 | printf("Shared add test successful.\n"); 40 | 41 | mzd_local_free(t1); 42 | mzd_local_free(t2); 43 | mzd_free(res); 44 | mzd_local_free_multiple(s1); 45 | mzd_local_free_multiple(s2); 46 | mzd_local_free_multiple(ress); 47 | mzd_local_free(cmp); 48 | } 49 | 50 | void test_mzd_local_equal(void) { 51 | for (unsigned int i = 0; i < 10; ++i) { 52 | mzd_t* a = mzd_init_random_vector((i + 1) * 64); 53 | mzd_t* b = mzd_local_copy(NULL, a); 54 | 55 | if (mzd_local_equal(a, b)) { 56 | printf("equal: ok [%u]\n", (i + 1) * 64); 57 | } 58 | 59 | b = mzd_xor(b, b, a); 60 | if (mzd_local_equal(a, b)) 61 | printf("equal: ok [%u]\n", (i + 1) * 64); 62 | 63 | mzd_local_free(a); 64 | mzd_local_free(b); 65 | } 66 | } 67 | 68 | static void test_mzd_mul(void) { 69 | for (unsigned int i = 1; i <= 10; ++i) { 70 | for (unsigned int j = 1; j <= 10; ++j) { 71 | mzd_t* A = mzd_local_init(i * 64, j * 64); 72 | mzd_t* v = mzd_local_init(1, i * 64); 73 | mzd_t* c = mzd_local_init(1, j * 64); 74 | 75 | mzd_randomize_ssl(A); 76 | mzd_randomize_ssl(v); 77 | mzd_randomize_ssl(c); 78 | 79 | mzd_t* c2 = mzd_local_copy(NULL, c); 80 | 81 | for (unsigned int k = 0; k < 3; ++k) { 82 | mzd_t* r = mzd_mul_v(c, v, A); 83 | mzd_t* r2 = mzd_mul(c2, v, A, __M4RI_STRASSEN_MUL_CUTOFF); 84 | 85 | if (mzd_cmp(r, r2) != 0) { 86 | printf("mul: fail [%u x %u]\n", i * 64, j * 64); 87 | printf("r = "); 88 | mzd_print(r); 89 | printf("r2 = "); 90 | mzd_print(r2); 91 | } 92 | } 93 | 94 | mzd_local_free(A); 95 | mzd_local_free(v); 96 | mzd_local_free(c); 97 | 98 | mzd_local_free(c2); 99 | } 100 | } 101 | } 102 | 103 | #ifdef WITH_OPT 104 | #include "simd.h" 105 | #endif 106 | 107 | static void test_mzd_shift(void) { 108 | #ifdef WITH_OPT 109 | #ifdef WITH_SSE2 110 | if (CPU_SUPPORTS_SSE2) { 111 | mzd_t* v = mzd_local_init(1, 128); 112 | mzd_t* w = mzd_local_copy(NULL, v); 113 | mzd_t* r = mzd_local_copy(NULL, v); 114 | __m128i* wr = __builtin_assume_aligned(FIRST_ROW(w), 16); 115 | 116 | for (unsigned int i = 0; i < 32; ++i) { 117 | mzd_randomize_ssl(v); 118 | mzd_local_copy(w, v); 119 | 120 | mzd_shift_left(r, v, i); 121 | *wr = mm128_shift_left(*wr, i); 122 | 123 | if (mzd_cmp(r, w) != 0) { 124 | printf("lshift fail\nv = "); 125 | mzd_print(v); 126 | printf("r = "); 127 | mzd_print(r); 128 | printf("w = "); 129 | mzd_print(w); 130 | } 131 | } 132 | 133 | for (unsigned int i = 0; i < 32; ++i) { 134 | mzd_randomize_ssl(v); 135 | mzd_local_copy(w, v); 136 | 137 | mzd_shift_right(r, v, i); 138 | *wr = mm128_shift_right(*wr, i); 139 | 140 | if (mzd_cmp(r, w) != 0) { 141 | printf("rshift fail\nv = "); 142 | mzd_print(v); 143 | printf("r = "); 144 | mzd_print(r); 145 | printf("w = "); 146 | mzd_print(w); 147 | } 148 | } 149 | 150 | mzd_local_free(w); 151 | mzd_local_free(v); 152 | mzd_local_free(r); 153 | } 154 | #endif 155 | #ifdef WITH_AVX2 156 | if (CPU_SUPPORTS_AVX2) { 157 | mzd_t* v = mzd_local_init(1, 256); 158 | mzd_t* w = mzd_local_copy(NULL, v); 159 | mzd_t* r = mzd_local_copy(NULL, v); 160 | __m256i* wr = __builtin_assume_aligned(FIRST_ROW(w), 32); 161 | 162 | for (unsigned int i = 0; i < 32; ++i) { 163 | mzd_randomize_ssl(v); 164 | mzd_local_copy(w, v); 165 | 166 | mzd_shift_left(r, v, i); 167 | *wr = mm256_shift_left(*wr, i); 168 | 169 | if (mzd_cmp(r, w) != 0) { 170 | printf("lshift fail\nv = "); 171 | mzd_print(v); 172 | printf("r = "); 173 | mzd_print(r); 174 | printf("w = "); 175 | mzd_print(w); 176 | } 177 | } 178 | 179 | for (unsigned int i = 0; i < 32; ++i) { 180 | mzd_randomize_ssl(v); 181 | mzd_local_copy(w, v); 182 | 183 | mzd_shift_right(r, v, i); 184 | *wr = mm256_shift_right(*wr, i); 185 | 186 | if (mzd_cmp(r, w) != 0) { 187 | printf("rshift fail\nv = "); 188 | mzd_print(v); 189 | printf("r = "); 190 | mzd_print(r); 191 | printf("w = "); 192 | mzd_print(w); 193 | } 194 | } 195 | 196 | mzd_local_free(w); 197 | mzd_local_free(v); 198 | mzd_local_free(r); 199 | } 200 | #endif 201 | #endif 202 | } 203 | 204 | void run_tests(void) { 205 | test_mpc_share(); 206 | test_mpc_add(); 207 | test_mzd_local_equal(); 208 | test_mzd_mul(); 209 | test_mzd_shift(); 210 | } 211 | 212 | int main() { 213 | init_rand_bytes(); 214 | init_EVP(); 215 | openmp_thread_setup(); 216 | 217 | run_tests(); 218 | 219 | openmp_thread_cleanup(); 220 | cleanup_EVP(); 221 | deinit_rand_bytes(); 222 | 223 | return 0; 224 | } 225 | -------------------------------------------------------------------------------- /lowmc.c: -------------------------------------------------------------------------------- 1 | #include "lowmc.h" 2 | #include "lowmc_pars.h" 3 | #include "mzd_additional.h" 4 | 5 | #ifdef WITH_OPT 6 | #include "simd.h" 7 | #endif 8 | 9 | static void sbox_layer_bitsliced(mzd_t* out, mzd_t* in, rci_t m, mask_t const* mask) { 10 | mzd_and(out, in, mask->mask); 11 | 12 | mzd_t* buffer[6] = {NULL}; 13 | mzd_local_init_multiple_ex(buffer, 6, 1, in->ncols, false); 14 | 15 | mzd_t* x0m = mzd_and(buffer[0], mask->x0, in); 16 | mzd_t* x1m = mzd_and(buffer[1], mask->x1, in); 17 | mzd_t* x2m = mzd_and(buffer[2], mask->x2, in); 18 | 19 | mzd_shift_left(x0m, x0m, 2); 20 | mzd_shift_left(x1m, x1m, 1); 21 | 22 | mzd_t* t0 = mzd_and(buffer[3], x1m, x2m); 23 | mzd_t* t1 = mzd_and(buffer[4], x0m, x2m); 24 | mzd_t* t2 = mzd_and(buffer[5], x0m, x1m); 25 | 26 | mzd_xor(t0, t0, x0m); 27 | 28 | mzd_xor(t1, t1, x0m); 29 | mzd_xor(t1, t1, x1m); 30 | 31 | mzd_xor(t2, t2, x0m); 32 | mzd_xor(t2, t2, x1m); 33 | mzd_xor(t2, t2, x2m); 34 | 35 | mzd_shift_right(t0, t0, 2); 36 | mzd_shift_right(t1, t1, 1); 37 | 38 | mzd_xor(out, out, t2); 39 | mzd_xor(out, out, t0); 40 | mzd_xor(out, out, t1); 41 | 42 | mzd_local_free_multiple(buffer); 43 | } 44 | 45 | #ifdef WITH_OPT 46 | #ifdef WITH_SSE2 47 | __attribute__((target("sse2"))) static void sbox_layer_sse(mzd_t* out, mzd_t* in, 48 | mask_t const* mask) { 49 | __m128i const* ip = __builtin_assume_aligned(CONST_FIRST_ROW(in), 16); 50 | __m128i const min = *ip; 51 | 52 | __m128i const* x0p = __builtin_assume_aligned(CONST_FIRST_ROW(mask->x0), 16); 53 | __m128i const* x1p = __builtin_assume_aligned(CONST_FIRST_ROW(mask->x1), 16); 54 | __m128i const* x2p = __builtin_assume_aligned(CONST_FIRST_ROW(mask->x2), 16); 55 | 56 | __m128i x0m = _mm_and_si128(min, *x0p); 57 | __m128i x1m = _mm_and_si128(min, *x1p); 58 | __m128i x2m = _mm_and_si128(min, *x2p); 59 | 60 | x0m = mm128_shift_left(x0m, 2); 61 | x1m = mm128_shift_left(x1m, 1); 62 | 63 | __m128i t0 = _mm_and_si128(x1m, x2m); 64 | __m128i t1 = _mm_and_si128(x0m, x2m); 65 | __m128i t2 = _mm_and_si128(x0m, x1m); 66 | 67 | t0 = _mm_xor_si128(t0, x0m); 68 | 69 | x0m = _mm_xor_si128(x0m, x1m); 70 | t1 = _mm_xor_si128(t1, x0m); 71 | 72 | t2 = _mm_xor_si128(t2, x0m); 73 | t2 = _mm_xor_si128(t2, x2m); 74 | 75 | t0 = mm128_shift_right(t0, 2); 76 | t1 = mm128_shift_right(t1, 1); 77 | 78 | __m128i const* xmp = __builtin_assume_aligned(CONST_FIRST_ROW(mask->mask), 16); 79 | __m128i* op = __builtin_assume_aligned(FIRST_ROW(out), 16); 80 | 81 | __m128i mout = _mm_and_si128(min, *xmp); 82 | 83 | mout = _mm_xor_si128(mout, t2); 84 | mout = _mm_xor_si128(mout, t1); 85 | *op = _mm_xor_si128(mout, t0); 86 | } 87 | #endif 88 | 89 | #ifdef WITH_AVX2 90 | /** 91 | * AVX2 version of LowMC. It assumes that mzd_t's row[0] is always 32 byte 92 | * aligned. 93 | */ 94 | __attribute__((target("avx2"))) static void sbox_layer_avx(mzd_t* out, mzd_t* in, 95 | mask_t const* mask) { 96 | __m256i const* ip = __builtin_assume_aligned(CONST_FIRST_ROW(in), 32); 97 | __m256i const min = *ip; 98 | 99 | __m256i const* x0p = __builtin_assume_aligned(CONST_FIRST_ROW(mask->x0), 32); 100 | __m256i const* x1p = __builtin_assume_aligned(CONST_FIRST_ROW(mask->x1), 32); 101 | __m256i const* x2p = __builtin_assume_aligned(CONST_FIRST_ROW(mask->x2), 32); 102 | 103 | __m256i x0m = _mm256_and_si256(min, *x0p); 104 | __m256i x1m = _mm256_and_si256(min, *x1p); 105 | __m256i x2m = _mm256_and_si256(min, *x2p); 106 | 107 | x0m = mm256_shift_left(x0m, 2); 108 | x1m = mm256_shift_left(x1m, 1); 109 | 110 | __m256i t0 = _mm256_and_si256(x1m, x2m); 111 | __m256i t1 = _mm256_and_si256(x0m, x2m); 112 | __m256i t2 = _mm256_and_si256(x0m, x1m); 113 | 114 | t0 = _mm256_xor_si256(t0, x0m); 115 | 116 | x0m = _mm256_xor_si256(x0m, x1m); 117 | t1 = _mm256_xor_si256(t1, x0m); 118 | 119 | t2 = _mm256_xor_si256(t2, x0m); 120 | t2 = _mm256_xor_si256(t2, x2m); 121 | 122 | t0 = mm256_shift_right(t0, 2); 123 | t1 = mm256_shift_right(t1, 1); 124 | 125 | __m256i const* xmp = __builtin_assume_aligned(CONST_FIRST_ROW(mask->mask), 32); 126 | __m256i* op = __builtin_assume_aligned(FIRST_ROW(out), 32); 127 | 128 | __m256i mout = _mm256_and_si256(min, *xmp); 129 | 130 | mout = _mm256_xor_si256(mout, t2); 131 | mout = _mm256_xor_si256(mout, t1); 132 | *op = _mm256_xor_si256(mout, t0); 133 | } 134 | #endif 135 | #endif 136 | 137 | mzd_t* lowmc_call(lowmc_t const* lowmc, lowmc_key_t const* lowmc_key, mzd_t const* p) { 138 | if (p->ncols > lowmc->n) { 139 | printf("p larger than block size!\n"); 140 | return NULL; 141 | } 142 | if (p->nrows != 1) { 143 | printf("p needs to have exactly one row!\n"); 144 | } 145 | 146 | mzd_t* x = mzd_local_init_ex(1, lowmc->n, false); 147 | mzd_t* y = mzd_local_init_ex(1, lowmc->n, false); 148 | 149 | mzd_local_copy(x, p); 150 | #ifdef NOSCR 151 | mzd_addmul_vl(x, lowmc_key, lowmc->k0_lookup); 152 | #else 153 | mzd_addmul_v(x, lowmc_key, lowmc->k0_matrix); 154 | #endif 155 | 156 | lowmc_round_t const* round = lowmc->rounds; 157 | for (unsigned i = 0; i < lowmc->r; ++i, ++round) { 158 | #ifdef WITH_OPT 159 | #ifdef WITH_SSE2 160 | if (CPU_SUPPORTS_SSE2 && lowmc->n == 128) { 161 | sbox_layer_sse(y, x, &lowmc->mask); 162 | } else 163 | #endif 164 | #ifdef WITH_AVX2 165 | if (CPU_SUPPORTS_AVX2 && lowmc->n == 256) { 166 | sbox_layer_avx(y, x, &lowmc->mask); 167 | } else 168 | #endif 169 | #endif 170 | { 171 | sbox_layer_bitsliced(y, x, lowmc->m, &lowmc->mask); 172 | } 173 | 174 | #ifdef NOSCR 175 | mzd_mul_vl(x, y, round->l_lookup); 176 | #else 177 | mzd_mul_v(x, y, round->l_matrix); 178 | #endif 179 | mzd_xor(x, x, round->constant); 180 | #ifdef NOSCR 181 | mzd_addmul_vl(x, lowmc_key, round->k_lookup); 182 | #else 183 | mzd_addmul_v(x, lowmc_key, round->k_matrix); 184 | #endif 185 | } 186 | 187 | mzd_local_free(y); 188 | 189 | return x; 190 | } 191 | -------------------------------------------------------------------------------- /mpc.h: -------------------------------------------------------------------------------- 1 | #ifndef MPC_H 2 | #define MPC_H 3 | 4 | #include "mpc_lowmc.h" 5 | #include 6 | 7 | void mpc_shift_right(mzd_t* const* res, mzd_t* const* val, unsigned count, unsigned sc) 8 | __attribute__((nonnull)); 9 | 10 | void mpc_shift_left(mzd_t* const* res, mzd_t* const* val, unsigned count, unsigned sc) 11 | __attribute__((nonnull)); 12 | 13 | void mpc_and_const(mzd_t* const* res, mzd_t* const* first, mzd_t const* second, unsigned sc) 14 | __attribute__((nonnull)); 15 | 16 | void mpc_xor(mzd_t* const* res, mzd_t* const* first, mzd_t* const* second, unsigned sc) 17 | __attribute__((nonnull)); 18 | 19 | void mpc_clear(mzd_t** res, unsigned sc) __attribute__((nonnull)); 20 | 21 | void mpc_and(mzd_t* const* res, mzd_t* const* first, mzd_t* const* second, mzd_t* const* r, 22 | view_t* view, unsigned viewshift, mzd_t* const* buffer) __attribute__((nonnull)); 23 | 24 | void mpc_and_verify(mzd_t* const* res, mzd_t* const* first, mzd_t* const* second, mzd_t* const* r, 25 | view_t const* view, mzd_t const* mask, unsigned viewshift, mzd_t* const* buffer) 26 | __attribute__((nonnull)); 27 | 28 | #ifdef WITH_OPT 29 | #include "simd.h" 30 | 31 | void mpc_and_sse(__m128i* res, __m128i const* first, __m128i const* second, __m128i const* r, 32 | view_t const* view, unsigned viewshift) __attribute__((nonnull)); 33 | 34 | void mpc_and_avx(__m256i* res, __m256i const* first, __m256i const* second, __m256i const* r, 35 | view_t const* view, unsigned viewshift) __attribute__((nonnull)); 36 | 37 | void mpc_and_verify_sse(__m128i* res, __m128i const* first, __m128i const* second, __m128i const* r, 38 | view_t const* view, __m128i const mask, unsigned viewshift) 39 | __attribute__((nonnull)); 40 | 41 | void mpc_and_verify_avx(__m256i* res, __m256i const* first, __m256i const* second, __m256i const* r, 42 | view_t const* view, __m256i const mask, unsigned viewshift) 43 | __attribute__((nonnull)); 44 | #endif 45 | 46 | /** 47 | * Linearly secret shares the vector v. 48 | * 49 | * \param v the vector to be secret shared 50 | * \return the vector v represented as three shares 51 | */ 52 | mzd_t** mpc_init_share_vector(mzd_t const* v); 53 | 54 | /** 55 | * Initializes a share vector where all three components 56 | * are set to v 57 | * 58 | * \param v the vector to be copied to all three share components 59 | * \return the vector v containing three copies of the vector 60 | */ 61 | mzd_t** mpc_init_plain_share_vector(mzd_t const* v); 62 | 63 | /** 64 | * Initializes a vector representing a sharing of a random 65 | * vector 66 | * 67 | * \param n the vector length 68 | * \param sc the share count 69 | * \return a random vector shared in three components 70 | */ 71 | mzd_t** mpc_init_random_vector(rci_t n, unsigned sc); 72 | 73 | /** 74 | * Initializes an array of three empty vectors 75 | * 76 | * \param n the vector length 77 | * \param the array of vectors 78 | * \param sc the share count 79 | */ 80 | mzd_t** mpc_init_empty_share_vector(rci_t n, unsigned sc); 81 | 82 | /** 83 | * Reconstructs a vector from three shares 84 | * 85 | * \param shared_vec an array containing the shares 86 | * \return the reconstructed vector 87 | */ 88 | mzd_t* mpc_reconstruct_from_share(mzd_t* dst, mzd_t** shared_vec); 89 | 90 | #if 0 91 | /** 92 | * Computes the a &= b on two secret shared bits according to 93 | * https://eprint.iacr.org/2016/163.pdf 94 | * 95 | * \param a the three shares of the first bit 96 | * \param b the three shares of the second bit 97 | * \param r the three shares containing the randomness 98 | * \param views the views 99 | * \param i the current view index 100 | * \param bp the position of the current bit within the view 101 | * \param sc the share count 102 | */ 103 | int mpc_and_bit(BIT* a, BIT* b, BIT* r, view_t* views, int* i, unsigned bp, unsigned sc); 104 | 105 | int mpc_and_bit_verify(BIT* a, BIT* b, BIT* r, view_t* views, int* i, unsigned bp, unsigned sc); 106 | 107 | /** 108 | * Computes a ^= b on two secret shared bits according to 109 | * https://eprint.iacr.org/2016/163.pdf 110 | * 111 | * \param a the three shares of the first bit 112 | * \param b the three shares of the second bit 113 | * \param sc the share count 114 | */ 115 | void mpc_xor_bit(BIT* a, BIT* b, unsigned sc); 116 | 117 | /** 118 | * Reads a secret shared bit from a given vector 119 | * 120 | * \param out destination of the secret shared bit 121 | * \param vec the secret shared vector 122 | * \param n the position of the bit 123 | * \param sc the share count 124 | */ 125 | void mpc_read_bit(BIT* out, mzd_t** vec, rci_t n, unsigned sc); 126 | 127 | /** 128 | * Writes a secret shared bit to a given vector 129 | * 130 | * \param vec the secret shared vector 131 | * \param n the position of the bit 132 | * \param bit the secret shared bit 133 | * \param sc the share count 134 | */ 135 | void mpc_write_bit(mzd_t** vec, rci_t n, BIT* bit, unsigned sc); 136 | #endif 137 | 138 | /** 139 | * Computes the addition in GF(2) of two secret shared 140 | * vectors according to https://eprint.iacr.org/2016/163.pdf 141 | * 142 | * \param result the result of the computation 143 | * \param first the first operand 144 | * \param second the second operand 145 | * \param sc the share count 146 | * \return the result of the computation 147 | */ 148 | mzd_t** mpc_add(mzd_t** result, mzd_t** first, mzd_t** second, unsigned sc) 149 | __attribute__((nonnull)); 150 | 151 | /** 152 | * Computes the addition in GF(2) of a secret shared 153 | * vector and a constant vector according to 154 | * https://eprint.iacr.org/2016/163.pdf 155 | * 156 | * \param result the result of the computation 157 | * \param first the first operand 158 | * \param second the second operand 159 | * \param sc the share count 160 | * \param c the callenge for verification (0 if in proving mode) 161 | * \return the result of the computation 162 | */ 163 | mzd_t** mpc_const_add(mzd_t** result, mzd_t** first, mzd_t const* second, unsigned sc, unsigned c) 164 | __attribute__((nonnull)); 165 | 166 | /** 167 | * Computes result = first * second in GF(2) of a 168 | * secret shared vector and a matrix according to 169 | * https://eprint.iacr.org/2016/163.pdf 170 | * 171 | * \param result the result of the computation 172 | * \param matrix the matrix 173 | * \param vector the secret shared vector 174 | * \param sc the share count 175 | * \return the result of the computation 176 | */ 177 | mzd_t** mpc_const_mat_mul(mzd_t** result, mzd_t const* matrix, mzd_t** vector, unsigned sc) 178 | __attribute__((nonnull)); 179 | 180 | void mpc_const_addmat_mul_l(mzd_t** result, mzd_t const* matrix, mzd_t** vector, unsigned sc) 181 | __attribute__((nonnull)); 182 | 183 | /** 184 | * Computes result = first * second in GF(2) of a 185 | * secret shared vector and a matrix according to 186 | * https://eprint.iacr.org/2016/163.pdf 187 | * 188 | * \param result the result of the computation 189 | * \param matrix the matrix 190 | * \param vector the secret shared vector 191 | * \param sc the share count 192 | * \return the result of the computation 193 | */ 194 | mzd_t** mpc_const_mat_mul_l(mzd_t** result, mzd_t const* matrix, mzd_t** vector, unsigned sc) 195 | __attribute__((nonnull)); 196 | 197 | /** 198 | * Deep copies a secret shared vector 199 | * 200 | * \param out the destination 201 | * \param in the source 202 | * \param sc the share count 203 | * 204 | */ 205 | void mpc_copy(mzd_t** out, mzd_t* const* in, unsigned sc) __attribute__((nonnull(2))); 206 | 207 | /** 208 | * Prints a secret shared vector 209 | * 210 | * \param shared_vec the vector 211 | */ 212 | void mpc_print(mzd_t** shared_vec); 213 | 214 | /** 215 | * Frees a secret shared vector 216 | */ 217 | void mpc_free(mzd_t** vec, unsigned sc); 218 | 219 | #endif 220 | -------------------------------------------------------------------------------- /lowmc_pars.c: -------------------------------------------------------------------------------- 1 | #include "lowmc_pars.h" 2 | #include "mpc.h" 3 | #include "mzd_additional.h" 4 | #include "randomness.h" 5 | 6 | #include 7 | #include 8 | 9 | static mask_t* prepare_masks(mask_t* mask, rci_t n, rci_t m) { 10 | mask->x0 = mzd_local_init(1, n); 11 | mask->x1 = mzd_local_init_ex(1, n, false); 12 | mask->x2 = mzd_local_init_ex(1, n, false); 13 | mask->mask = mzd_local_init(1, n); 14 | 15 | const int bound = n - 3 * m; 16 | for (int i = 0; i < bound; ++i) { 17 | mzd_write_bit(mask->mask, 0, i, 1); 18 | } 19 | for (int i = bound; i < n; i += 3) { 20 | mzd_write_bit(mask->x0, 0, i, 1); 21 | } 22 | mzd_shift_left(mask->x1, mask->x0, 1); 23 | mzd_shift_left(mask->x2, mask->x0, 2); 24 | 25 | return mask; 26 | } 27 | 28 | static mzd_t* mzd_sample_matrix_word(rci_t n, rci_t k, rci_t rank, bool with_xor) { 29 | // use mzd_init for A since m4ri will work with it in mzd_echolonize 30 | // also, this function cannot be parallelized as mzd_echolonize will call 31 | // mzd_init and mzd_free at will causing various crashes. 32 | mzd_t* A = mzd_init(n, k); 33 | mzd_t* B = mzd_local_init_ex(n, k, false); 34 | do { 35 | mzd_randomize_ssl(A); 36 | if (with_xor) { 37 | for (rci_t i = 0; i < n; i++) { 38 | mzd_xor_bits(A, n - i - 1, (k + i + 1) % k, 1, 1); 39 | } 40 | } 41 | mzd_local_copy(B, A); 42 | } while (mzd_echelonize(A, 0) != rank); 43 | mzd_free(A); 44 | return B; 45 | }; 46 | 47 | /** 48 | * Samples the L matrix for the LowMC instance 49 | * 50 | * \param n the blocksize 51 | */ 52 | static mzd_t* mzd_sample_lmatrix(rci_t n) { 53 | return mzd_sample_matrix_word(n, n, n, false); 54 | } 55 | 56 | /** 57 | * Samples the K matrix for the LowMC instance 58 | * \param n the blocksize 59 | */ 60 | static mzd_t* mzd_sample_kmatrix(rci_t n, rci_t k) { 61 | return mzd_sample_matrix_word(n, k, MIN(n, k), true); 62 | } 63 | 64 | lowmc_t* lowmc_init(size_t m, size_t n, size_t r, size_t k) { 65 | if (n - 3 * m < 2) { 66 | printf("Bitsliced implementation requires in->ncols - 3 * m >= 2\n"); 67 | return NULL; 68 | } 69 | 70 | lowmc_t* ret = readFile(m, n, r, k); 71 | if (ret) { 72 | return ret; 73 | } 74 | 75 | lowmc_t* lowmc = calloc(sizeof(lowmc_t), 1); 76 | lowmc->m = m; 77 | lowmc->n = n; 78 | lowmc->r = r; 79 | lowmc->k = k; 80 | 81 | lowmc->k0_matrix = mzd_sample_kmatrix(k, n); 82 | #ifdef NOSCR 83 | lowmc->k0_lookup = mzd_precompute_matrix_lookup(lowmc->k0_matrix); 84 | #endif 85 | 86 | lowmc->rounds = calloc(sizeof(lowmc_round_t), r); 87 | for (unsigned int i = 0; i < r; ++i) { 88 | lowmc->rounds[i].l_matrix = mzd_sample_lmatrix(n); 89 | lowmc->rounds[i].k_matrix = mzd_sample_kmatrix(k, n); 90 | lowmc->rounds[i].constant = mzd_init_random_vector(n); 91 | 92 | #ifdef NOSCR 93 | lowmc->rounds[i].l_lookup = mzd_precompute_matrix_lookup(lowmc->rounds[i].l_matrix); 94 | lowmc->rounds[i].k_lookup = mzd_precompute_matrix_lookup(lowmc->rounds[i].k_matrix); 95 | #endif 96 | } 97 | 98 | if (!prepare_masks(&lowmc->mask, n, m)) { 99 | lowmc_free(lowmc); 100 | return NULL; 101 | } 102 | 103 | writeFile(lowmc); 104 | 105 | return lowmc; 106 | } 107 | 108 | lowmc_t* readFile(size_t m, size_t n, size_t r, size_t k) { 109 | 110 | lowmc_t* lowmc = NULL; 111 | char* file_name = calloc(20, sizeof(char)); 112 | sprintf(file_name, "%zu-%zu-%zu-%zu", m, n, r, k); 113 | FILE* file = fopen(file_name, "r+"); 114 | free(file_name); 115 | if (file) { 116 | lowmc = calloc(1, sizeof(lowmc_t)); 117 | 118 | int ret = 0; 119 | 120 | ret = fread(&lowmc->m, sizeof(lowmc->m), 1, file); 121 | ret += fread(&lowmc->n, sizeof(lowmc->n), 1, file); 122 | ret += fread(&lowmc->r, sizeof(lowmc->r), 1, file); 123 | ret += fread(&lowmc->k, sizeof(lowmc->k), 1, file); 124 | 125 | if (lowmc->m != m || lowmc->n != n || lowmc->r != r || lowmc->k != k) { 126 | printf("Error when reading file!\n"); 127 | return NULL; 128 | } 129 | 130 | lowmc->mask.x0 = readMZD_TStructFromFile(file); 131 | lowmc->mask.x1 = readMZD_TStructFromFile(file); 132 | lowmc->mask.x2 = readMZD_TStructFromFile(file); 133 | lowmc->mask.mask = readMZD_TStructFromFile(file); 134 | 135 | lowmc->k0_matrix = readMZD_TStructFromFile(file); 136 | #ifdef NOSCR 137 | lowmc->k0_lookup = readMZD_TStructFromFile(file); 138 | #endif 139 | lowmc->rounds = calloc(r, sizeof(lowmc_round_t)); 140 | for (size_t i = 0; i < lowmc->r; ++i) { 141 | lowmc->rounds[i].k_matrix = readMZD_TStructFromFile(file); 142 | lowmc->rounds[i].l_matrix = readMZD_TStructFromFile(file); 143 | lowmc->rounds[i].constant = readMZD_TStructFromFile(file); 144 | #ifdef NOSCR 145 | lowmc->rounds[i].k_lookup = readMZD_TStructFromFile(file); 146 | lowmc->rounds[i].l_lookup = readMZD_TStructFromFile(file); 147 | #endif 148 | } 149 | fclose(file); 150 | } 151 | 152 | return lowmc; 153 | } 154 | 155 | bool writeFile(lowmc_t* lowmc) { 156 | 157 | char* file_name = calloc(20, sizeof(char)); 158 | sprintf(file_name, "%zu-%zu-%zu-%zu", lowmc->m, lowmc->n, lowmc->r, lowmc->k); 159 | FILE* file = fopen(file_name, "w"); 160 | free(file_name); 161 | if (file) { 162 | fwrite(&lowmc->m, sizeof(lowmc->m), 1, file); 163 | fwrite(&lowmc->n, sizeof(lowmc->n), 1, file); 164 | fwrite(&lowmc->r, sizeof(lowmc->r), 1, file); 165 | fwrite(&lowmc->k, sizeof(lowmc->k), 1, file); 166 | 167 | writeMZD_TStructToFile(lowmc->mask.x0, file); 168 | writeMZD_TStructToFile(lowmc->mask.x1, file); 169 | writeMZD_TStructToFile(lowmc->mask.x2, file); 170 | writeMZD_TStructToFile(lowmc->mask.mask, file); 171 | 172 | writeMZD_TStructToFile(lowmc->k0_matrix, file); 173 | 174 | #ifdef NOSCR 175 | writeMZD_TStructToFile(lowmc->k0_lookup, file); 176 | #endif 177 | for (size_t i = 0; i < lowmc->r; ++i) { 178 | writeMZD_TStructToFile(lowmc->rounds[i].k_matrix, file); 179 | writeMZD_TStructToFile(lowmc->rounds[i].l_matrix, file); 180 | writeMZD_TStructToFile(lowmc->rounds[i].constant, file); 181 | #ifdef NOSCR 182 | writeMZD_TStructToFile(lowmc->rounds[i].k_lookup, file); 183 | writeMZD_TStructToFile(lowmc->rounds[i].l_lookup, file); 184 | #endif 185 | } 186 | fclose(file); 187 | } 188 | 189 | return false; 190 | } 191 | 192 | void writeMZD_TStructToFile(mzd_t* matrix, FILE* file) { 193 | 194 | fwrite(&(matrix->nrows), sizeof(rci_t), 1, file); 195 | fwrite(&(matrix->ncols), sizeof(rci_t), 1, file); 196 | 197 | for (int i = 0; i < matrix->nrows; i++) { 198 | fwrite((matrix->rows[i]), matrix->rowstride * sizeof(word), 1, file); 199 | } 200 | } 201 | 202 | mzd_t* readMZD_TStructFromFile(FILE* file) { 203 | 204 | int ret = 0; 205 | int nrows = 0; 206 | int ncols = 0; 207 | ret += fread(&(nrows), sizeof(rci_t), 1, file); 208 | ret += fread(&(ncols), sizeof(rci_t), 1, file); 209 | 210 | mzd_t* A = mzd_local_init_ex(nrows, ncols, false); 211 | for (int i = 0; i < A->nrows; i++) { 212 | ret += fread((A->rows[i]), A->rowstride * sizeof(word), 1, file); 213 | } 214 | 215 | return A; 216 | } 217 | 218 | lowmc_key_t* lowmc_keygen(lowmc_t* lowmc) { 219 | return mzd_init_random_vector(lowmc->k); 220 | } 221 | 222 | void lowmc_free(lowmc_t* lowmc) { 223 | for (unsigned i = 0; i < lowmc->r; ++i) { 224 | #ifdef NOSCR 225 | mzd_local_free(lowmc->rounds[i].k_lookup); 226 | mzd_local_free(lowmc->rounds[i].l_lookup); 227 | #endif 228 | mzd_local_free(lowmc->rounds[i].constant); 229 | mzd_local_free(lowmc->rounds[i].k_matrix); 230 | mzd_local_free(lowmc->rounds[i].l_matrix); 231 | } 232 | #ifdef NOSCR 233 | mzd_local_free(lowmc->k0_lookup); 234 | #endif 235 | mzd_local_free(lowmc->k0_matrix); 236 | free(lowmc->rounds); 237 | 238 | mzd_local_free(lowmc->mask.x0); 239 | mzd_local_free(lowmc->mask.x1); 240 | mzd_local_free(lowmc->mask.x2); 241 | mzd_local_free(lowmc->mask.mask); 242 | 243 | free(lowmc); 244 | } 245 | 246 | void lowmc_key_free(lowmc_key_t* lowmc_key) { 247 | mzd_local_free(lowmc_key); 248 | } 249 | -------------------------------------------------------------------------------- /signature_fis.c: -------------------------------------------------------------------------------- 1 | #include "signature_fis.h" 2 | #include "hashing_util.h" 3 | #include "lowmc.h" 4 | #include "mpc.h" 5 | #include "mpc_lowmc.h" 6 | #include "randomness.h" 7 | #include "timing.h" 8 | 9 | unsigned fis_compute_sig_size(unsigned m, unsigned n, unsigned r, unsigned k) { 10 | unsigned first_view_size = k; 11 | unsigned full_view_size = n; 12 | unsigned int_view_size = 3 * m; 13 | // views for mpc_and in sbox, intial view and last view 14 | unsigned views = r * int_view_size + first_view_size + full_view_size; 15 | // commitment and r and seed 16 | unsigned int commitment = 8 * (COMMITMENT_LENGTH + 2 * (COMMITMENT_RAND_LENGTH + PRNG_KEYSIZE)); 17 | unsigned int challenge = (FIS_NUM_ROUNDS + 3) / 4; 18 | 19 | return (FIS_NUM_ROUNDS * (commitment + views) + full_view_size + challenge + 7) / 8; 20 | } 21 | 22 | unsigned char* fis_sig_to_char_array(public_parameters_t* pp, fis_signature_t* sig, unsigned* len) { 23 | return proof_to_char_array(pp->lowmc, sig->proof, len, true); 24 | } 25 | 26 | fis_signature_t* fis_sig_from_char_array(public_parameters_t* pp, unsigned char* data) { 27 | unsigned len = 0; 28 | fis_signature_t* sig = malloc(sizeof(fis_signature_t)); 29 | sig->proof = proof_from_char_array(pp->lowmc, 0, data, &len, true); 30 | return sig; 31 | } 32 | 33 | bool fis_create_key(public_parameters_t* pp, fis_private_key_t* private_key, 34 | fis_public_key_t* public_key) { 35 | TIME_FUNCTION; 36 | 37 | START_TIMING; 38 | private_key->k = lowmc_keygen(pp->lowmc); 39 | END_TIMING(timing_and_size->gen.keygen); 40 | 41 | if (!private_key->k) { 42 | return false; 43 | } 44 | 45 | mzd_t* p = mzd_local_init(1, pp->lowmc->n); 46 | if (!p) { 47 | return false; 48 | } 49 | 50 | START_TIMING; 51 | public_key->pk = lowmc_call(pp->lowmc, private_key->k, p); 52 | END_TIMING(timing_and_size->gen.pubkey); 53 | 54 | mzd_local_free(p); 55 | 56 | return public_key->pk != NULL; 57 | } 58 | 59 | void fis_destroy_key(fis_private_key_t* private_key, fis_public_key_t* public_key) { 60 | lowmc_key_free(private_key->k); 61 | private_key->k = NULL; 62 | 63 | mzd_local_free(public_key->pk); 64 | public_key->pk = NULL; 65 | } 66 | 67 | static proof_t* fis_prove(mpc_lowmc_t* lowmc, lowmc_key_t* lowmc_key, mzd_t* p, const uint8_t* m, 68 | unsigned m_len) { 69 | TIME_FUNCTION; 70 | 71 | const unsigned int view_count = lowmc->r + 2; 72 | 73 | unsigned char r[FIS_NUM_ROUNDS][3][COMMITMENT_RAND_LENGTH]; 74 | unsigned char keys[FIS_NUM_ROUNDS][3][16]; 75 | unsigned char secret_sharing_key[16]; 76 | 77 | // Generating keys 78 | START_TIMING; 79 | if (rand_bytes((unsigned char*)keys, sizeof(keys)) != 1 || 80 | rand_bytes((unsigned char*)r, sizeof(r)) != 1 || 81 | rand_bytes(secret_sharing_key, sizeof(secret_sharing_key)) != 1) { 82 | return 0; 83 | } 84 | END_TIMING(timing_and_size->sign.rand); 85 | 86 | START_TIMING; 87 | view_t* views[FIS_NUM_ROUNDS]; 88 | init_view(lowmc, views); 89 | 90 | mzd_shared_t s[FIS_NUM_ROUNDS]; 91 | for (unsigned int i = 0; i < FIS_NUM_ROUNDS; ++i) { 92 | mzd_shared_init(&s[i], lowmc_key); 93 | mzd_shared_share_from_keys(&s[i], keys[i]); 94 | } 95 | END_TIMING(timing_and_size->sign.secret_sharing); 96 | 97 | START_TIMING; 98 | mzd_t** c_mpc[FIS_NUM_ROUNDS]; 99 | 100 | #ifdef WITH_OPENMP 101 | mzd_t** rvecs[FIS_NUM_ROUNDS][3]; 102 | #else 103 | mzd_t** rvec[SC_PROOF]; 104 | for (unsigned int i = 0; i < SC_PROOF; ++i) { 105 | rvec[i] = malloc(sizeof(mzd_t*) * lowmc->r); 106 | mzd_local_init_multiple_ex(rvec[i], lowmc->r, 1, lowmc->n, false); 107 | } 108 | #endif 109 | 110 | #pragma omp parallel for 111 | for (unsigned int i = 0; i < FIS_NUM_ROUNDS; ++i) { 112 | #ifdef WITH_OPENMP 113 | mzd_t*** rvec = rvecs[i]; 114 | rvec[0] = mzd_init_random_vectors_from_seed(keys[i][0], lowmc->n, lowmc->r); 115 | rvec[1] = mzd_init_random_vectors_from_seed(keys[i][1], lowmc->n, lowmc->r); 116 | rvec[2] = mzd_init_random_vectors_from_seed(keys[i][2], lowmc->n, lowmc->r); 117 | #else 118 | for (unsigned int j = 0; j < SC_PROOF; ++j) { 119 | mzd_randomize_multiple_from_seed(rvec[j], lowmc->r, keys[i][j]); 120 | } 121 | #endif 122 | c_mpc[i] = mpc_lowmc_call(lowmc, &s[i], p, views[i], rvec); 123 | } 124 | END_TIMING(timing_and_size->sign.lowmc_enc); 125 | 126 | START_TIMING; 127 | unsigned char hashes[FIS_NUM_ROUNDS][3][COMMITMENT_LENGTH]; 128 | #pragma omp parallel for 129 | for (unsigned int i = 0; i < FIS_NUM_ROUNDS; ++i) { 130 | H(keys[i][0], c_mpc[i], views[i], 0, view_count, r[i][0], hashes[i][0]); 131 | H(keys[i][1], c_mpc[i], views[i], 1, view_count, r[i][1], hashes[i][1]); 132 | H(keys[i][2], c_mpc[i], views[i], 2, view_count, r[i][2], hashes[i][2]); 133 | } 134 | END_TIMING(timing_and_size->sign.views); 135 | 136 | START_TIMING; 137 | unsigned char ch[FIS_NUM_ROUNDS]; 138 | fis_H3(hashes, m, m_len, ch); 139 | 140 | proof_t* proof = create_proof(NULL, lowmc, hashes, ch, r, keys, views); 141 | 142 | for (unsigned int j = 0; j < FIS_NUM_ROUNDS; ++j) { 143 | mzd_shared_clear(&s[j]); 144 | #ifdef WITH_OPENMP 145 | for (unsigned int i = 0; i < SC_PROOF; ++i) { 146 | mzd_local_free_multiple(rvecs[j][i]); 147 | free(rvecs[j][i]); 148 | } 149 | #endif 150 | mpc_free(c_mpc[j], 3); 151 | } 152 | 153 | #ifndef WITH_OPENMP 154 | for (unsigned int i = 0; i < SC_PROOF; ++i) { 155 | mzd_local_free_multiple(rvec[i]); 156 | free(rvec[i]); 157 | } 158 | #endif 159 | 160 | free_view(lowmc, views); 161 | END_TIMING(timing_and_size->sign.challenge); 162 | 163 | return proof; 164 | } 165 | 166 | static int fis_proof_verify(mpc_lowmc_t const* lowmc, mzd_t const* p, mzd_t const* c, 167 | proof_t const* prf, const uint8_t* m, unsigned m_len) { 168 | TIME_FUNCTION; 169 | 170 | const unsigned int view_count = lowmc->r + 2; 171 | const unsigned int last_view_index = lowmc->r + 1; 172 | 173 | #ifdef WITH_OPENMP 174 | mzd_t* ycs[FIS_NUM_ROUNDS] = {NULL}; 175 | mzd_local_init_multiple(ycs, FIS_NUM_ROUNDS, 1, lowmc->n); 176 | #else 177 | mzd_t* yc = mzd_local_init(1, lowmc->n); 178 | #endif 179 | 180 | START_TIMING; 181 | unsigned char ch[FIS_NUM_ROUNDS]; 182 | unsigned char hash[FIS_NUM_ROUNDS][2][COMMITMENT_LENGTH]; 183 | 184 | #ifndef WITH_OPENMP 185 | mzd_t** rv[SC_VERIFY]; 186 | for (unsigned int i = 0; i < SC_VERIFY; ++i) { 187 | rv[i] = malloc(sizeof(mzd_t*) * lowmc->r); 188 | mzd_local_init_multiple_ex(rv[i], lowmc->r, 1, lowmc->n, false); 189 | } 190 | #endif 191 | 192 | #pragma omp parallel for 193 | for (unsigned int i = 0; i < FIS_NUM_ROUNDS; ++i) { 194 | unsigned int a_i = getChAt(prf->ch, i); 195 | unsigned int b_i = (a_i + 1) % 3; 196 | unsigned int c_i = (a_i + 2) % 3; 197 | 198 | #ifdef WITH_OPENMP 199 | mzd_t** rv[2]; 200 | rv[0] = mzd_init_random_vectors_from_seed(prf->keys[i][0], lowmc->n, lowmc->r); 201 | rv[1] = mzd_init_random_vectors_from_seed(prf->keys[i][1], lowmc->n, lowmc->r); 202 | #else 203 | for (unsigned int j = 0; j < SC_VERIFY; ++j) { 204 | mzd_randomize_multiple_from_seed(rv[j], lowmc->r, prf->keys[i][j]); 205 | } 206 | #endif 207 | 208 | for (unsigned int j = 1; j < view_count - 1; ++j) { 209 | mzd_local_clear(prf->views[i][j].s[0]); 210 | } 211 | 212 | mpc_lowmc_verify_keys(lowmc, p, prf->views[i], rv, a_i, prf->keys[i]); 213 | 214 | mzd_t* ys[3]; 215 | ys[a_i] = prf->views[i][last_view_index].s[0]; 216 | ys[b_i] = prf->views[i][last_view_index].s[1]; 217 | ys[c_i] = (mzd_t*)c; 218 | 219 | #ifdef WITH_OPENMP 220 | mzd_t* yc = ycs[i]; 221 | #endif 222 | ys[c_i] = mpc_reconstruct_from_share(yc, ys); 223 | 224 | H(prf->keys[i][0], ys, prf->views[i], 0, view_count, prf->r[i][0], hash[i][0]); 225 | H(prf->keys[i][1], ys, prf->views[i], 1, view_count, prf->r[i][1], hash[i][1]); 226 | 227 | #ifdef WITH_OPENMP 228 | mzd_local_free_multiple(rv[1]); 229 | free(rv[1]); 230 | mzd_local_free_multiple(rv[0]); 231 | free(rv[0]); 232 | #endif 233 | } 234 | fis_H3_verify(hash, prf->hashes, prf->ch, m, m_len, ch); 235 | 236 | #ifdef WITH_OPENMP 237 | mzd_local_free_multiple(ycs); 238 | #else 239 | for (unsigned int i = 0; i < SC_VERIFY; ++i) { 240 | mzd_local_free_multiple(rv[i]); 241 | free(rv[i]); 242 | } 243 | mzd_local_free(yc); 244 | #endif 245 | 246 | unsigned char ch_collapsed[(FIS_NUM_ROUNDS + 3) / 4] = {0}; 247 | for (unsigned int i = 0; i < FIS_NUM_ROUNDS; ++i) { 248 | const unsigned int idx = i / 4; 249 | const unsigned int shift = (i % 4) << 1; 250 | 251 | ch_collapsed[idx] |= ch[i] << shift; 252 | } 253 | 254 | const int success_status = 255 | memcmp(ch_collapsed, prf->ch, ((FIS_NUM_ROUNDS + 3) / 4) * sizeof(unsigned char)); 256 | END_TIMING(timing_and_size->verify.verify); 257 | 258 | START_TIMING; 259 | 260 | return success_status; 261 | } 262 | 263 | fis_signature_t* fis_sign(public_parameters_t* pp, fis_private_key_t* private_key, 264 | const uint8_t* msg, size_t msglen) { 265 | fis_signature_t* sig = malloc(sizeof(fis_signature_t)); 266 | mzd_t* p = mzd_local_init(1, pp->lowmc->n); 267 | sig->proof = fis_prove(pp->lowmc, private_key->k, p, msg, msglen); 268 | mzd_local_free(p); 269 | return sig; 270 | } 271 | 272 | int fis_verify(public_parameters_t* pp, fis_public_key_t* public_key, const uint8_t* msg, 273 | size_t msglen, fis_signature_t* sig) { 274 | mzd_t* p = mzd_local_init(1, pp->lowmc->n); 275 | int res = fis_proof_verify(pp->lowmc, p, public_key->pk, sig->proof, msg, msglen); 276 | mzd_local_free(p); 277 | return res; 278 | } 279 | 280 | void fis_free_signature(public_parameters_t* pp, fis_signature_t* signature) { 281 | free_proof(pp->lowmc, signature->proof); 282 | free(signature); 283 | } 284 | -------------------------------------------------------------------------------- /mpc.c: -------------------------------------------------------------------------------- 1 | #include "mpc.h" 2 | #include "mzd_additional.h" 3 | #include "simd.h" 4 | 5 | #if 0 6 | void mpc_clear(mzd_t** res, unsigned sc) { 7 | for (unsigned int i = 0; i < sc; i++) { 8 | mzd_local_clear(res[i]); 9 | } 10 | } 11 | #endif 12 | 13 | void mpc_shift_right(mzd_t* const* res, mzd_t* const* val, unsigned count, unsigned sc) { 14 | for (unsigned i = 0; i < sc; ++i) 15 | mzd_shift_right(res[i], val[i], count); 16 | } 17 | 18 | void mpc_shift_left(mzd_t* const* res, mzd_t* const* val, unsigned count, unsigned sc) { 19 | for (unsigned i = 0; i < sc; ++i) 20 | mzd_shift_left(res[i], val[i], count); 21 | } 22 | 23 | void mpc_and_const(mzd_t* const* res, mzd_t* const* first, mzd_t const* second, unsigned sc) { 24 | for (unsigned i = 0; i < sc; i++) { 25 | mzd_and(res[i], first[i], second); 26 | } 27 | } 28 | 29 | void mpc_xor(mzd_t* const* res, mzd_t* const* first, mzd_t* const* second, unsigned sc) { 30 | for (unsigned i = 0; i < sc; i++) { 31 | mzd_xor(res[i], first[i], second[i]); 32 | } 33 | } 34 | 35 | #ifdef WITH_OPT 36 | #ifdef WITH_SSE2 37 | __attribute__((target("sse2"))) void mpc_and_sse(__m128i* res, __m128i const* first, 38 | __m128i const* second, __m128i const* r, 39 | view_t const* view, unsigned viewshift) { 40 | for (unsigned m = 0; m < SC_PROOF; ++m) { 41 | const unsigned j = (m + 1) % SC_PROOF; 42 | 43 | __m128i* sm = __builtin_assume_aligned(FIRST_ROW(view->s[m]), 16); 44 | 45 | __m128i tmp1 = _mm_xor_si128(second[m], second[j]); 46 | __m128i tmp2 = _mm_and_si128(first[j], second[m]); 47 | tmp1 = _mm_and_si128(tmp1, first[m]); 48 | tmp1 = _mm_xor_si128(tmp1, tmp2); 49 | 50 | tmp2 = _mm_xor_si128(r[m], r[j]); 51 | res[m] = tmp1 = _mm_xor_si128(tmp1, tmp2); 52 | 53 | tmp1 = mm128_shift_right(tmp1, viewshift); 54 | *sm = _mm_xor_si128(tmp1, *sm); 55 | } 56 | } 57 | #endif 58 | 59 | #ifdef WITH_AVX2 60 | __attribute__((target("avx2"))) void mpc_and_avx(__m256i* res, __m256i const* first, 61 | __m256i const* second, __m256i const* r, 62 | view_t const* view, unsigned viewshift) { 63 | for (unsigned m = 0; m < SC_PROOF; ++m) { 64 | const unsigned j = (m + 1) % SC_PROOF; 65 | 66 | __m256i* sm = __builtin_assume_aligned(FIRST_ROW(view->s[m]), 32); 67 | 68 | __m256i tmp1 = _mm256_xor_si256(second[m], second[j]); 69 | __m256i tmp2 = _mm256_and_si256(first[j], second[m]); 70 | tmp1 = _mm256_and_si256(tmp1, first[m]); 71 | tmp1 = _mm256_xor_si256(tmp1, tmp2); 72 | 73 | tmp2 = _mm256_xor_si256(r[m], r[j]); 74 | res[m] = tmp1 = _mm256_xor_si256(tmp1, tmp2); 75 | 76 | tmp1 = mm256_shift_right(tmp1, viewshift); 77 | *sm = _mm256_xor_si256(tmp1, *sm); 78 | } 79 | } 80 | #endif 81 | #endif 82 | 83 | void mpc_and(mzd_t* const* res, mzd_t* const* first, mzd_t* const* second, mzd_t* const* r, 84 | view_t* view, unsigned viewshift, mzd_t* const* buffer) { 85 | mzd_t* b = buffer[0]; 86 | 87 | for (unsigned m = 0; m < SC_PROOF; ++m) { 88 | const unsigned j = (m + 1) % SC_PROOF; 89 | 90 | mzd_and(res[m], first[m], second[m]); 91 | 92 | mzd_and(b, first[j], second[m]); 93 | mzd_xor(res[m], res[m], b); 94 | 95 | mzd_and(b, first[m], second[j]); 96 | mzd_xor(res[m], res[m], b); 97 | 98 | mzd_xor(res[m], res[m], r[m]); 99 | mzd_xor(res[m], res[m], r[j]); 100 | } 101 | 102 | mpc_shift_right(buffer, res, viewshift, SC_PROOF); 103 | mpc_xor(view->s, view->s, buffer, SC_PROOF); 104 | } 105 | 106 | #ifdef WITH_OPT 107 | #ifdef WITH_SSE2 108 | __attribute__((target("sse2"))) void mpc_and_verify_sse(__m128i* res, __m128i const* first, 109 | __m128i const* second, __m128i const* r, 110 | view_t const* view, __m128i const mask, 111 | unsigned viewshift) { 112 | for (unsigned m = 0; m < (SC_VERIFY - 1); ++m) { 113 | const unsigned j = (m + 1); 114 | 115 | __m128i* sm = __builtin_assume_aligned(FIRST_ROW(view->s[m]), 16); 116 | 117 | __m128i tmp1 = _mm_xor_si128(second[m], second[j]); 118 | __m128i tmp2 = _mm_and_si128(first[j], second[m]); 119 | tmp1 = _mm_and_si128(tmp1, first[m]); 120 | tmp1 = _mm_xor_si128(tmp1, tmp2); 121 | 122 | tmp2 = _mm_xor_si128(r[m], r[j]); 123 | res[m] = tmp1 = _mm_xor_si128(tmp1, tmp2); 124 | 125 | tmp1 = mm128_shift_right(tmp1, viewshift); 126 | *sm = _mm_xor_si128(tmp1, *sm); 127 | } 128 | 129 | __m128i const* s1 = __builtin_assume_aligned(CONST_FIRST_ROW(view->s[SC_VERIFY - 1]), 16); 130 | __m128i rsc = mm128_shift_left(*s1, viewshift); 131 | res[SC_VERIFY - 1] = _mm_and_si128(rsc, mask); 132 | } 133 | #endif 134 | 135 | #ifdef WITH_AVX2 136 | __attribute__((target("avx2"))) void mpc_and_verify_avx(__m256i* res, __m256i const* first, 137 | __m256i const* second, __m256i const* r, 138 | view_t const* view, __m256i const mask, 139 | unsigned viewshift) { 140 | for (unsigned m = 0; m < (SC_VERIFY - 1); ++m) { 141 | const unsigned j = (m + 1); 142 | 143 | __m256i* sm = __builtin_assume_aligned(FIRST_ROW(view->s[m]), 32); 144 | 145 | __m256i tmp1 = _mm256_xor_si256(second[m], second[j]); 146 | __m256i tmp2 = _mm256_and_si256(first[j], second[m]); 147 | tmp1 = _mm256_and_si256(tmp1, first[m]); 148 | tmp1 = _mm256_xor_si256(tmp1, tmp2); 149 | 150 | tmp2 = _mm256_xor_si256(r[m], r[j]); 151 | res[m] = tmp1 = _mm256_xor_si256(tmp1, tmp2); 152 | 153 | tmp1 = mm256_shift_right(tmp1, viewshift); 154 | *sm = _mm256_xor_si256(tmp1, *sm); 155 | } 156 | 157 | __m256i const* s1 = __builtin_assume_aligned(CONST_FIRST_ROW(view->s[SC_VERIFY - 1]), 32); 158 | __m256i rsc = mm256_shift_left(*s1, viewshift); 159 | res[SC_VERIFY - 1] = _mm256_and_si256(rsc, mask); 160 | } 161 | #endif 162 | #endif 163 | 164 | void mpc_and_verify(mzd_t* const* res, mzd_t* const* first, mzd_t* const* second, mzd_t* const* r, 165 | view_t const* view, mzd_t const* mask, unsigned viewshift, 166 | mzd_t* const* buffer) { 167 | mzd_t* b = buffer[0]; 168 | 169 | for (unsigned m = 0; m < (SC_VERIFY - 1); ++m) { 170 | const unsigned j = m + 1; 171 | 172 | mzd_and(res[m], first[m], second[m]); 173 | 174 | mzd_and(b, first[j], second[m]); 175 | mzd_xor(res[m], res[m], b); 176 | 177 | mzd_and(b, first[m], second[j]); 178 | mzd_xor(res[m], res[m], b); 179 | 180 | mzd_xor(res[m], res[m], r[m]); 181 | mzd_xor(res[m], res[m], r[j]); 182 | } 183 | 184 | for (unsigned m = 0; m < (SC_VERIFY - 1); ++m) { 185 | mzd_shift_right(b, res[m], viewshift); 186 | mzd_xor(view->s[m], view->s[m], b); 187 | } 188 | 189 | mzd_shift_left(res[SC_VERIFY - 1], view->s[SC_VERIFY - 1], viewshift); 190 | mzd_and(res[SC_VERIFY - 1], res[SC_VERIFY - 1], mask); 191 | } 192 | 193 | #if 0 194 | int mpc_and_bit(BIT* a, BIT* b, BIT* r, view_t* views, int* i, unsigned bp, unsigned sc) { 195 | BIT* wp = (BIT*)malloc(sc * sizeof(BIT)); 196 | for (unsigned m = 0; m < sc; ++m) { 197 | unsigned j = (m + 1) % 3; 198 | wp[m] = (a[m] & b[m]) ^ (a[j] & b[m]) ^ (a[m] & b[j]) ^ r[m] ^ r[j]; 199 | } 200 | for (unsigned m = 0; m < sc; ++m) { 201 | a[m] = wp[m]; 202 | } 203 | mpc_write_bit(views[*i].s, bp, a, sc); 204 | free(wp); 205 | return 0; 206 | } 207 | 208 | int mpc_and_bit_verify(BIT* a, BIT* b, BIT* r, view_t* views, int* i, unsigned bp, unsigned sc) { 209 | BIT* wp = (BIT*)malloc(sc * sizeof(BIT)); 210 | for (unsigned m = 0; m < sc - 1; m++) { 211 | unsigned j = m + 1; 212 | wp[m] = (a[m] & b[m]) ^ (a[j] & b[m]) ^ (a[m] & b[j]) ^ r[m] ^ r[j]; 213 | } 214 | for (unsigned m = 0; m < sc - 1; m++) { 215 | a[m] = wp[m]; 216 | if (a[m] != mzd_read_bit(views[*i].s[m], 0, bp)) { 217 | free(wp); 218 | return -1; 219 | } 220 | } 221 | a[sc - 1] = mzd_read_bit(views[*i].s[sc - 1], 0, bp); 222 | free(wp); 223 | return 0; 224 | } 225 | 226 | void mpc_xor_bit(BIT* a, BIT* b, unsigned sc) { 227 | for (unsigned i = 0; i < sc; i++) { 228 | a[i] ^= b[i]; 229 | } 230 | } 231 | 232 | void mpc_read_bit(BIT* out, mzd_t** vec, rci_t n, unsigned sc) { 233 | for (unsigned i = 0; i < sc; i++) 234 | out[i] = mzd_read_bit(vec[i], 0, n); 235 | } 236 | 237 | void mpc_write_bit(mzd_t** vec, rci_t n, BIT* bit, unsigned sc) { 238 | for (unsigned i = 0; i < sc; i++) 239 | mzd_write_bit(vec[i], 0, n, bit[i]); 240 | } 241 | #endif 242 | 243 | mzd_t** mpc_add(mzd_t** result, mzd_t** first, mzd_t** second, unsigned sc) { 244 | for (unsigned i = 0; i < sc; i++) { 245 | mzd_xor(result[i], first[i], second[i]); 246 | } 247 | return result; 248 | } 249 | 250 | mzd_t** mpc_const_add(mzd_t** result, mzd_t** first, mzd_t const* second, unsigned sc, unsigned c) { 251 | if (c == 0) 252 | mzd_xor(result[0], first[0], second); 253 | else if (c == sc) 254 | mzd_xor(result[sc - 1], first[sc - 1], second); 255 | return result; 256 | } 257 | 258 | mzd_t** mpc_const_mat_mul(mzd_t** result, mzd_t const* matrix, mzd_t** vector, unsigned sc) { 259 | for (unsigned i = 0; i < sc; ++i) { 260 | mzd_mul_v(result[i], vector[i], matrix); 261 | } 262 | return result; 263 | } 264 | 265 | void mpc_const_addmat_mul_l(mzd_t** result, mzd_t const* matrix, mzd_t** vector, unsigned sc) { 266 | for (unsigned i = 0; i < sc; ++i) { 267 | mzd_addmul_vl(result[i], vector[i], matrix); 268 | } 269 | } 270 | 271 | mzd_t** mpc_const_mat_mul_l(mzd_t** result, mzd_t const* matrix, mzd_t** vector, unsigned sc) { 272 | for (unsigned i = 0; i < sc; ++i) { 273 | mzd_mul_vl(result[i], vector[i], matrix); 274 | } 275 | return result; 276 | } 277 | 278 | void mpc_copy(mzd_t** out, mzd_t* const* in, unsigned sc) { 279 | for (unsigned i = 0; i < sc; ++i) { 280 | mzd_local_copy(out[i], in[i]); 281 | } 282 | } 283 | 284 | mzd_t* mpc_reconstruct_from_share(mzd_t* dst, mzd_t** shared_vec) { 285 | if (!dst) { 286 | dst = mzd_local_init_ex(shared_vec[0]->nrows, shared_vec[0]->ncols, false); 287 | } 288 | mzd_xor(dst, shared_vec[0], shared_vec[1]); 289 | return mzd_xor(dst, dst, shared_vec[2]); 290 | } 291 | 292 | void mpc_print(mzd_t** shared_vec) { 293 | mzd_t* r = mpc_reconstruct_from_share(NULL, shared_vec); 294 | mzd_print(r); 295 | mzd_local_free(r); 296 | } 297 | 298 | void mpc_free(mzd_t** vec, unsigned sc) { 299 | (void)sc; 300 | mzd_local_free_multiple(vec); 301 | free(vec); 302 | } 303 | 304 | mzd_t** mpc_init_empty_share_vector(rci_t n, unsigned sc) { 305 | mzd_t** s = malloc(sc * sizeof(mzd_t*)); 306 | mzd_local_init_multiple(s, sc, 1, n); 307 | return s; 308 | } 309 | 310 | mzd_t** mpc_init_random_vector(rci_t n, unsigned sc) { 311 | mzd_t** s = malloc(sc * sizeof(mzd_t*)); 312 | mzd_local_init_multiple_ex(s, sc, 1, n, false); 313 | for (unsigned i = 0; i < sc; ++i) { 314 | mzd_randomize_ssl(s[i]); 315 | } 316 | return s; 317 | } 318 | 319 | mzd_t** mpc_init_plain_share_vector(mzd_t const* v) { 320 | mzd_t** s = malloc(3 * sizeof(mzd_t*)); 321 | mzd_local_init_multiple_ex(s, 3, 1, v->ncols, false); 322 | for (unsigned i = 0; i < 3; ++i) { 323 | mzd_local_copy(s[i], v); 324 | } 325 | 326 | return s; 327 | } 328 | 329 | mzd_t** mpc_init_share_vector(mzd_t const* v) { 330 | mzd_t** s = malloc(3 * sizeof(mzd_t*)); 331 | mzd_local_init_multiple_ex(s, 3, 1, v->ncols, false); 332 | 333 | mzd_randomize_ssl(s[0]); 334 | mzd_randomize_ssl(s[1]); 335 | 336 | mzd_xor(s[2], s[0], s[1]); 337 | mzd_xor(s[2], s[2], v); 338 | 339 | return s; 340 | } 341 | -------------------------------------------------------------------------------- /timing/graphs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import argparse 4 | import h5py 5 | import numpy as np 6 | import matplotlib 7 | import matplotlib.ticker as plticker 8 | import matplotlib.pyplot as plt 9 | import pandas as pd 10 | import seaborn as sns 11 | import math 12 | from operator import itemgetter 13 | import json 14 | import os.path 15 | 16 | 17 | # from ZKBoo (SHA-256, 219 rounds) 18 | mpc_sha256_proof = 187 19 | mpc_sha256_verify = 89 20 | mpc_sha256_size = 1368312 / 1024.0 21 | 22 | figsize=(10, 10 * 3 / 4.0) 23 | 24 | strings = { 25 | 'FS': '${\sf Fish}$', 26 | 'BG': '${\sf Begol}$', 27 | 'Verify': '${\sf Verify}$', 28 | 'Sign': '${\sf Sign}$' 29 | } 30 | 31 | class ScalarFormatterLim(plticker.ScalarFormatter): 32 | 33 | def __init__(self, minval, maxval, base, *args, **kwargs): 34 | self.minval = minval 35 | self.maxval = maxval 36 | self.base = base 37 | super(ScalarFormatterLim, self).__init__(*args, **kwargs) 38 | 39 | def pprint_val(self, value): 40 | if (value >= self.minval and value < self.maxval) or int(value) % self.base == 0: 41 | return super(ScalarFormatterLim, self).pprint_val(value) 42 | return '' 43 | 44 | 45 | class MultiScalarFormatterLim(plticker.ScalarFormatter): 46 | 47 | def __init__(self, minvals, maxvals, bases, *args, **kwargs): 48 | self.minval = minvals 49 | self.maxval = maxvals 50 | self.base = bases 51 | self.len = len(bases) 52 | 53 | assert len(minvals) == len(maxvals) == len(bases) 54 | 55 | super(MultiScalarFormatterLim, self).__init__(*args, **kwargs) 56 | 57 | def pprint_val(self, value): 58 | for i in range(self.len): 59 | if (value >= self.minval[i] and value < self.maxval[i]) and int(value) % self.base[i] == 0: 60 | return super(MultiScalarFormatterLim, self).pprint_val(value) 61 | return '' 62 | 63 | 64 | def lookup_style(style, *args): 65 | for a in args: 66 | if a in style: 67 | style = style[a] 68 | else: 69 | return {} 70 | return style 71 | 72 | 73 | def compute_sign(data): 74 | return np.sum(data[:, 3:8] / 1000, axis=1) 75 | 76 | 77 | def compute_verify(data): 78 | return np.sum(data[:, 8:12] / 1000, axis=1) 79 | 80 | 81 | def round_up(x, f=5.0): 82 | return max(math.ceil(x / f) * f + f / 2.0, 0) 83 | 84 | 85 | def round_down(x, f=5.0): 86 | return max(math.floor(x / f) * f - f / 2.0, 0) 87 | 88 | 89 | def round_up_log(x): 90 | return round_up(2**(math.ceil(4 * math.log(x, 2)) / 4), f=4.0) 91 | 92 | 93 | def round_down_log(x): 94 | return round_down(x, 10.0) 95 | 96 | 97 | def pick_5(size, sign, verify, labels): 98 | if len(labels) <= 5: 99 | return size, sign, verify, labels 100 | 101 | # always remove first and last one 102 | del size[-1] 103 | del sign[-1] 104 | del verify[-1] 105 | del labels[-1] 106 | del size[0] 107 | del sign[0] 108 | del verify[0] 109 | del labels[0] 110 | 111 | if len(labels) <= 5: 112 | return size, sign, verify, labels 113 | 114 | l = len(labels) 115 | s = len(labels) / 5 116 | 117 | return size[0:l:s], sign[0:l:s], verify[0:l:s], labels[0:l:s] 118 | 119 | 120 | def pick_interesting(size, sign, verify, labels): 121 | new_size = [] 122 | new_sign = [] 123 | new_verify = [] 124 | new_labels = [] 125 | rounds = set() 126 | 127 | for i in range(len(labels)): 128 | m, r = labels[i].split('-') 129 | if r in rounds: 130 | continue 131 | 132 | rounds.add(r) 133 | new_size.append(size[i]) 134 | new_sign.append(sign[i]) 135 | new_verify.append(verify[i]) 136 | new_labels.append(labels[i]) 137 | 138 | return new_size, new_sign, new_verify, new_labels 139 | 140 | 141 | def prepare_data(data, labels): 142 | size = data[:, 3] 143 | sign = data[:, 1] 144 | verify = data[:, 2] 145 | return pick_interesting(size, sign, verify, labels) 146 | 147 | 148 | class Annotation(object): 149 | def __init__(self, label, point, color, **style): 150 | self.label = label 151 | self.point = point 152 | self.style = {'horizontalalignment': 'left', 'xytext': (0,5), 'textcoords': 'offset points', 153 | 'fontsize': 8} 154 | self.color = color 155 | 156 | if style is not None: 157 | self.style.update(style) 158 | 159 | def plot(self, ax): 160 | ax.plot([self.point[0]], [self.point[1]], marker='o', color=self.color, linestyle='', 161 | markersize=4) 162 | if self.label is not None: 163 | ax.annotate(self.label, xy=self.point, **self.style) 164 | 165 | 166 | def create_graph(prefix, fis_n, bg_n, fis_k, bg_k, fis_data, bg_data, fis_labels, bg_labels, 167 | fis_annotate=None, bg_annotate=None, include_sha=True, style={}, **kwargs): 168 | colors = sns.color_palette('Greys_d', n_colors=5) 169 | annotation_color = colors[0] 170 | annotation_color_e = 'r' 171 | annotation_color_b = 'g' 172 | 173 | dataframes = {} 174 | annotate = [] 175 | 176 | t_fis_size, t_fis_sign, t_fis_verify, t_fis_labels = prepare_data(fis_data, fis_labels) 177 | if bg_data is not None: 178 | t_bg_size, t_bg_sign, t_bg_verify, t_bg_labels = prepare_data(bg_data, bg_labels) 179 | 180 | if fis_annotate is not None: 181 | fis_index = t_fis_labels.index(fis_annotate) 182 | else: 183 | fis_index = len(t_fis_labels) // 2 184 | 185 | if bg_data is not None: 186 | if bg_annotate is not None: 187 | bg_index = t_bg_labels.index(bg_annotate) 188 | else: 189 | bg_index = len(t_bg_labels) // 2 190 | 191 | t_fis_labels = ['{0}-{1}-{2}'.format(fis_n, fis_k, l) for l in t_fis_labels] 192 | if bg_data is not None: 193 | t_bg_labels = ['{0}-{1}-{2}'.format(bg_n, bg_k, l) for l in t_bg_labels] 194 | 195 | dataframes['fis_sign_{0}'.format(fis_n)] = pd.Series(t_fis_sign, index=t_fis_labels) 196 | dataframes['fis_verify_{0}'.format(fis_n)] = pd.Series(t_fis_verify, index=t_fis_labels) 197 | dataframes['fis_size_{0}'.format(fis_n)] = pd.Series(t_fis_size, index=t_fis_labels) 198 | if bg_data is not None: 199 | dataframes['bg_sign_{0}'.format(bg_n)] = pd.Series(t_bg_sign, index=t_bg_labels) 200 | dataframes['bg_verify_{0}'.format(bg_n)] = pd.Series(t_bg_verify, index=t_bg_labels) 201 | dataframes['bg_size_{0}'.format(bg_n)] = pd.Series(t_bg_size, index=t_bg_labels) 202 | 203 | fis_min_index = t_fis_size.index(min(t_fis_size)) 204 | fis_max_index = t_fis_size.index(max(t_fis_size)) 205 | if bg_data is not None: 206 | bg_min_index = t_bg_size.index(min(t_bg_size)) 207 | bg_max_index = t_bg_size.index(max(t_bg_size)) 208 | 209 | 210 | def annotate_and_print(scheme, labels, size, sign, verify, index, color=annotation_color_e): 211 | cstyle = lookup_style(style, 'default', scheme, labels[index]) 212 | 213 | annotate.append(Annotation(labels[index], (size[index], sign[index]), color, **cstyle)) 214 | annotate.append(Annotation(None, (size[index], verify[index]), color, **cstyle)) 215 | print("Annotating {} {}: size={}, sign={}, verify={}".format(scheme, labels[index], 216 | size[index] * 1024, sign[index], verify[index])) 217 | 218 | annotate_and_print("Fish", t_fis_labels, t_fis_size, t_fis_sign, t_fis_verify, fis_min_index) 219 | annotate_and_print("Fish", t_fis_labels, t_fis_size, t_fis_sign, t_fis_verify, fis_max_index) 220 | annotate_and_print("Fish", t_fis_labels, t_fis_size, t_fis_sign, t_fis_verify, fis_index, 221 | color=annotation_color_b) 222 | 223 | if bg_data is not None: 224 | annotate_and_print("Begol", t_bg_labels, t_bg_size, t_bg_sign, t_bg_verify, bg_min_index) 225 | annotate_and_print("Begol", t_bg_labels, t_bg_size, t_bg_sign, t_bg_verify, bg_max_index) 226 | annotate_and_print("Begol", t_bg_labels, t_bg_size, t_bg_sign, t_bg_verify, bg_index, 227 | color=annotation_color_b) 228 | 229 | combined_time = t_fis_sign + t_fis_verify 230 | combined_size = t_fis_size 231 | if bg_data is not None: 232 | combined_time += t_bg_sign + t_bg_verify 233 | combined_size += t_bg_size 234 | 235 | if include_sha and 'sha_proof' in kwargs and 'sha_verify' in kwargs and 'sha_size' in kwargs: 236 | sha_proof = kwargs['sha_proof'] 237 | sha_verify = kwargs['sha_verify'] 238 | sha_size = kwargs['sha_size'] 239 | 240 | annotate.append(Annotation('SHA256 proof', 241 | (sha_size, sha_proof), 242 | annotation_color, horizontalalignment='right')) 243 | annotate.append(Annotation('SHA256 verify', 244 | (sha_size, sha_verify), 245 | annotation_color, horizontalalignment='right')) 246 | 247 | combined_time += [sha_proof, sha_verify] 248 | combined_size += [sha_size] 249 | 250 | ylim = (0, round_up_log(max(combined_time))) 251 | xlim = (round_down_log(min(combined_size)), round_up_log(max(combined_size))) 252 | 253 | df = pd.DataFrame(dataframes) 254 | df.sort_values(by=[k for k in dataframes.keys() if '_size_' in k], inplace=True) 255 | 256 | plt.figure(figsize=figsize) 257 | 258 | args = {'logy': True, 'logx': True, 'linewidth': 1, 'ax': None} 259 | args['ax'] = df.plot(x='fis_size_{0}'.format(fis_n), y='fis_sign_{0}'.format(fis_n), 260 | label=('{Sign} ({FS})' + (' n={0}' if bg_n != fis_n else '')).format(fis_n, **strings), 261 | color=colors[-1], linestyle='--', **args) 262 | df.plot(x='fis_size_{0}'.format(fis_n), y='fis_verify_{0}'.format(fis_n), 263 | label=('{Verify} ({FS})' + (' n={0}' if bg_n != fis_n else '')).format(fis_n, **strings), 264 | color=colors[-1], linestyle=':', **args) 265 | if bg_data is not None: 266 | df.plot(x='bg_size_{0}'.format(bg_n), y='bg_sign_{0}'.format(bg_n), 267 | label=('{Sign} ({BG})' + (' n={0}' if bg_n != fis_n else '')).format(bg_n, **strings), 268 | color=colors[0], linestyle='--', **args) 269 | df.plot(x='bg_size_{0}'.format(bg_n), y='bg_verify_{0}'.format(bg_n), 270 | label=('{Verify} ({BG})' + (' n={0}' if bg_n != fis_n else '')).format(bg_n, **strings), 271 | color=colors[0], linestyle=':', **args) 272 | 273 | ax = args['ax'] 274 | for a in annotate: 275 | a.plot(ax) 276 | 277 | # title and labels 278 | ax.set_title('Runtime vs. Signature Size, [n]-[k]-[m]-[r]' + (', n={0}'.format(bg_n) if bg_n == fis_n else '')) 279 | ax.set_ylabel('Time [ms]') 280 | ax.set_xlabel('Size [kB]') 281 | 282 | # legend 283 | handles, labels = ax.get_legend_handles_labels() 284 | plt.legend(handles, labels, loc='lower right', prop=lookup_style(style, 'legend', 'n={0}'.format(bg_n))) 285 | 286 | # limits 287 | ax.set_xlim(xlim) 288 | ax.set_ylim(ylim) 289 | 290 | # grid and ticks 291 | ax.xaxis.set_major_locator(plticker.MultipleLocator(50)) 292 | ax.yaxis.set_major_locator(plticker.MultipleLocator(10 if bg_n == 128 else 50)) 293 | ax.xaxis.set_major_formatter(MultiScalarFormatterLim([0, 200, 600, 1000], [200, 600, 1000, 10000], 294 | [50, 100, 200, 500])) 295 | if bg_n == 128: 296 | ax.yaxis.set_major_formatter(ScalarFormatterLim(0, 50, 100)) 297 | else: 298 | ax.yaxis.set_major_formatter(MultiScalarFormatterLim([0, 200, 600, 1000], [200, 600, 1000, 10000], 299 | [50, 100, 200, 500])) 300 | 301 | ax.grid(True, axis='y', which='both') 302 | 303 | plt.savefig('{0}.eps'.format(prefix)) 304 | plt.savefig('{0}.pdf'.format(prefix)) 305 | 306 | 307 | def create_omp_graph(prefix, n, k, data, size, labels, max_num_threads, title=''): 308 | datadict = {'1 thread' if not i else '{0} threads'.format(i + 1): 309 | pd.Series(data[i], index=labels) for i in range(max_num_threads)} 310 | datadict['size'] = pd.Series(size, index=labels) 311 | 312 | df = pd.DataFrame(datadict) 313 | df.sort_values(by='size', inplace=True) 314 | 315 | plt.figure(figsize=figsize) 316 | 317 | colors = sns.color_palette(n_colors=max_num_threads) 318 | ax = None 319 | for i in range(max_num_threads): 320 | ax = df.plot(y='1 thread' if not i else '{0} threads'.format(i + 1), x='size', legend=True, ax=ax) 321 | 322 | # title and labels 323 | # ax.set_title('Parallel Execution with OpenMP {0}'.format(title)) 324 | ax.set_ylabel('Time [ms]') 325 | ax.set_xlabel('Size [kB]') 326 | 327 | # grid 328 | ax.yaxis.set_minor_locator(plticker.AutoMinorLocator(4)) 329 | ax.grid(True, axis='y', which='both') 330 | 331 | plt.savefig('{0}-{1}-{2}.eps'.format(prefix, n, k)) 332 | plt.savefig('{0}-{1}-{2}.pdf'.format(prefix, n, k)) 333 | 334 | 335 | def fix_h5py_strings(strings): 336 | def f(s): 337 | if isinstance(s, bytes): 338 | return s.decode('utf-8') 339 | else: 340 | return s 341 | 342 | return [f(s) for s in strings] 343 | 344 | 345 | def create_omp_graphs(args, style=None): 346 | prefix = args.prefix 347 | n = args.bg_blocksize 348 | k = args.bg_keysize 349 | max_num_threads = args.threads 350 | 351 | labels = None 352 | all_fis_sign = [] 353 | all_fis_verify = [] 354 | all_bg_sign = [] 355 | all_bg_verify = [] 356 | all_fis_size = [] 357 | all_bg_size = [] 358 | 359 | for threads in range(1, 1 + max_num_threads): 360 | with h5py.File('{0}-{1}-{2}-{3}.mat'.format(prefix, threads, n, k), 'r') as timings: 361 | ol = fix_h5py_strings(list(timings.get('labels'))) 362 | 363 | fis_sum = np.array(timings.get('fis_mean')) 364 | if timings.get('bg_mean') is not None: 365 | bg_sum = np.array(timings.get('bg_mean')) 366 | else: 367 | bg_sum = None 368 | 369 | size, sign, verify, l = prepare_data(fis_sum[2:], ol[2:]) 370 | all_fis_sign.append(sign) 371 | all_fis_verify.append(verify) 372 | all_fis_size.append(size) 373 | 374 | if bg_sum is not None: 375 | size, sign, verify, l = prepare_data(bg_sum[2:], ol[2:]) 376 | all_bg_sign.append(sign) 377 | all_bg_verify.append(verify) 378 | all_bg_size.append(size) 379 | 380 | if labels is None: 381 | labels = l 382 | 383 | create_omp_graph('{0}-fis-sign'.format(prefix), n, k, all_fis_sign, all_fis_size[0], labels, 384 | max_num_threads, title='(Sign)') 385 | create_omp_graph('{0}-fis-verify'.format(prefix), n, k, all_fis_verify, all_fis_size[0], labels, 386 | max_num_threads, title='(Verify)') 387 | if len(all_bg_sign): 388 | create_omp_graph('{0}-bg-sign'.format(prefix), n, k, all_bg_sign, all_bg_size[0], labels, 389 | max_num_threads, title='(Sign)') 390 | create_omp_graph('{0}-bg-verify'.format(prefix), n, k, all_bg_verify, all_bg_size[0], labels, 391 | max_num_threads, title='(Verify)') 392 | 393 | 394 | def create_graphs(args, style=None): 395 | prefix = args.prefix 396 | fis_n = args.fs_blocksize 397 | fis_k = args.fs_keysize 398 | bg_n = args.bg_blocksize 399 | bg_k = args.bg_keysize 400 | 401 | with h5py.File('{0}-{1}-{2}.mat'.format(prefix, fis_n, fis_k), 'r') as timings: 402 | fis_labels = fix_h5py_strings(list(timings.get('labels'))) 403 | fis_sum = np.array(timings.get('fis_mean')) 404 | 405 | if os.path.exists('{0}-{1}-{2}.mat'.format(prefix, bg_n, bg_k)): 406 | with h5py.File('{0}-{1}-{2}.mat'.format(prefix, bg_n, bg_k), 'r') as timings: 407 | if timings.get('bg_mean') is not None: 408 | bg_labels = fix_h5py_strings(list(timings.get('labels'))) 409 | bg_sum = np.array(timings.get('bg_mean')) 410 | else: 411 | bg_labels = None 412 | bg_sum = None 413 | 414 | create_graph('{0}'.format(prefix), fis_n, bg_n, fis_k, bg_k, fis_sum, bg_sum, fis_labels, 415 | bg_labels, args.fs_annotate, args.bg_annotate, style=style, sha_size=args.sha_size, 416 | sha_verify=args.sha_verify, sha_proof=args.sha_proof, include_sha=args.annotate_sha) 417 | 418 | 419 | def create_qh_graphs(args, style=None): 420 | prefix = args.prefix 421 | bg_n = args.bg_blocksize 422 | bg_k = args.bg_keysize 423 | 424 | dataframes = {} 425 | annotate = [] 426 | 427 | with h5py.File('{0}-{1}-{2}.mat'.format(prefix, bg_n, bg_k), 'r') as timings: 428 | bg_labels = fix_h5py_strings(list(timings.get('labels'))) 429 | bg_sum = np.array(timings.get('bg_mean')) 430 | 431 | bg_size, bg_sign, bg_verify, bg_label = prepare_data(bg_sum, bg_labels) 432 | dataframes['bg_sign'] = pd.Series(bg_sign, index=bg_label) 433 | dataframes['bg_verify'] = pd.Series(bg_verify, index=bg_label) 434 | dataframes['bg_size'] = pd.Series(bg_size, index=bg_label) 435 | 436 | min_idx = bg_size.index(min(bg_size)) 437 | max_idx = bg_size.index(max(bg_size)) 438 | 439 | xlim = [min(bg_size), max(bg_size)] 440 | ylim = [0, max(bg_sign)] 441 | 442 | if args.annotate_extreme: 443 | min_label = '{0}-{1}-{2}'.format(bg_n, bg_k, bg_label[min_idx]) 444 | min_style = lookup_style(style, 'omp', 'BG', min_label) 445 | max_label = '{0}-{1}-{2}'.format(bg_n, bg_k, bg_label[max_idx]) 446 | max_style = lookup_style(style, 'omp', 'BG', max_label) 447 | 448 | annotate.append(Annotation(min_label, 449 | (bg_size[min_idx], bg_sign[min_idx]), 'r', **min_style)) 450 | annotate.append(Annotation(max_label, 451 | (bg_size[max_idx], bg_sign[max_idx]), 'r', **max_style)) 452 | 453 | if args.bg_annotate: 454 | try: 455 | idx = bg_label.index(args.bg_annotate) 456 | 457 | alabel = '{0}-{1}-{2}'.format(bg_n, bg_k, bg_label[idx]) 458 | astyle = lookup_style(style, 'omp', 'BG', alabel) 459 | 460 | annotate.append(Annotation(alabel, 461 | (bg_size[idx], bg_sign[idx]), 'g', **astyle)) 462 | except ValueError: 463 | pass 464 | 465 | fs_annotations = args.fs_annotate.split(' ') 466 | for n in args.fsblocksizes: 467 | with h5py.File('{0}-{1}-{2}.mat'.format(prefix, n, n), 'r') as timings: 468 | fis_labels = fix_h5py_strings(list(timings.get('labels'))) 469 | fis_sum = np.array(timings.get('fis_mean')) 470 | 471 | size, sign, verify, label = prepare_data(fis_sum, fis_labels) 472 | 473 | dataframes['fis_sign_{0}'.format(n)] = pd.Series(sign, index=label) 474 | dataframes['fis_verify_{0}'.format(n)] = pd.Series(verify, index=label) 475 | dataframes['fis_size_{0}'.format(n)] = pd.Series(size, index=label) 476 | 477 | min_idx = size.index(min(size)) 478 | max_idx = size.index(max(size)) 479 | 480 | xlim = [min(size + xlim), max(size + xlim)] 481 | ylim = [0, max(sign + ylim)] 482 | 483 | if args.annotate_extreme: 484 | min_label = '{0}-{1}-{2}'.format(n, n, label[min_idx]) 485 | min_style = lookup_style(style, 'omp', 'FS', min_label) 486 | max_label = '{0}-{1}-{2}'.format(n, n, label[max_idx]) 487 | max_style = lookup_style(style, 'omp', 'FS', max_label) 488 | 489 | annotate.append(Annotation(min_label, 490 | (size[min_idx], sign[min_idx]), 'r', **min_style)) 491 | annotate.append(Annotation(max_label, 492 | (size[max_idx], sign[max_idx]), 'r', **max_style)) 493 | 494 | if args.fs_annotate: 495 | idx = None 496 | try: 497 | for annot in fs_annotations: 498 | if annot.startswith('{0}-{0}'.format(n)): 499 | idx = label.index('-'.join(annot.split('-')[2:])) 500 | except ValueError: 501 | pass 502 | 503 | if idx is not None: 504 | alabel = '{0}-{1}-{2}'.format(n, n, label[idx]) 505 | astyle = lookup_style(style, 'omp', 'FS', alabel) 506 | 507 | annotate.append(Annotation(alabel, 508 | (size[idx], sign[idx]), 'g', **astyle)) 509 | 510 | 511 | xlim = (round_down_log(xlim[0]), round_up_log(xlim[1])) 512 | ylim = (0, round_up_log(ylim[1])) 513 | 514 | colors = sns.color_palette('Greys_d', n_colors=len(args.fsblocksizes) + 1) 515 | annotation_color = 'g' 516 | 517 | df = pd.DataFrame(dataframes) 518 | df.sort_values(by=[k for k in dataframes.keys() if '_size' in k], inplace=True) 519 | 520 | plt.figure(figsize=figsize) 521 | 522 | pargs = {'xlim': xlim, 'ylim': ylim, 'logx': True, 'logy': True, 'ax': None} 523 | pargs['ax'] = df.plot(x='bg_size', y='bg_sign', label='{BG}, $Q_H = 2^{{60}}, \ldots, 2^{{100}}$'.format(**strings), color=colors[0], linestyle='-', 524 | **pargs) 525 | 526 | qhs = [60, 80, 100, 120] 527 | linestyles = ['-.', ':', '--'] 528 | for i in range(len(args.fsblocksizes)): 529 | n = args.fsblocksizes[i] 530 | qh = qhs[i] 531 | df.plot(x='fis_size_{0}'.format(n), y='fis_sign_{0}'.format(n), label='{FS}, $Q_H = 2^{{{0}}}$'.format(qh, **strings), 532 | color=colors[i], linestyle=linestyles[i % len(linestyles)], **pargs) 533 | 534 | ax = pargs['ax'] 535 | for a in annotate: 536 | a.plot(ax) 537 | 538 | # title and labels 539 | # ax.set_title('Runtime vs. Signature size with increasing q_H'.format(k)) 540 | ax.set_ylabel('Time [ms]') 541 | ax.set_xlabel('Size [kB]') 542 | 543 | # legend 544 | handles, labels = ax.get_legend_handles_labels() 545 | plt.legend(handles, labels, loc='upper right') 546 | 547 | # grid and ticks 548 | ax.xaxis.set_major_locator(plticker.MultipleLocator(50)) 549 | ax.yaxis.set_major_locator(plticker.MultipleLocator(25)) 550 | ax.xaxis.set_major_formatter(ScalarFormatterLim(0, 200, 100)) 551 | ax.yaxis.set_major_formatter(ScalarFormatterLim(0, 100, 100)) 552 | ax.grid(True, axis='y', which='both') 553 | 554 | plt.savefig('qh-{0}.eps'.format(prefix)) 555 | plt.savefig('qh-{0}.pdf'.format(prefix)) 556 | 557 | 558 | def main(): 559 | sns.set(style='white', context='paper', font='CMU Serif') 560 | sns.set_style('white', { 561 | 'legend.frameon': True, 562 | 'text.usetex': True, 563 | 'font.family': 'CMU Serif', 564 | 'font.serif': ['CMU Serif'] 565 | }) 566 | 567 | parser = argparse.ArgumentParser(description='Create graphs') 568 | parser.add_argument('-p', '--prefix', help='prefix of mat files', 569 | default='timings') 570 | parser.add_argument('-s', '--style', help='JSON file with style info', default='style.json') 571 | subparsers = parser.add_subparsers() 572 | 573 | thread_parser = subparsers.add_parser('omp', help='OpenMP graphs') 574 | thread_parser.set_defaults(func=create_omp_graphs) 575 | thread_parser.add_argument('-t', '--threads', help='# of OpenMP threads', type=int, default=4) 576 | thread_parser.add_argument('--bg-keysize', help='LowMC key size for BG', 577 | choices=[128, 192, 256, 384, 448, 512], required=True, type=int) 578 | thread_parser.add_argument('--bg-blocksize', help='LowMC block size for BG', 579 | choices=[128, 192, 256, 384, 448, 512], required=True, type=int) 580 | 581 | default_parser = subparsers.add_parser('default', help='Size vs Runtime graphs') 582 | default_parser.set_defaults(func=create_graphs) 583 | default_parser.add_argument('--bg-keysize', help='LowMC key size for BG', 584 | choices=[128, 192, 256, 384, 448, 512], required=True, type=int) 585 | default_parser.add_argument('--bg-blocksize', help='LowMC block size for BG', 586 | choices=[128, 192, 256, 384, 448, 512], required=True, type=int) 587 | default_parser.add_argument('--fs-keysize', help='LowMC key size for FS', 588 | choices=[128, 192, 256, 384, 448, 512], required=True, type=int) 589 | default_parser.add_argument('--fs-blocksize', help='LowMC block size for FS', 590 | choices=[128, 192, 256, 384, 448, 512], required=True, type=int) 591 | default_parser.add_argument('--bg-annotate', help='Pick BG instance to annotate', 592 | dest='bg_annotate') 593 | default_parser.add_argument('--fs-annotate', help='Pick FS instance to annotate', 594 | dest='fs_annotate') 595 | default_parser.add_argument('--sha-size', help='Size of the proof for SHA-256', 596 | dest='sha_size', default=mpc_sha256_size, type=float) 597 | default_parser.add_argument('--sha-verify', help='Runtime of the proof verification for SHA-256', 598 | dest='sha_verify', default=mpc_sha256_verify, type=float) 599 | default_parser.add_argument('--sha-proof', help='Runtime of the proof generation for SHA-256', 600 | dest='sha_proof', default=mpc_sha256_proof, type=float) 601 | default_parser.add_argument('--no-sha-annotation', help='Annotate SHA', dest='annotate_sha', 602 | action='store_false', default=True) 603 | 604 | qh_parser = subparsers.add_parser('qH', help='graphs for rising q_H') 605 | qh_parser.set_defaults(func=create_qh_graphs) 606 | qh_parser.add_argument('--bg-keysize', help='LowMC key size for BG', 607 | choices=[128, 192, 256, 384, 448, 512], required=True, type=int) 608 | qh_parser.add_argument('--bg-blocksize', help='LowMC block size for BG', 609 | choices=[128, 192, 256, 384, 448, 512], required=True, type=int) 610 | qh_parser.add_argument('--bg-annotate', help='Pick BG instance to annotate', dest='bg_annotate') 611 | qh_parser.add_argument('--fs-annotate', help='Pick FS instance to annotate', dest='fs_annotate') 612 | qh_parser.add_argument('--annotate-extreme', help='Annotate min/max points', 613 | dest='annotate_extreme', default=False, action='store_true') 614 | qh_parser.add_argument('fsblocksizes', help='LowMC block size for FS', type=int, 615 | choices=[128, 192, 256, 384, 448, 512], nargs='+') 616 | 617 | args = parser.parse_args() 618 | 619 | style = None 620 | if args.style: 621 | with open(args.style, 'r') as s: 622 | style = json.load(s) 623 | 624 | args.func(args, style) 625 | 626 | 627 | if __name__ == '__main__': 628 | main() 629 | 630 | # vim: tw=100 sts=2 sw=2 et 631 | -------------------------------------------------------------------------------- /mpc_lowmc.c: -------------------------------------------------------------------------------- 1 | #include "mpc_lowmc.h" 2 | #include "hashing_util.h" 3 | #include "io.h" 4 | #include "lowmc_pars.h" 5 | #include "mpc.h" 6 | #include "mzd_additional.h" 7 | 8 | #include 9 | #include 10 | 11 | #ifdef WITH_OPT 12 | #include "simd.h" 13 | #endif 14 | 15 | typedef struct { 16 | mzd_t* x0m[SC_PROOF]; 17 | mzd_t* x1m[SC_PROOF]; 18 | mzd_t* x2m[SC_PROOF]; 19 | mzd_t* r0m[SC_PROOF]; 20 | mzd_t* r1m[SC_PROOF]; 21 | mzd_t* r2m[SC_PROOF]; 22 | mzd_t* x0s[SC_PROOF]; 23 | mzd_t* r0s[SC_PROOF]; 24 | mzd_t* x1s[SC_PROOF]; 25 | mzd_t* r1s[SC_PROOF]; 26 | mzd_t* v[SC_PROOF]; 27 | 28 | mzd_t** storage; 29 | } sbox_vars_t; 30 | 31 | static sbox_vars_t* sbox_vars_init(sbox_vars_t* vars, rci_t n, unsigned sc); 32 | static void sbox_vars_clear(sbox_vars_t* vars); 33 | 34 | typedef int (*BIT_and_ptr)(BIT*, BIT*, BIT*, view_t*, int*, unsigned, unsigned); 35 | typedef int (*and_ptr)(mzd_t**, mzd_t**, mzd_t**, mzd_t**, view_t*, mzd_t*, unsigned, mzd_t**); 36 | 37 | unsigned char* proof_to_char_array(mpc_lowmc_t* lowmc, proof_t* proof, unsigned* len, 38 | bool store_ch) { 39 | unsigned first_view_bytes = lowmc->k / 8; 40 | unsigned full_mzd_size = lowmc->n / 8; 41 | unsigned single_mzd_bytes = ((3 * lowmc->m) + 7) / 8; 42 | unsigned mzd_bytes = lowmc->r * single_mzd_bytes + first_view_bytes + full_mzd_size; 43 | *len = 44 | NUM_ROUNDS * (COMMITMENT_LENGTH + 2 * (COMMITMENT_RAND_LENGTH + PRNG_KEYSIZE) + mzd_bytes) + 45 | (store_ch ? ((NUM_ROUNDS + 3) / 4) : 0); 46 | unsigned char* result = (unsigned char*)malloc(*len * sizeof(unsigned char)); 47 | 48 | unsigned char* temp = result; 49 | 50 | if (store_ch) { 51 | memcpy(temp, proof->ch, (NUM_ROUNDS + 3) / 4); 52 | temp += (NUM_ROUNDS + 3) / 4; 53 | } 54 | 55 | memcpy(temp, proof->hashes, NUM_ROUNDS * COMMITMENT_LENGTH * sizeof(unsigned char)); 56 | temp += NUM_ROUNDS * COMMITMENT_LENGTH; 57 | 58 | for (unsigned i = 0; i < NUM_ROUNDS; i++) { 59 | memcpy(temp, proof->r[i][0], COMMITMENT_RAND_LENGTH * sizeof(unsigned char)); 60 | temp += COMMITMENT_RAND_LENGTH; 61 | memcpy(temp, proof->r[i][1], COMMITMENT_RAND_LENGTH * sizeof(unsigned char)); 62 | temp += COMMITMENT_RAND_LENGTH; 63 | 64 | memcpy(temp, proof->keys[i][0], PRNG_KEYSIZE * sizeof(unsigned char)); 65 | temp += PRNG_KEYSIZE; 66 | memcpy(temp, proof->keys[i][1], PRNG_KEYSIZE * sizeof(unsigned char)); 67 | temp += PRNG_KEYSIZE; 68 | 69 | unsigned char* v0; 70 | 71 | if (getChAt(proof->ch, i) != 0) { 72 | v0 = mzd_to_char_array(proof->views[i][0].s[getChAt(proof->ch, i) % 2], first_view_bytes); 73 | memcpy(temp, v0, first_view_bytes); 74 | temp += first_view_bytes; 75 | free(v0); 76 | } 77 | 78 | for (unsigned j = 1; j < 1 + lowmc->r; j++) { 79 | v0 = mzd_to_char_array(proof->views[i][j].s[0], single_mzd_bytes); 80 | 81 | memcpy(temp, v0, single_mzd_bytes); 82 | temp += single_mzd_bytes; 83 | 84 | free(v0); 85 | } 86 | 87 | v0 = mzd_to_char_array(proof->views[i][1 + lowmc->r].s[1], full_mzd_size); 88 | 89 | memcpy(temp, v0, full_mzd_size); 90 | temp += full_mzd_size; 91 | 92 | free(v0); 93 | } 94 | 95 | return result; 96 | } 97 | 98 | proof_t* proof_from_char_array(mpc_lowmc_t* lowmc, proof_t* proof, unsigned char* data, 99 | unsigned* len, bool contains_ch) { 100 | if (!proof) 101 | proof = calloc(sizeof(proof_t), 1); 102 | 103 | unsigned first_view_bytes = lowmc->k / 8; 104 | unsigned full_mzd_size = lowmc->n / 8; 105 | unsigned single_mzd_bytes = ((3 * lowmc->m) + 7) / 8; 106 | unsigned mzd_bytes = lowmc->r * single_mzd_bytes + first_view_bytes + full_mzd_size; 107 | *len = 108 | NUM_ROUNDS * (COMMITMENT_LENGTH + 2 * (COMMITMENT_RAND_LENGTH + PRNG_KEYSIZE) + mzd_bytes) + 109 | (contains_ch ? ((NUM_ROUNDS + 3) / 4) : 0); 110 | 111 | unsigned char* temp = data; 112 | 113 | if (contains_ch) { 114 | memcpy(proof->ch, temp, (NUM_ROUNDS + 3) / 4); 115 | temp += (NUM_ROUNDS + 3) / 4; 116 | } 117 | 118 | memcpy(proof->hashes, temp, NUM_ROUNDS * COMMITMENT_LENGTH * sizeof(unsigned char)); 119 | temp += NUM_ROUNDS * COMMITMENT_LENGTH; 120 | 121 | for (unsigned int i = 0; i < NUM_ROUNDS; i++) { 122 | memcpy(proof->r[i][0], temp, COMMITMENT_RAND_LENGTH * sizeof(unsigned char)); 123 | temp += COMMITMENT_RAND_LENGTH; 124 | memcpy(proof->r[i][1], temp, COMMITMENT_RAND_LENGTH * sizeof(unsigned char)); 125 | temp += COMMITMENT_RAND_LENGTH; 126 | 127 | memcpy(proof->keys[i][0], temp, PRNG_KEYSIZE * sizeof(char)); 128 | temp += PRNG_KEYSIZE; 129 | memcpy(proof->keys[i][1], temp, PRNG_KEYSIZE * sizeof(char)); 130 | temp += PRNG_KEYSIZE; 131 | proof->views[i] = malloc((2 + lowmc->r) * sizeof(view_t)); 132 | 133 | const unsigned char ch = getChAt(proof->ch, i); 134 | if (ch == 0) { 135 | proof->views[i][0].s[0] = mzd_init_random_vector_from_seed(proof->keys[i][0], lowmc->k); 136 | proof->views[i][0].s[1] = mzd_init_random_vector_from_seed(proof->keys[i][1], lowmc->k); 137 | } else if (ch == 1) { 138 | proof->views[i][0].s[0] = mzd_init_random_vector_from_seed(proof->keys[i][0], lowmc->k); 139 | proof->views[i][0].s[1] = mzd_from_char_array(temp, first_view_bytes, lowmc->k); 140 | temp += first_view_bytes; 141 | } else { 142 | proof->views[i][0].s[0] = mzd_from_char_array(temp, first_view_bytes, lowmc->k); 143 | proof->views[i][0].s[1] = mzd_init_random_vector_from_seed(proof->keys[i][1], lowmc->k); 144 | temp += first_view_bytes; 145 | } 146 | proof->views[i][0].s[2] = NULL; 147 | for (unsigned j = 1; j < 1 + lowmc->r; j++) { 148 | proof->views[i][j].s[0] = mzd_local_init(1, lowmc->n); 149 | proof->views[i][j].s[1] = mzd_from_char_array(temp, single_mzd_bytes, lowmc->n); 150 | temp += single_mzd_bytes; 151 | proof->views[i][j].s[2] = NULL; 152 | } 153 | proof->views[i][1 + lowmc->r].s[0] = mzd_local_init(1, lowmc->n); 154 | proof->views[i][1 + lowmc->r].s[1] = mzd_from_char_array(temp, full_mzd_size, lowmc->n); 155 | temp += full_mzd_size; 156 | proof->views[i][1 + lowmc->r].s[2] = NULL; 157 | } 158 | 159 | return proof; 160 | } 161 | 162 | proof_t* create_proof(proof_t* proof, mpc_lowmc_t const* lowmc, 163 | unsigned char hashes[NUM_ROUNDS][SC_PROOF][COMMITMENT_LENGTH], 164 | unsigned char ch[NUM_ROUNDS], 165 | unsigned char r[NUM_ROUNDS][SC_PROOF][COMMITMENT_RAND_LENGTH], 166 | unsigned char keys[NUM_ROUNDS][SC_PROOF][PRNG_KEYSIZE], 167 | view_t* const views[NUM_ROUNDS]) { 168 | if (!proof) 169 | proof = calloc(sizeof(proof_t), 1); 170 | 171 | const size_t num_views = 2 + lowmc->r; 172 | const size_t last_round = 1 + lowmc->r; 173 | 174 | for (unsigned int i = 0; i < NUM_ROUNDS; i++) { 175 | unsigned int a = ch[i]; 176 | unsigned int b = (a + 1) % 3; 177 | unsigned int c = (a + 2) % 3; 178 | 179 | memcpy(proof->hashes[i], hashes[i][c], COMMITMENT_LENGTH); 180 | 181 | memcpy(proof->r[i][0], r[i][a], COMMITMENT_RAND_LENGTH); 182 | memcpy(proof->r[i][1], r[i][b], COMMITMENT_RAND_LENGTH); 183 | 184 | memcpy(proof->keys[i][0], keys[i][a], PRNG_KEYSIZE); 185 | memcpy(proof->keys[i][1], keys[i][b], PRNG_KEYSIZE); 186 | 187 | proof->views[i] = malloc(num_views * sizeof(view_t)); 188 | proof->views[i][0].s[0] = views[i][0].s[a]; 189 | proof->views[i][0].s[1] = views[i][0].s[b]; 190 | proof->views[i][0].s[2] = NULL; 191 | mzd_local_free(views[i][0].s[c]); 192 | for (unsigned j = 1; j < last_round; j++) { 193 | proof->views[i][j].s[0] = views[i][j].s[b]; 194 | // we keep the reference to this pointer here and free it later 195 | // to circumvent the need for two clear functions. Note that 196 | // this reference is not serialized withing proof_to_char_array 197 | proof->views[i][j].s[1] = views[i][j].s[a]; 198 | proof->views[i][j].s[2] = NULL; 199 | mzd_local_free(views[i][j].s[c]); 200 | } 201 | proof->views[i][last_round].s[0] = NULL; 202 | proof->views[i][last_round].s[1] = views[i][last_round].s[b]; 203 | proof->views[i][last_round].s[2] = NULL; 204 | mzd_local_free(views[i][last_round].s[a]); 205 | mzd_local_free(views[i][last_round].s[c]); 206 | 207 | const unsigned int idx = i / 4; 208 | const unsigned int shift = (i % 4) << 1; 209 | 210 | proof->ch[idx] |= a << shift; 211 | } 212 | 213 | return proof; 214 | } 215 | 216 | #define bitsliced_step_1(sc) \ 217 | mpc_and_const(out, in, mask->mask, sc); \ 218 | \ 219 | mpc_and_const(vars->x0m, in, mask->x0, sc); \ 220 | mpc_and_const(vars->x1m, in, mask->x1, sc); \ 221 | mpc_and_const(vars->x2m, in, mask->x2, sc); \ 222 | mpc_and_const(vars->r0m, rvec, mask->x0, sc); \ 223 | mpc_and_const(vars->r1m, rvec, mask->x1, sc); \ 224 | mpc_and_const(vars->r2m, rvec, mask->x2, sc); \ 225 | \ 226 | mpc_shift_left(vars->x0s, vars->x0m, 2, sc); \ 227 | mpc_shift_left(vars->r0s, vars->r0m, 2, sc); \ 228 | \ 229 | mpc_shift_left(vars->x1s, vars->x1m, 1, sc); \ 230 | mpc_shift_left(vars->r1s, vars->r1m, 1, sc) 231 | 232 | #define bitsliced_step_2(sc) \ 233 | mpc_xor(vars->r2m, vars->r2m, vars->x0s, sc); \ 234 | \ 235 | mpc_xor(vars->x0s, vars->x0s, vars->x1s, sc); \ 236 | mpc_xor(vars->r1m, vars->r1m, vars->x0s, sc); \ 237 | \ 238 | mpc_xor(vars->r0m, vars->r0m, vars->x0s, sc); \ 239 | mpc_xor(vars->r0m, vars->r0m, vars->x2m, sc); \ 240 | \ 241 | mpc_shift_right(vars->x0s, vars->r2m, 2, sc); \ 242 | mpc_shift_right(vars->x1s, vars->r1m, 1, sc); \ 243 | \ 244 | mpc_xor(out, out, vars->r0m, sc); \ 245 | mpc_xor(out, out, vars->x0s, sc); \ 246 | mpc_xor(out, out, vars->x1s, sc) 247 | 248 | static void _mpc_sbox_layer_bitsliced(mzd_t** out, mzd_t* const* in, view_t* view, 249 | mzd_t* const* rvec, mask_t const* mask, 250 | sbox_vars_t const* vars) { 251 | bitsliced_step_1(SC_PROOF); 252 | 253 | mpc_and(vars->r0m, vars->x0s, vars->x1s, vars->r2m, view, 0, vars->v); 254 | mpc_and(vars->r2m, vars->x1s, vars->x2m, vars->r0s, view, 2, vars->v); 255 | mpc_and(vars->r1m, vars->x0s, vars->x2m, vars->r1s, view, 1, vars->v); 256 | 257 | bitsliced_step_2(SC_PROOF); 258 | } 259 | 260 | static void _mpc_sbox_layer_bitsliced_verify(mzd_t** out, mzd_t* const* in, view_t const* view, 261 | mzd_t* const* rvec, mask_t const* mask, 262 | sbox_vars_t const* vars) { 263 | bitsliced_step_1(SC_VERIFY); 264 | 265 | mpc_and_verify(vars->r0m, vars->x0s, vars->x1s, vars->r2m, view, mask->x2, 0, vars->v); 266 | mpc_and_verify(vars->r2m, vars->x1s, vars->x2m, vars->r0s, view, mask->x2, 2, vars->v); 267 | mpc_and_verify(vars->r1m, vars->x0s, vars->x2m, vars->r1s, view, mask->x2, 1, vars->v); 268 | 269 | bitsliced_step_2(SC_VERIFY); 270 | } 271 | 272 | #ifdef WITH_OPT 273 | #define bitsliced_mm_step_1(sc, type, and, shift_left) \ 274 | type r0m[sc] __attribute__((aligned(alignof(type)))); \ 275 | type r0s[sc] __attribute__((aligned(alignof(type)))); \ 276 | type r1m[sc] __attribute__((aligned(alignof(type)))); \ 277 | type r1s[sc] __attribute__((aligned(alignof(type)))); \ 278 | type r2m[sc] __attribute__((aligned(alignof(type)))); \ 279 | type x0s[sc] __attribute__((aligned(alignof(type)))); \ 280 | type x1s[sc] __attribute__((aligned(alignof(type)))); \ 281 | type x2m[sc] __attribute__((aligned(alignof(type)))); \ 282 | const type mx2 __attribute__((aligned(alignof(type)))) = \ 283 | *((const type*)__builtin_assume_aligned(CONST_FIRST_ROW(mask->x2), alignof(type))); \ 284 | do { \ 285 | const type mx0 __attribute__((aligned(alignof(type)))) = \ 286 | *((const type*)__builtin_assume_aligned(CONST_FIRST_ROW(mask->x0), alignof(type))); \ 287 | const type mx1 __attribute__((aligned(alignof(type)))) = \ 288 | *((const type*)__builtin_assume_aligned(CONST_FIRST_ROW(mask->x1), alignof(type))); \ 289 | \ 290 | for (unsigned int m = 0; m < (sc); ++m) { \ 291 | const type inm __attribute__((aligned(alignof(type)))) = \ 292 | *((const type*)__builtin_assume_aligned(CONST_FIRST_ROW(in[m]), alignof(type))); \ 293 | const type rvecm __attribute__((aligned(alignof(type)))) = \ 294 | *((const type*)__builtin_assume_aligned(CONST_FIRST_ROW(rvec[m]), alignof(type))); \ 295 | \ 296 | type tmp1 = (and)(inm, mx0); \ 297 | type tmp2 = (and)(inm, mx1); \ 298 | x2m[m] = (and)(inm, mx2); \ 299 | \ 300 | x0s[m] = (shift_left)(tmp1, 2); \ 301 | x1s[m] = (shift_left)(tmp2, 1); \ 302 | \ 303 | r0m[m] = tmp1 = (and)(rvecm, mx0); \ 304 | r1m[m] = tmp2 = (and)(rvecm, mx1); \ 305 | r2m[m] = (and)(rvecm, mx2); \ 306 | \ 307 | r0s[m] = (shift_left)(tmp1, 2); \ 308 | r1s[m] = (shift_left)(tmp2, 1); \ 309 | } \ 310 | } while (0) 311 | 312 | #define bitsliced_mm_step_2(sc, type, and, xor, shift_right) \ 313 | do { \ 314 | const type maskm __attribute__((aligned(alignof(type)))) = \ 315 | *((const type*)__builtin_assume_aligned(CONST_FIRST_ROW(mask->mask), alignof(type))); \ 316 | for (unsigned int m = 0; m < sc; ++m) { \ 317 | const type inm __attribute__((aligned(alignof(type)))) = \ 318 | *((const type*)__builtin_assume_aligned(CONST_FIRST_ROW(in[m]), alignof(type))); \ 319 | type* outm = __builtin_assume_aligned(CONST_FIRST_ROW(out[m]), alignof(type)); \ 320 | \ 321 | type tmp1 = (xor)(r2m[m], x0s[m]); \ 322 | type tmp2 = (xor)(x0s[m], x1s[m]); \ 323 | type tmp3 = (xor)(tmp2, r1m[m]); \ 324 | \ 325 | type mout = (and)(maskm, inm); \ 326 | \ 327 | type tmp4 = (xor)(tmp2, r0m[m]); \ 328 | tmp4 = (xor)(tmp4, x2m[m]); \ 329 | mout = (xor)(mout, tmp4); \ 330 | \ 331 | tmp2 = (shift_right)(tmp1, 2); \ 332 | mout = (xor)(mout, tmp2); \ 333 | \ 334 | tmp1 = (shift_right)(tmp3, 1); \ 335 | *outm = (xor)(mout, tmp1); \ 336 | } \ 337 | } while (0) 338 | 339 | #ifdef WITH_SSE2 340 | __attribute__((target("sse2"))) static void 341 | _mpc_sbox_layer_bitsliced_sse(mzd_t** out, mzd_t* const* in, view_t const* view, mzd_t* const* rvec, 342 | mask_t const* mask) { 343 | bitsliced_mm_step_1(SC_PROOF, __m128i, _mm_and_si128, mm128_shift_left); 344 | 345 | mpc_and_sse(r0m, x0s, x1s, r2m, view, 0); 346 | mpc_and_sse(r2m, x1s, x2m, r0s, view, 2); 347 | mpc_and_sse(r1m, x0s, x2m, r1s, view, 1); 348 | 349 | bitsliced_mm_step_2(SC_PROOF, __m128i, _mm_and_si128, _mm_xor_si128, mm128_shift_right); 350 | } 351 | 352 | __attribute__((target("sse2"))) static void 353 | _mpc_sbox_layer_bitsliced_sse_verify(mzd_t** out, mzd_t* const* in, view_t const* view, 354 | mzd_t** rvec, mask_t const* mask) { 355 | bitsliced_mm_step_1(SC_VERIFY, __m128i, _mm_and_si128, mm128_shift_left); 356 | 357 | mpc_and_verify_sse(r0m, x0s, x1s, r2m, view, mx2, 0); 358 | mpc_and_verify_sse(r2m, x1s, x2m, r0s, view, mx2, 2); 359 | mpc_and_verify_sse(r1m, x0s, x2m, r1s, view, mx2, 1); 360 | 361 | bitsliced_mm_step_2(SC_VERIFY, __m128i, _mm_and_si128, _mm_xor_si128, mm128_shift_right); 362 | } 363 | #endif 364 | 365 | #ifdef WITH_AVX2 366 | __attribute__((target("avx2"))) static void 367 | _mpc_sbox_layer_bitsliced_avx(mzd_t** out, mzd_t* const* in, view_t const* view, mzd_t* const* rvec, 368 | mask_t const* mask) { 369 | bitsliced_mm_step_1(SC_PROOF, __m256i, _mm256_and_si256, mm256_shift_left); 370 | 371 | mpc_and_avx(r0m, x0s, x1s, r2m, view, 0); 372 | mpc_and_avx(r2m, x1s, x2m, r0s, view, 2); 373 | mpc_and_avx(r1m, x0s, x2m, r1s, view, 1); 374 | 375 | bitsliced_mm_step_2(SC_PROOF, __m256i, _mm256_and_si256, _mm256_xor_si256, mm256_shift_right); 376 | } 377 | 378 | __attribute__((target("avx2"))) static void 379 | _mpc_sbox_layer_bitsliced_avx_verify(mzd_t** out, mzd_t** in, view_t const* view, 380 | mzd_t* const* rvec, mask_t const* mask) { 381 | bitsliced_mm_step_1(SC_VERIFY, __m256i, _mm256_and_si256, mm256_shift_left); 382 | 383 | mpc_and_verify_avx(r0m, x0s, x1s, r2m, view, mx2, 0); 384 | mpc_and_verify_avx(r2m, x1s, x2m, r0s, view, mx2, 2); 385 | mpc_and_verify_avx(r1m, x0s, x2m, r1s, view, mx2, 1); 386 | 387 | bitsliced_mm_step_2(SC_VERIFY, __m256i, _mm256_and_si256, _mm256_xor_si256, mm256_shift_right); 388 | } 389 | #endif 390 | #endif 391 | 392 | #if 0 393 | static int _mpc_sbox_layer(mzd_t** out, mzd_t** in, rci_t m, view_t* views, int* i, mzd_t** rvec, 394 | unsigned sc, BIT_and_ptr andBitPtr) { 395 | mpc_copy(out, in, sc); 396 | 397 | BIT* x0 = malloc(sizeof(BIT) * sc); 398 | BIT* x1 = malloc(sizeof(BIT) * sc); 399 | BIT* x2 = malloc(sizeof(BIT) * sc); 400 | BIT* r0 = malloc(sizeof(BIT) * sc); 401 | BIT* r1 = malloc(sizeof(BIT) * sc); 402 | BIT* r2 = malloc(sizeof(BIT) * sc); 403 | 404 | for (rci_t n = out[0]->ncols - 3 * m; n < out[0]->ncols; n += 3) { 405 | mpc_read_bit(x0, in, n + 0, sc); 406 | mpc_read_bit(x1, in, n + 1, sc); 407 | mpc_read_bit(x2, in, n + 2, sc); 408 | mpc_read_bit(r0, rvec, n + 0, sc); 409 | mpc_read_bit(r1, rvec, n + 1, sc); 410 | mpc_read_bit(r2, rvec, n + 2, sc); 411 | 412 | BIT tmp1[sc], tmp2[sc], tmp3[sc]; 413 | for (unsigned m = 0; m < sc; m++) { 414 | tmp1[m] = x1[m]; 415 | tmp2[m] = x0[m]; 416 | tmp3[m] = x0[m]; 417 | } 418 | if (andBitPtr(tmp1, x2, r0, views, i, n, sc) || andBitPtr(tmp2, x2, r1, views, i, n + 1, sc) || 419 | andBitPtr(tmp3, x1, r2, views, i, n + 2, sc)) { 420 | return -1; 421 | } 422 | 423 | mpc_xor_bit(tmp1, x0, sc); 424 | mpc_write_bit(out, n + 0, tmp1, sc); 425 | 426 | mpc_xor_bit(tmp2, x0, sc); 427 | mpc_xor_bit(tmp2, x1, sc); 428 | mpc_write_bit(out, n + 1, tmp2, sc); 429 | 430 | mpc_xor_bit(tmp3, x0, sc); 431 | mpc_xor_bit(tmp3, x1, sc); 432 | mpc_xor_bit(tmp3, x2, sc); 433 | mpc_write_bit(out, n + 2, tmp3, sc); 434 | } 435 | free(x0); 436 | free(x1); 437 | free(x2); 438 | free(r0); 439 | free(r1); 440 | free(r2); 441 | 442 | (*i)++; 443 | return 0; 444 | } 445 | 446 | static mzd_t** _mpc_lowmc_call(mpc_lowmc_t const* lowmc, mpc_lowmc_key_t* lowmc_key, mzd_t* p, 447 | view_t* views, mzd_t*** rvec, unsigned sc, unsigned ch, 448 | BIT_and_ptr andBitPtr, int* status) { 449 | int vcnt = 0; 450 | 451 | for (unsigned i = 0; i < sc; i++) 452 | mzd_local_copy(views[vcnt].s[i], lowmc_key->shared[i]); 453 | vcnt++; 454 | 455 | mzd_t** c = mpc_init_empty_share_vector(lowmc->n, sc); 456 | 457 | mzd_t** x = mpc_init_empty_share_vector(lowmc->n, sc); 458 | mzd_t** y = mpc_init_empty_share_vector(lowmc->n, sc); 459 | mzd_t** z = mpc_init_empty_share_vector(lowmc->n, sc); 460 | 461 | mpc_const_mat_mul(x, lowmc->k0_matrix, lowmc_key->shared, sc); 462 | mpc_const_add(x, x, p, sc, ch); 463 | 464 | mzd_t* r[3]; 465 | lowmc_round_t* round = lowmc->rounds; 466 | for (unsigned i = 0; i < lowmc->r; ++i, ++round) { 467 | for (unsigned j = 0; j < sc; j++) { 468 | r[j] = rvec[j][i]; 469 | } 470 | if (_mpc_sbox_layer(y, x, lowmc->m, views, &vcnt, r, sc, andBitPtr)) { 471 | *status = -1; 472 | return 0; 473 | } 474 | mpc_const_mat_mul(z, round->l_matrix, y, sc); 475 | mpc_const_add(z, z, round->constant, sc, ch); 476 | mzd_t** t = mpc_init_empty_share_vector(lowmc->n, sc); 477 | mpc_const_mat_mul(t, round->k_matrix, lowmc_key->shared, sc); 478 | mpc_add(z, z, t, sc); 479 | mpc_free(t, sc); 480 | mpc_copy(x, z, sc); 481 | } 482 | mpc_copy(c, x, sc); 483 | mpc_copy(views[vcnt].s, c, sc); 484 | 485 | mpc_free(z, sc); 486 | mpc_free(y, sc); 487 | mpc_free(x, sc); 488 | return c; 489 | } 490 | #endif 491 | 492 | static mzd_t** _mpc_lowmc_call_bitsliced(mpc_lowmc_t const* lowmc, mpc_lowmc_key_t* lowmc_key, 493 | mzd_t const* p, view_t* views, mzd_t*** rvec, 494 | unsigned ch) { 495 | mpc_copy(views->s, lowmc_key->shared, SC_PROOF); 496 | ++views; 497 | 498 | sbox_vars_t vars = {{NULL}}; 499 | sbox_vars_init(&vars, lowmc->n, SC_PROOF); 500 | 501 | mzd_t** x = mpc_init_empty_share_vector(lowmc->n, SC_PROOF); 502 | mzd_t* y[SC_PROOF]; 503 | mzd_local_init_multiple_ex(y, SC_PROOF, 1, lowmc->n, false); 504 | 505 | #ifdef NOSCR 506 | mpc_const_mat_mul_l(x, lowmc->k0_lookup, lowmc_key->shared, SC_PROOF); 507 | #else 508 | mpc_const_mat_mul(x, lowmc->k0_matrix, lowmc_key->shared, SC_PROOF); 509 | #endif 510 | mpc_const_add(x, x, p, SC_PROOF, ch); 511 | 512 | lowmc_round_t const* round = lowmc->rounds; 513 | for (unsigned i = 0; i < lowmc->r; ++i, ++views, ++round) { 514 | // TODO: fix for SC_PROOF != 3 515 | mzd_t* r[SC_PROOF] = {rvec[0][i], rvec[1][i], rvec[2][i]}; 516 | 517 | #ifdef WITH_OPT 518 | #ifdef WITH_SSE2 519 | if (CPU_SUPPORTS_SSE2 && lowmc->n <= 128) { 520 | _mpc_sbox_layer_bitsliced_sse(y, x, views, r, &lowmc->mask); 521 | } else 522 | #endif 523 | #ifdef WITH_AVX2 524 | if (CPU_SUPPORTS_AVX2 && lowmc->n <= 256) { 525 | _mpc_sbox_layer_bitsliced_avx(y, x, views, r, &lowmc->mask); 526 | } else 527 | #endif 528 | #endif 529 | { 530 | _mpc_sbox_layer_bitsliced(y, x, views, r, &lowmc->mask, &vars); 531 | } 532 | 533 | #ifdef NOSCR 534 | mpc_const_mat_mul_l(x, round->l_lookup, y, SC_PROOF); 535 | #else 536 | mpc_const_mat_mul(x, round->l_matrix, y, SC_PROOF); 537 | #endif 538 | mpc_const_add(x, x, round->constant, SC_PROOF, ch); 539 | #ifdef NOSCR 540 | mpc_const_addmat_mul_l(x, round->k_lookup, lowmc_key->shared, SC_PROOF); 541 | #else 542 | mpc_const_mat_mul(y, round->k_matrix, lowmc_key->shared, SC_PROOF); 543 | mpc_add(x, x, y, SC_PROOF); 544 | #endif 545 | } 546 | 547 | mpc_copy(views->s, x, SC_PROOF); 548 | sbox_vars_clear(&vars); 549 | 550 | mzd_local_free_multiple(y); 551 | return x; 552 | } 553 | 554 | static mzd_t** _mpc_lowmc_call_bitsliced_verify(mpc_lowmc_t const* lowmc, 555 | mpc_lowmc_key_t* lowmc_key, mzd_t const* p, 556 | view_t const* views, mzd_t*** rvec, 557 | unsigned ch, int* status) { 558 | ++views; 559 | 560 | sbox_vars_t vars = {{NULL}}; 561 | sbox_vars_init(&vars, lowmc->n, SC_VERIFY); 562 | 563 | mzd_t** x = mpc_init_empty_share_vector(lowmc->n, SC_VERIFY); 564 | mzd_t* y[SC_VERIFY] = {NULL}; 565 | mzd_local_init_multiple_ex(y, SC_VERIFY, 1, lowmc->n, false); 566 | 567 | #ifdef NOSCR 568 | mpc_const_mat_mul_l(x, lowmc->k0_lookup, lowmc_key->shared, SC_VERIFY); 569 | #else 570 | mpc_const_mat_mul(x, lowmc->k0_matrix, lowmc_key->shared, SC_VERIFY); 571 | #endif 572 | mpc_const_add(x, x, p, SC_VERIFY, ch); 573 | 574 | lowmc_round_t const* round = lowmc->rounds; 575 | for (unsigned i = 0; i < lowmc->r; ++i, ++views, ++round) { 576 | // TODO: fix for SC_VERIFY != 2 577 | mzd_t* r[SC_VERIFY] = {rvec[0][i], rvec[1][i]}; 578 | 579 | #ifdef WITH_OPT 580 | #ifdef WITH_SSE2 581 | if (CPU_SUPPORTS_SSE2 && lowmc->n <= 128) { 582 | _mpc_sbox_layer_bitsliced_sse_verify(y, x, views, r, &lowmc->mask); 583 | } else 584 | #endif 585 | #ifdef WITH_AVX2 586 | if (CPU_SUPPORTS_AVX2 && lowmc->n <= 256) { 587 | _mpc_sbox_layer_bitsliced_avx_verify(y, x, views, r, &lowmc->mask); 588 | } else 589 | #endif 590 | #endif 591 | { 592 | _mpc_sbox_layer_bitsliced_verify(y, x, views, r, &lowmc->mask, &vars); 593 | } 594 | 595 | #ifdef NOSCR 596 | mpc_const_mat_mul_l(x, round->l_lookup, y, SC_VERIFY); 597 | #else 598 | mpc_const_mat_mul(x, round->l_matrix, y, SC_VERIFY); 599 | #endif 600 | mpc_const_add(x, x, round->constant, SC_VERIFY, ch); 601 | #ifdef NOSCR 602 | mpc_const_addmat_mul_l(x, round->k_lookup, lowmc_key->shared, SC_VERIFY); 603 | #else 604 | mpc_const_mat_mul(y, round->k_matrix, lowmc_key->shared, SC_VERIFY); 605 | mpc_add(x, x, y, SC_VERIFY); 606 | #endif 607 | } 608 | 609 | mzd_copy(views->s[0], x[0]); 610 | 611 | sbox_vars_clear(&vars); 612 | mzd_local_free_multiple(y); 613 | return x; 614 | } 615 | 616 | mzd_t** mpc_lowmc_call(mpc_lowmc_t const* lowmc, mpc_lowmc_key_t* lowmc_key, mzd_t const* p, 617 | view_t* views, mzd_t*** rvec) { 618 | return _mpc_lowmc_call_bitsliced(lowmc, lowmc_key, p, views, rvec, 0); 619 | } 620 | 621 | static int _mpc_lowmc_verify(mpc_lowmc_t const* lowmc, mpc_lowmc_key_t* lowmc_key, mzd_t const* p, 622 | view_t const* views, mzd_t*** rvec, int c) { 623 | int status = 0; 624 | mzd_t** v = _mpc_lowmc_call_bitsliced_verify(lowmc, lowmc_key, p, views, rvec, c, &status); 625 | mpc_free(v, SC_VERIFY); 626 | #if 0 627 | if (v) { 628 | for (unsigned int i = 0; i < SC_VERIFY; ++i) { 629 | if (!mzd_local_equal(views[lowmc->r + 1].s[i], v[i])) { 630 | status = 1; 631 | break; 632 | } 633 | } 634 | mpc_free(v, SC_VERIFY); 635 | } 636 | #endif 637 | mzd_shared_clear(lowmc_key); 638 | return status; 639 | } 640 | 641 | int mpc_lowmc_verify(mpc_lowmc_t const* lowmc, mzd_t const* p, view_t const* views, 642 | mzd_t*** rvec, int c) { 643 | mpc_lowmc_key_t lowmc_key; 644 | mzd_shared_from_shares(&lowmc_key, views[0].s, SC_VERIFY); 645 | lowmc_key.share_count = 2; 646 | 647 | return _mpc_lowmc_verify(lowmc, &lowmc_key, p, views, rvec, c); 648 | } 649 | 650 | int mpc_lowmc_verify_keys(mpc_lowmc_t const* lowmc, mzd_t const* p, view_t const* views, 651 | mzd_t*** rvec, int c, const unsigned char keys[2][16]) { 652 | mpc_lowmc_key_t lowmc_key; 653 | mzd_shared_from_shares(&lowmc_key, views[0].s, SC_VERIFY); 654 | lowmc_key.share_count = 2; 655 | 656 | return _mpc_lowmc_verify(lowmc, &lowmc_key, p, views, rvec, c); 657 | } 658 | 659 | void sbox_vars_clear(sbox_vars_t* vars) { 660 | if (vars->storage) { 661 | mzd_local_free_multiple(vars->storage); 662 | free(vars->storage); 663 | memset(vars, 0, sizeof(*vars)); 664 | } 665 | } 666 | 667 | sbox_vars_t* sbox_vars_init(sbox_vars_t* vars, rci_t n, unsigned sc) { 668 | #ifdef WITH_OPT 669 | #ifdef WITH_AVX2 670 | if (CPU_SUPPORTS_AVX2 && n <= 256) { 671 | vars->storage = NULL; 672 | return vars; 673 | } 674 | #endif 675 | #ifdef WITH_SSE2 676 | if (CPU_SUPPORTS_SSE2 && n <= 128) { 677 | vars->storage = NULL; 678 | return vars; 679 | } 680 | #endif 681 | #endif 682 | 683 | vars->storage = calloc(11 * sc, sizeof(mzd_t*)); 684 | mzd_local_init_multiple_ex(vars->storage, 11 * sc, 1, n, false); 685 | 686 | for (unsigned int i = 0; i < sc; ++i) { 687 | vars->x0m[i] = vars->storage[11 * i + 0]; 688 | vars->x1m[i] = vars->storage[11 * i + 1]; 689 | vars->x2m[i] = vars->storage[11 * i + 2]; 690 | vars->r0m[i] = vars->storage[11 * i + 3]; 691 | vars->r1m[i] = vars->storage[11 * i + 4]; 692 | vars->r2m[i] = vars->storage[11 * i + 5]; 693 | vars->x0s[i] = vars->storage[11 * i + 6]; 694 | vars->x1s[i] = vars->storage[11 * i + 7]; 695 | vars->r0s[i] = vars->storage[11 * i + 8]; 696 | vars->r1s[i] = vars->storage[11 * i + 9]; 697 | vars->v[i] = vars->storage[11 * i + 10]; 698 | } 699 | 700 | return vars; 701 | } 702 | 703 | void clear_proof(mpc_lowmc_t const* lowmc, proof_t const* proof) { 704 | const size_t numrounds = lowmc->r + 2; 705 | 706 | for (unsigned int i = 0; i < NUM_ROUNDS; ++i) { 707 | for (unsigned int j = 0; j < numrounds; ++j) { 708 | for (unsigned int k = 0; k < SC_PROOF; ++k) { 709 | mzd_local_free(proof->views[i][j].s[k]); 710 | proof->views[i][j].s[k] = NULL; 711 | } 712 | } 713 | free(proof->views[i]); 714 | } 715 | } 716 | 717 | void free_proof(mpc_lowmc_t const* mpc_lowmc, proof_t* proof) { 718 | clear_proof(mpc_lowmc, proof); 719 | free(proof); 720 | } 721 | --------------------------------------------------------------------------------