├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── aes.cpp ├── aes.h ├── banquet.cpp ├── banquet.h ├── banquet_instances.cpp ├── banquet_instances.h ├── cmake ├── FindGF2X.cmake ├── FindGMP.cmake └── FindNTL.cmake ├── field.cpp ├── field.h ├── gsl-lite.hpp ├── kdf_shake.h ├── keccak ├── CMakeLists.txt ├── KeccakHash.c ├── KeccakHash.h ├── KeccakHashtimes4.c ├── KeccakHashtimes4.h ├── KeccakSponge.c ├── KeccakSponge.h ├── KeccakSponge.inc ├── KeccakSpongetimes4.c ├── KeccakSpongetimes4.h ├── KeccakSpongetimes4.inc ├── SnP-Relaned.h ├── align.h ├── avx2 │ ├── KeccakP-1600-AVX2.s │ ├── KeccakP-1600-SnP.h │ ├── KeccakP-1600-times4-SIMD256.c │ ├── KeccakP-1600-times4-SnP.h │ ├── KeccakP-1600-unrolling.macros │ └── SIMD256-config.h ├── opt64 │ ├── KeccakP-1600-64.macros │ ├── KeccakP-1600-SnP.h │ ├── KeccakP-1600-opt64-config.h │ ├── KeccakP-1600-opt64.c │ ├── KeccakP-1600-times4-SnP.h │ ├── KeccakP-1600-times4-on1.c │ ├── KeccakP-1600-unrolling.macros │ └── PlSnP-Fallback.inc └── portable_endian.h ├── macros.h ├── portable_endian.h ├── randomness.c ├── randomness.h ├── tape.cpp ├── tape.h ├── tests ├── aes_test.cpp ├── banquet_test.cpp ├── field_test.cpp ├── tree_test.cpp ├── util_test.cpp ├── utils.cpp └── utils.h ├── tools ├── bench.cpp ├── bench_free.cpp ├── bench_timing.cpp ├── bench_timing.h ├── bench_utils.cpp ├── bench_utils.h ├── morphism.sage └── parse_bench.py ├── tree.cpp ├── tree.h └── types.h /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | .vscode/ 3 | 4 | # compiled sage code 5 | *.sage.py 6 | 7 | # Prerequisites 8 | *.d 9 | 10 | # Compiled Object files 11 | *.slo 12 | *.lo 13 | *.o 14 | *.obj 15 | 16 | # Precompiled Headers 17 | *.gch 18 | *.pch 19 | 20 | # Compiled Dynamic libraries 21 | *.so 22 | *.dylib 23 | *.dll 24 | 25 | # Fortran module files 26 | *.mod 27 | *.smod 28 | 29 | # Compiled Static libraries 30 | *.lai 31 | *.la 32 | *.a 33 | *.lib 34 | 35 | # Executables 36 | *.exe 37 | *.out 38 | *.app 39 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.12) 2 | project (banquet C CXX) 3 | 4 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 5 | set(CMAKE_CXX_STANDARD 17) 6 | 7 | if(NOT CMAKE_BUILD_TYPE) 8 | set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build." FORCE) 9 | endif() 10 | 11 | include(CheckCXXCompilerFlag) 12 | 13 | set(BUILD_TESTS OFF CACHE BOOL "Build unit tests.") 14 | 15 | SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) 16 | 17 | add_compile_options("-Wall") 18 | 19 | add_subdirectory(keccak) 20 | 21 | set(BANQUET_SRCS 22 | aes.cpp 23 | banquet.cpp 24 | banquet_instances.cpp 25 | field.cpp 26 | tree.cpp 27 | tape.cpp 28 | randomness.c 29 | ) 30 | 31 | CHECK_CXX_COMPILER_FLAG(-mpclmul COMPILER_HAS_M_PCLMUL) 32 | CHECK_CXX_COMPILER_FLAG(-msse2 COMPILER_HAS_M_SSE2) 33 | CHECK_CXX_COMPILER_FLAG(-msse4 COMPILER_HAS_M_SSE4) 34 | CHECK_CXX_COMPILER_FLAG(-maes COMPILER_HAS_M_AES) 35 | if (COMPILER_HAS_M_PCLMUL AND COMPILER_HAS_M_SSE2 AND COMPILER_HAS_M_SSE4 AND COMPILER_HAS_M_AES) 36 | add_compile_options(-mpclmul -msse2 -msse4 -maes) 37 | else() 38 | message( 39 | ERROR 40 | "compiler does not have at least one of flag (pclmul, sse2, sse4, aes) which are needed" ) 41 | endif() 42 | 43 | add_library(banquet_static STATIC ${BANQUET_SRCS}) 44 | target_link_libraries(banquet_static PUBLIC keccak) 45 | 46 | add_library(bench_utils STATIC tools/bench_utils.cpp tools/bench_timing.cpp) 47 | add_executable(bench tools/bench.cpp) 48 | add_executable(bench_free tools/bench_free.cpp) 49 | target_link_libraries(bench banquet_static bench_utils) 50 | target_link_libraries(bench_free banquet_static bench_utils) 51 | 52 | if(BUILD_TESTS) 53 | FIND_PACKAGE(NTL REQUIRED) 54 | FIND_PACKAGE(GMP REQUIRED) 55 | set(THREADS_PREFER_PTHREAD_FLAG ON) 56 | find_package(Threads REQUIRED) 57 | Include(FetchContent) 58 | 59 | FetchContent_Declare( 60 | Catch2 61 | GIT_REPOSITORY https://github.com/catchorg/Catch2.git 62 | GIT_TAG v2.13.1) 63 | 64 | FetchContent_MakeAvailable(Catch2) 65 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${Catch2_SOURCE_DIR}/contrib/") 66 | add_library(test_utils STATIC tests/utils.cpp) 67 | target_link_libraries(test_utils PUBLIC ${NTL_LIBRARY} ${GMP_LIBRARIES} Threads::Threads banquet_static) 68 | 69 | add_executable(aes_test tests/aes_test.cpp) 70 | add_executable(tree_test tests/tree_test.cpp) 71 | add_executable(banquet_test tests/banquet_test.cpp) 72 | add_executable(util_test tests/util_test.cpp) 73 | add_executable(field_test tests/field_test.cpp) 74 | target_link_libraries(aes_test Catch2::Catch2 test_utils) 75 | target_link_libraries(tree_test Catch2::Catch2 test_utils) 76 | target_link_libraries(banquet_test Catch2::Catch2 test_utils) 77 | target_link_libraries(util_test Catch2::Catch2 test_utils) 78 | target_link_libraries(field_test Catch2::Catch2 test_utils) 79 | 80 | include(CTest) 81 | include(Catch) 82 | catch_discover_tests(tree_test) 83 | catch_discover_tests(aes_test) 84 | catch_discover_tests(banquet_test) 85 | catch_discover_tests(field_test) 86 | catch_discover_tests(util_test) 87 | endif() -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020-2021 Daniel Kales 2 | Copyright (c) 2020-2021 Peter Scholl 3 | Copyright (c) 2020-2021 Greg Zaverucha 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the ""Software""), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Banquet: Short and Fast Signatures from AES 2 | This an implementation of the Banquet signature scheme presented in the following work ([eprint](https://eprint.iacr.org/2021/068)): 3 | 4 | **Banquet: Short and Fast Signatures from AES** 5 | *Carsten Baum, Cyprien Delpech de Saint Guilhem, Daniel Kales, Emmanuela Orsini, Peter Scholl and Greg Zaverucha*, 6 | Public Key Cryptography 2021 7 | 8 | 9 | Banquet is a signature scheme build on the MPC-in-the-Head paradigm and is intended to provide security against both classical and quantum attackers. The security against quantum attackers stems from the use of symmetric-key cryptography such as block ciphers and hash functions, without relying on certain number-theoretic hardness assumptions that are broken in the presence of quantum attackers. In contrast to similar designs such as [Picnic](https://microsoft.github.io/Picnic/), Banquet relies only on standardized symmetric-key primitives such as AES and SHAKE. While these choices traditionally make for much larger and slower signatures, Banquet signatures can nearly match the signature sizes of Picnic (albeit with slower, but still practical run times) or have speed within a factor of two of Picnic (at the cost of larger signatures). 10 | 11 | 12 | ## Requirements 13 | 14 | Dependencies for building 15 | * A C++17 compatible C++ tool chain 16 | * [CMake](https://cmake.org/) 3.12+ 17 | 18 | Additional requirements for unit tests 19 | * [GMP](https://gmplib.org/) 20 | * [NTL](https://shoup.net/ntl) 21 | 22 | 23 | ## Setup 24 | 25 | ```bash 26 | mkdir build 27 | cd build 28 | cmake .. 29 | make 30 | # tests (if you built them by passing -DBUILD_TESTS=On to CMake) 31 | make test 32 | # benchmarks 33 | ./bench -i #instance from banquet_instances.h 34 | ./bench_free -i #benchmark parameters freely, see paper for secure parameters 35 | ``` 36 | 37 | ## Acknowledgements 38 | 39 | Some parts of the code were based on the [optimized Picnic implementation](https://github.com/IAIK/Picnic). -------------------------------------------------------------------------------- /aes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "gsl-lite.hpp" 4 | #include "types.h" 5 | #include 6 | #include 7 | #include 8 | 9 | namespace AES128 { 10 | constexpr size_t NUM_SBOXES = 200; 11 | constexpr size_t BLOCK_SIZE = 16; 12 | constexpr size_t KEY_SIZE = 16; 13 | constexpr size_t NUM_BLOCKS = 1; 14 | 15 | bool aes_128(const std::vector &key_in, 16 | const std::vector &plaintext_in, 17 | std::vector &ciphertext_out); 18 | 19 | std::pair, std::vector> 20 | aes_128_with_sbox_output(const std::vector &key_in, 21 | const std::vector &plaintext_in, 22 | std::vector &ciphertext_out); 23 | 24 | void aes_128_s_shares(const std::vector> &key_in, 25 | const std::vector> &t_shares, 26 | const std::vector &plaintext_in, 27 | std::vector> &ciphertext_shares_out, 28 | std::vector> &s_shares_out); 29 | 30 | } // namespace AES128 31 | 32 | namespace AES192 { 33 | constexpr size_t NUM_SBOXES = 416; 34 | constexpr size_t BLOCK_SIZE = 16; 35 | constexpr size_t KEY_SIZE = 24; 36 | constexpr size_t NUM_BLOCKS = 2; 37 | 38 | bool aes_192(const std::vector &key_in, 39 | const std::vector &plaintexts_in, 40 | std::vector &ciphertexts_out); 41 | 42 | std::pair, std::vector> 43 | aes_192_with_sbox_output(const std::vector &key_in, 44 | const std::vector &plaintext_in, 45 | std::vector &ciphertext_out); 46 | 47 | void aes_192_s_shares(const std::vector> &key_in, 48 | const std::vector> &t_shares, 49 | const std::vector &plaintext_in, 50 | std::vector> &ciphertext_shares_out, 51 | std::vector> &s_shares_out); 52 | 53 | } // namespace AES192 54 | 55 | namespace AES256 { 56 | constexpr size_t NUM_SBOXES = 500; 57 | constexpr size_t BLOCK_SIZE = 16; 58 | constexpr size_t KEY_SIZE = 32; 59 | constexpr size_t NUM_BLOCKS = 2; 60 | 61 | bool aes_256(const std::vector &key_in, 62 | const std::vector &plaintexts_in, 63 | std::vector &ciphertexts_out); 64 | 65 | std::pair, std::vector> 66 | aes_256_with_sbox_output(const std::vector &key_in, 67 | const std::vector &plaintext_in, 68 | std::vector &ciphertext_out); 69 | 70 | void aes_256_s_shares(const std::vector> &key_in, 71 | const std::vector> &t_shares, 72 | const std::vector &plaintext_in, 73 | std::vector> &ciphertext_shares_out, 74 | std::vector> &s_shares_out); 75 | 76 | } // namespace AES256 -------------------------------------------------------------------------------- /banquet.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "banquet_instances.h" 9 | #include "types.h" 10 | 11 | // crypto api 12 | banquet_keypair_t banquet_keygen(const banquet_instance_t &instance); 13 | 14 | banquet_signature_t banquet_sign(const banquet_instance_t &instance, 15 | const banquet_keypair_t &keypair, 16 | const uint8_t *message, size_t message_len); 17 | 18 | bool banquet_verify(const banquet_instance_t &instance, 19 | const std::vector &pk, 20 | const banquet_signature_t &signature, 21 | const uint8_t *message, size_t message_len); 22 | 23 | std::vector 24 | banquet_serialize_signature(const banquet_instance_t &instance, 25 | const banquet_signature_t &signature); 26 | banquet_signature_t 27 | banquet_deserialize_signature(const banquet_instance_t &instance, 28 | const std::vector &signature); -------------------------------------------------------------------------------- /banquet_instances.cpp: -------------------------------------------------------------------------------- 1 | #include "banquet_instances.h" 2 | 3 | #include 4 | 5 | /* key_size, block_size, num_blocks, num_sboxes */ 6 | constexpr banquet_aes_t AES128_PARAMS = {16, 16, 1, 200 /* 160 + 40 */}; 7 | constexpr banquet_aes_t AES192_PARAMS = {24, 16, 2, 416 /* 2*192 + 32 */}; 8 | constexpr banquet_aes_t AES256_PARAMS = {32, 16, 2, 500 /* 2*224 + 52 */}; 9 | 10 | static const banquet_instance_t instances[PARAMETER_SET_MAX_INDEX] = { 11 | { 12 | {0, 0, 0, 0}, 13 | 0, 14 | 0, 15 | 0, 16 | 0, 17 | 0, 18 | 0, 19 | 0, 20 | PARAMETER_SET_INVALID, 21 | }, 22 | /* AES_params, digest size, seed size, T, N, m1, m2, lambda */ 23 | {AES128_PARAMS, 32, 16, 31, 64, 10, 20, 4, Banquet_L1_Param1}, 24 | {AES128_PARAMS, 32, 16, 31, 64, 20, 10, 4, Banquet_L1_Param2}, 25 | {AES128_PARAMS, 32, 16, 29, 64, 10, 20, 5, Banquet_L1_Param3}, 26 | {AES128_PARAMS, 32, 16, 27, 64, 10, 20, 6, Banquet_L1_Param4}, 27 | {AES128_PARAMS, 32, 16, 41, 16, 10, 20, 4, Banquet_L1_Param5}, 28 | {AES128_PARAMS, 32, 16, 35, 32, 10, 20, 4, Banquet_L1_Param6}, 29 | {AES128_PARAMS, 32, 16, 28, 128, 10, 20, 4, Banquet_L1_Param8}, 30 | {AES128_PARAMS, 32, 16, 24, 128, 10, 20, 6, Banquet_L1_Param7}, 31 | {AES128_PARAMS, 32, 16, 23, 256, 10, 20, 5, Banquet_L1_Param9}, 32 | {AES128_PARAMS, 32, 16, 21, 256, 10, 20, 6, Banquet_L1_Param10}, 33 | {AES192_PARAMS, 48, 24, 46, 64, 16, 26, 4, Banquet_L3_Param1}, 34 | {AES192_PARAMS, 48, 24, 46, 64, 26, 16, 4, Banquet_L3_Param2}, 35 | {AES192_PARAMS, 48, 24, 62, 16, 26, 16, 4, Banquet_L3_Param3}, 36 | {AES192_PARAMS, 48, 24, 53, 32, 26, 16, 4, Banquet_L3_Param4}, 37 | {AES192_PARAMS, 48, 24, 40, 64, 26, 16, 6, Banquet_L3_Param5}, 38 | {AES192_PARAMS, 48, 24, 36, 128, 26, 16, 6, Banquet_L3_Param6}, 39 | {AES192_PARAMS, 48, 24, 32, 256, 26, 16, 6, Banquet_L3_Param7}, 40 | {AES256_PARAMS, 64, 32, 63, 64, 20, 25, 4, Banquet_L5_Param1}, 41 | {AES256_PARAMS, 64, 32, 84, 16, 25, 20, 4, Banquet_L5_Param2}, 42 | {AES256_PARAMS, 64, 32, 63, 32, 25, 20, 6, Banquet_L5_Param3}, 43 | {AES256_PARAMS, 64, 32, 54, 64, 25, 20, 6, Banquet_L5_Param4}, 44 | {AES256_PARAMS, 64, 32, 48, 128, 25, 20, 6, Banquet_L5_Param5}, 45 | {AES256_PARAMS, 64, 32, 43, 256, 25, 20, 6, Banquet_L5_Param6}, 46 | }; 47 | 48 | const banquet_instance_t &banquet_instance_get(banquet_params_t param) { 49 | if (param <= PARAMETER_SET_INVALID || param >= PARAMETER_SET_MAX_INDEX) { 50 | throw std::runtime_error("invalid parameter set"); 51 | } 52 | 53 | return instances[param]; 54 | } 55 | -------------------------------------------------------------------------------- /banquet_instances.h: -------------------------------------------------------------------------------- 1 | #ifndef BANQUET_INSTANCES_H 2 | #define BANQUET_INSTANCES_H 3 | 4 | #include 5 | #include 6 | 7 | /** Parameter set names */ 8 | enum banquet_params_t { 9 | PARAMETER_SET_INVALID = 0, 10 | Banquet_L1_Param1 = 1, 11 | Banquet_L1_Param2 = 2, 12 | Banquet_L1_Param3 = 3, 13 | Banquet_L1_Param4 = 4, 14 | Banquet_L1_Param5 = 5, 15 | Banquet_L1_Param6 = 6, 16 | Banquet_L1_Param7 = 7, 17 | Banquet_L1_Param8 = 8, 18 | Banquet_L1_Param9 = 9, 19 | Banquet_L1_Param10 = 10, 20 | Banquet_L3_Param1 = 11, 21 | Banquet_L3_Param2 = 12, 22 | Banquet_L3_Param3 = 13, 23 | Banquet_L3_Param4 = 14, 24 | Banquet_L3_Param5 = 15, 25 | Banquet_L3_Param6 = 16, 26 | Banquet_L3_Param7 = 17, 27 | Banquet_L5_Param1 = 18, 28 | Banquet_L5_Param2 = 19, 29 | Banquet_L5_Param3 = 20, 30 | Banquet_L5_Param4 = 21, 31 | Banquet_L5_Param5 = 22, 32 | Banquet_L5_Param6 = 23, 33 | PARAMETER_SET_MAX_INDEX = 24 34 | }; 35 | 36 | struct banquet_aes_t { 37 | uint32_t key_size; 38 | uint32_t block_size; 39 | uint32_t num_blocks; 40 | uint32_t num_sboxes; 41 | }; 42 | 43 | struct banquet_instance_t { 44 | 45 | banquet_aes_t aes_params; 46 | 47 | uint32_t digest_size; /* bytes */ 48 | uint32_t seed_size; /* bytes */ 49 | uint32_t num_rounds; // T 50 | uint32_t num_MPC_parties; // N 51 | 52 | // m1 * m2 = m (NUM_AES_SBOXES) 53 | uint32_t m1; // m1: dimension 1 of sqrt check 54 | uint32_t m2; // m2: dimension 2 of sqrt check 55 | uint32_t lambda; // field expansion factor 56 | 57 | banquet_params_t params; 58 | }; 59 | 60 | const banquet_instance_t &banquet_instance_get(banquet_params_t param); 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /cmake/FindGF2X.cmake: -------------------------------------------------------------------------------- 1 | # Locate GF2X 2 | # This module defines 3 | # GF2X_LIBRARY 4 | # GF2X_FOUND, if false, do not try to link to OpenAL 5 | # GF2X_INCLUDE_DIR, where to find the headers 6 | # 7 | 8 | FIND_PATH(GF2X_INCLUDE_DIR gf2x.h 9 | HINTS 10 | $ENV{GF2XDIR} 11 | PATH_SUFFIXES GF2X include/GF2X include 12 | PATHS 13 | /usr/local 14 | /usr 15 | ) 16 | 17 | FIND_LIBRARY(GF2X_LIBRARY 18 | NAMES gf2x 19 | HINTS 20 | $ENV{GF2XDIR} 21 | PATH_SUFFIXES lib64 lib libs64 libs libs/Win32 libs/Win64 22 | PATHS 23 | /usr/local 24 | /usr 25 | ) 26 | 27 | MESSAGE(STATUS "GF2X libs: " ${GF2X_LIBRARY}) 28 | # handle the QUIETLY and REQUIRED arguments and set NTL_FOUND to TRUE if 29 | # all listed variables are TRUE 30 | INCLUDE(FindPackageHandleStandardArgs) 31 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(GF2X DEFAULT_MSG GF2X_LIBRARY GF2X_INCLUDE_DIR) 32 | 33 | MARK_AS_ADVANCED(GF2X_LIBRARY GF2X_INCLUDE_DIR) -------------------------------------------------------------------------------- /cmake/FindGMP.cmake: -------------------------------------------------------------------------------- 1 | # Try to find the GMP librairies 2 | # GMP_FOUND - system has GMP lib 3 | # GMP_INCLUDE_DIR - the GMP include directory 4 | # GMP_LIBRARIES - Libraries needed to use GMP 5 | 6 | if (GMP_INCLUDE_DIR AND GMP_LIBRARIES) 7 | # Already in cache, be silent 8 | set(GMP_FIND_QUIETLY TRUE) 9 | endif (GMP_INCLUDE_DIR AND GMP_LIBRARIES) 10 | 11 | find_path(GMP_INCLUDE_DIR NAMES gmp.h ) 12 | find_library(GMP_LIBRARIES NAMES gmp libgmp ) 13 | find_library(GMPXX_LIBRARIES NAMES gmpxx libgmpxx ) 14 | MESSAGE(STATUS "GMP libs: " ${GMP_LIBRARIES} " " ${GMPXX_LIBRARIES} ) 15 | 16 | include(FindPackageHandleStandardArgs) 17 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(GMP DEFAULT_MSG GMP_INCLUDE_DIR GMP_LIBRARIES) 18 | 19 | mark_as_advanced(GMP_INCLUDE_DIR GMP_LIBRARIES) -------------------------------------------------------------------------------- /cmake/FindNTL.cmake: -------------------------------------------------------------------------------- 1 | # Locate NTL 2 | # This module defines 3 | # NTL_LIBRARY 4 | # NTL_FOUND, if false, do not try to link to OpenAL 5 | # NTL_INCLUDE_DIR, where to find the headers 6 | # 7 | # Created by Tai Chi Minh Ralph Eastwood 8 | 9 | FIND_PATH(NTL_INCLUDE_DIR RR.h 10 | HINTS 11 | $ENV{NTLDIR} 12 | PATH_SUFFIXES NTL include/NTL include 13 | PATHS 14 | ~/local 15 | /usr/local 16 | /usr 17 | ) 18 | 19 | FIND_LIBRARY(NTL_LIBRARY 20 | NAMES ntl 21 | HINTS 22 | $ENV{NTLDIR} 23 | PATH_SUFFIXES lib64 lib libs64 libs libs/Win32 libs/Win64 24 | PATHS 25 | ~/local 26 | /usr/local 27 | /usr 28 | ) 29 | 30 | MESSAGE(STATUS "NTL libs: " ${NTL_LIBRARY}) 31 | # handle the QUIETLY and REQUIRED arguments and set NTL_FOUND to TRUE if 32 | # all listed variables are TRUE 33 | INCLUDE(FindPackageHandleStandardArgs) 34 | FIND_PACKAGE_HANDLE_STANDARD_ARGS(NTL DEFAULT_MSG NTL_LIBRARY NTL_INCLUDE_DIR) 35 | 36 | MARK_AS_ADVANCED(NTL_LIBRARY NTL_INCLUDE_DIR) -------------------------------------------------------------------------------- /field.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "banquet_instances.h" 4 | #include 5 | #include 6 | #include 7 | extern "C" { 8 | #include 9 | #include 10 | } 11 | 12 | namespace field { 13 | class GF2E; 14 | } 15 | 16 | field::GF2E dot_product(const std::vector &lhs, 17 | const std::vector &rhs); 18 | 19 | namespace field { 20 | class GF2E { 21 | 22 | uint64_t data; 23 | #pragma GCC diagnostic push 24 | #pragma GCC diagnostic ignored "-Wignored-attributes" 25 | static std::function reduce; 26 | #pragma GCC diagnostic pop 27 | static size_t byte_size; 28 | static uint64_t modulus; 29 | 30 | public: 31 | GF2E() : data(0){}; 32 | GF2E(uint64_t data) : data(data) {} 33 | GF2E(const GF2E &other) = default; 34 | ~GF2E() = default; 35 | GF2E &operator=(const GF2E &other) = default; 36 | 37 | void clear() { data = 0; } 38 | void set_coeff(size_t idx) { data |= (1ULL << idx); } 39 | GF2E operator+(const GF2E &other) const; 40 | GF2E &operator+=(const GF2E &other); 41 | GF2E operator-(const GF2E &other) const; 42 | GF2E &operator-=(const GF2E &other); 43 | GF2E operator*(const GF2E &other) const; 44 | GF2E &operator*=(const GF2E &other); 45 | bool operator==(const GF2E &other) const; 46 | bool operator!=(const GF2E &other) const; 47 | 48 | GF2E inverse() const; 49 | 50 | void to_bytes(uint8_t *out) const; 51 | std::vector to_bytes() const; 52 | void from_bytes(uint8_t *in); 53 | static void init_extension_field(const banquet_instance_t &instance); 54 | 55 | friend GF2E(::dot_product)(const std::vector &lhs, 56 | const std::vector &rhs); 57 | }; 58 | 59 | const GF2E &lift_uint8_t(uint8_t value); 60 | 61 | std::vector get_first_n_field_elements(size_t n); 62 | std::vector> 63 | precompute_lagrange_polynomials(const std::vector &x_values); 64 | std::vector interpolate_with_precomputation( 65 | const std::vector> &precomputed_lagrange_polynomials, 66 | const std::vector &y_values); 67 | 68 | std::vector build_from_roots(const std::vector &roots); 69 | GF2E eval(const std::vector &poly, const GF2E &point); 70 | } // namespace field 71 | 72 | std::vector operator+(const std::vector &lhs, 73 | const std::vector &rhs); 74 | std::vector &operator+=(std::vector &self, 75 | const std::vector &rhs); 76 | std::vector operator*(const std::vector &lhs, 77 | const field::GF2E &rhs); 78 | std::vector operator*(const field::GF2E &lhs, 79 | const std::vector &rhs); 80 | std::vector operator*(const std::vector &lhs, 81 | const std::vector &rhs); -------------------------------------------------------------------------------- /kdf_shake.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the optimized implementation of the Picnic signature 3 | * scheme. 4 | * See the accompanying documentation for complete details. 5 | * The code is provided under the MIT license: 6 | * 7 | * Copyright (c) 2019-2020 Sebastian Ramacher, AIT 8 | * Copyright (c) 2016-2020 Graz University of Technology 9 | * Copyright (c) 2017 Angela Promitzer 10 | 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the ""Software""), to 13 | * deal in the Software without restriction, including without limitation the 14 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 15 | * sell copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in 19 | * all copies or substantial portions of the Software. 20 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | */ 28 | 29 | #ifndef KDF_SHAKE_H 30 | #define KDF_SHAKE_H 31 | 32 | #include 33 | 34 | #include "macros.h" 35 | #include "portable_endian.h" 36 | 37 | #include "keccak/KeccakHash.h" 38 | #include "keccak/KeccakHashtimes4.h" 39 | 40 | typedef Keccak_HashInstance hash_context ATTR_ALIGNED(32); 41 | 42 | /** 43 | * Initialize hash context based on the digest size used by Picnic. If the size 44 | * is 32 bytes, SHAKE128 is used, otherwise SHAKE256 is used. 45 | */ 46 | static inline void hash_init(hash_context *ctx, size_t digest_size) { 47 | if (digest_size == 32) { 48 | Keccak_HashInitialize_SHAKE128(ctx); 49 | } else { 50 | Keccak_HashInitialize_SHAKE256(ctx); 51 | } 52 | } 53 | 54 | static inline void hash_update(hash_context *ctx, const uint8_t *data, 55 | size_t size) { 56 | Keccak_HashUpdate(ctx, data, size << 3); 57 | } 58 | 59 | static inline void hash_final(hash_context *ctx) { 60 | Keccak_HashFinal(ctx, NULL); 61 | } 62 | 63 | static inline void hash_squeeze(hash_context *ctx, uint8_t *buffer, 64 | size_t buflen) { 65 | Keccak_HashSqueeze(ctx, buffer, buflen << 3); 66 | } 67 | 68 | #define hash_clear(ctx) 69 | 70 | static inline void hash_update_uint16_le(hash_context *ctx, uint16_t data) { 71 | const uint16_t data_le = htole16(data); 72 | hash_update(ctx, (const uint8_t *)&data_le, sizeof(data_le)); 73 | } 74 | 75 | static inline void hash_init_prefix(hash_context *ctx, size_t digest_size, 76 | const uint8_t prefix) { 77 | hash_init(ctx, digest_size); 78 | hash_update(ctx, &prefix, sizeof(prefix)); 79 | } 80 | 81 | typedef hash_context kdf_shake_t; 82 | 83 | #define kdf_shake_init(ctx, digest_size) hash_init((ctx), (digest_size)) 84 | #define kdf_shake_init_prefix(ctx, digest_size, prefix) \ 85 | hash_init_prefix((ctx), (digest_size), (prefix)) 86 | #define kdf_shake_update_key(ctx, key, keylen) \ 87 | hash_update((ctx), (key), (keylen)) 88 | #define kdf_shake_update_key_uint16_le(ctx, key) \ 89 | hash_update_uint16_le((ctx), (key)) 90 | #define kdf_shake_finalize_key(ctx) hash_final((ctx)) 91 | #define kdf_shake_get_randomness(ctx, dst, count) \ 92 | hash_squeeze((ctx), (dst), (count)) 93 | #define kdf_shake_clear(ctx) hash_clear((ctx)) 94 | 95 | // 4x parallel hashing 96 | 97 | /* Instances that work with 4 states in parallel. */ 98 | typedef Keccak_HashInstancetimes4 hash_context_x4 ATTR_ALIGNED(32); 99 | 100 | static inline void hash_init_x4(hash_context_x4 *ctx, size_t digest_size) { 101 | if (digest_size == 32) { 102 | Keccak_HashInitializetimes4_SHAKE128(ctx); 103 | } else { 104 | Keccak_HashInitializetimes4_SHAKE256(ctx); 105 | } 106 | } 107 | 108 | static inline void hash_update_x4(hash_context_x4 *ctx, const uint8_t **data, 109 | size_t size) { 110 | Keccak_HashUpdatetimes4(ctx, data, size << 3); 111 | } 112 | 113 | static inline void hash_update_x4_4(hash_context_x4 *ctx, const uint8_t *data0, 114 | const uint8_t *data1, const uint8_t *data2, 115 | const uint8_t *data3, size_t size) { 116 | const uint8_t *data[4] = {data0, data1, data2, data3}; 117 | hash_update_x4(ctx, data, size); 118 | } 119 | 120 | static inline void hash_update_x4_1(hash_context_x4 *ctx, const uint8_t *data, 121 | size_t size) { 122 | const uint8_t *tmp[4] = {data, data, data, data}; 123 | hash_update_x4(ctx, tmp, size); 124 | } 125 | 126 | static inline void hash_init_prefix_x4(hash_context_x4 *ctx, size_t digest_size, 127 | const uint8_t prefix) { 128 | hash_init_x4(ctx, digest_size); 129 | hash_update_x4_1(ctx, &prefix, sizeof(prefix)); 130 | } 131 | 132 | static inline void hash_final_x4(hash_context_x4 *ctx) { 133 | Keccak_HashFinaltimes4(ctx, NULL); 134 | } 135 | 136 | static inline void hash_squeeze_x4(hash_context_x4 *ctx, uint8_t **buffer, 137 | size_t buflen) { 138 | Keccak_HashSqueezetimes4(ctx, buffer, buflen << 3); 139 | } 140 | 141 | static inline void hash_squeeze_x4_4(hash_context_x4 *ctx, uint8_t *buffer0, 142 | uint8_t *buffer1, uint8_t *buffer2, 143 | uint8_t *buffer3, size_t buflen) { 144 | uint8_t *buffer[4] = {buffer0, buffer1, buffer2, buffer3}; 145 | hash_squeeze_x4(ctx, buffer, buflen); 146 | } 147 | 148 | #define hash_clear_x4(ctx) 149 | static inline void hash_update_x4_uint16_le(hash_context_x4 *ctx, 150 | uint16_t data) { 151 | const uint16_t data_le = htole16(data); 152 | hash_update_x4_1(ctx, (const uint8_t *)&data_le, sizeof(data_le)); 153 | } 154 | 155 | static inline void hash_update_x4_uint16s_le(hash_context_x4 *ctx, 156 | const uint16_t data[4]) { 157 | const uint16_t data0_le = htole16(data[0]); 158 | const uint16_t data1_le = htole16(data[1]); 159 | const uint16_t data2_le = htole16(data[2]); 160 | const uint16_t data3_le = htole16(data[3]); 161 | hash_update_x4_4(ctx, (const uint8_t *)&data0_le, (const uint8_t *)&data1_le, 162 | (const uint8_t *)&data2_le, (const uint8_t *)&data3_le, 163 | sizeof(data[0])); 164 | } 165 | 166 | typedef hash_context_x4 kdf_shake_x4_t; 167 | 168 | #define kdf_shake_x4_init(ctx, digest_size) hash_init_x4((ctx), (digest_size)) 169 | #define kdf_shake_x4_init_prefix(ctx, digest_size, prefix) \ 170 | hash_init_prefix_x4((ctx), (digest_size), (prefix)) 171 | #define kdf_shake_x4_update_key(ctx, key, keylen) \ 172 | hash_update_x4((ctx), (key), (keylen)) 173 | #define kdf_shake_x4_update_key_4(ctx, key0, key1, key2, key3, keylen) \ 174 | hash_update_x4_4((ctx), (key0), (key1), (key2), (key3), (keylen)) 175 | #define kdf_shake_x4_update_key_1(ctx, key, keylen) \ 176 | hash_update_x4_1((ctx), (key), (keylen)) 177 | #define kdf_shake_x4_update_key_uint16_le(ctx, key) \ 178 | hash_update_x4_uint16_le((ctx), (key)) 179 | #define kdf_shake_x4_update_key_uint16s_le(ctx, keys) \ 180 | hash_update_x4_uint16s_le((ctx), (keys)) 181 | #define kdf_shake_x4_finalize_key(ctx) hash_final_x4((ctx)) 182 | #define kdf_shake_x4_get_randomness(ctx, dst, count) \ 183 | hash_squeeze_x4((ctx), (dst), (count)) 184 | #define kdf_shake_x4_get_randomness_4(ctx, dst0, dst1, dst2, dst3, count) \ 185 | hash_squeeze_x4_4((ctx), (dst0), (dst1), (dst2), (dst3), (count)) 186 | #define kdf_shake_x4_clear(ctx) hash_clear_x4((ctx)) 187 | #endif -------------------------------------------------------------------------------- /keccak/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.4.1) 2 | project(Keccak C ASM) 3 | 4 | set(KECCAK_SRCS 5 | KeccakHash.c 6 | KeccakSponge.c 7 | KeccakSpongetimes4.c 8 | KeccakHashtimes4.c 9 | ) 10 | 11 | 12 | 13 | 14 | if(MSVC) 15 | set(DEFAULT_USE_AVX2 OFF) 16 | else() 17 | set(DEFAULT_USE_AVX2 ON) 18 | endif() 19 | set(USE_AVX2 ${DEFAULT_USE_AVX2} CACHE BOOL "USE AVX2 version.") 20 | 21 | 22 | if (USE_AVX2) 23 | set(KECCAK_SRCS ${KECCAK_SRCS} 24 | avx2/KeccakP-1600-AVX2.s 25 | avx2/KeccakP-1600-times4-SIMD256.c 26 | ) 27 | set_property(SOURCE avx2/KeccakP-1600-AVX2.s PROPERTY COMPILE_FLAGS "-x assembler-with-cpp") 28 | else () 29 | set(KECCAK_SRCS ${KECCAK_SRCS} 30 | opt64/KeccakP-1600-opt64.c 31 | opt64/KeccakP-1600-times4-on1.c 32 | ) 33 | endif () 34 | 35 | add_library(keccak STATIC ${KECCAK_SRCS}) 36 | target_include_directories(keccak PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") 37 | if (USE_AVX2) 38 | target_include_directories(keccak PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/avx2/") 39 | else () 40 | target_include_directories(keccak PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/opt64/") 41 | endif () 42 | 43 | -------------------------------------------------------------------------------- /keccak/KeccakHash.c: -------------------------------------------------------------------------------- 1 | /* 2 | The eXtended Keccak Code Package (XKCP) 3 | https://github.com/XKCP/XKCP 4 | 5 | Keccak, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van 6 | Assche. 7 | 8 | Implementation by the designers, hereby denoted as "the implementer". 9 | 10 | For more information, feedback or questions, please refer to the Keccak Team 11 | website: https://keccak.team/ 12 | 13 | To the extent possible under law, the implementer has waived all copyright 14 | and related or neighboring rights to the source code in this file. 15 | http://creativecommons.org/publicdomain/zero/1.0/ 16 | */ 17 | 18 | #include "KeccakHash.h" 19 | #include 20 | 21 | /* ---------------------------------------------------------------- */ 22 | 23 | HashReturn Keccak_HashInitialize(Keccak_HashInstance *instance, 24 | unsigned int rate, unsigned int capacity, 25 | unsigned int hashbitlen, 26 | unsigned char delimitedSuffix) { 27 | HashReturn result; 28 | 29 | if (delimitedSuffix == 0) 30 | return KECCAK_FAIL; 31 | result = (HashReturn)KeccakWidth1600_SpongeInitialize(&instance->sponge, rate, 32 | capacity); 33 | if (result != KECCAK_SUCCESS) 34 | return result; 35 | instance->fixedOutputLength = hashbitlen; 36 | instance->delimitedSuffix = delimitedSuffix; 37 | return KECCAK_SUCCESS; 38 | } 39 | 40 | /* ---------------------------------------------------------------- */ 41 | 42 | HashReturn Keccak_HashUpdate(Keccak_HashInstance *instance, 43 | const BitSequence *data, BitLength databitlen) { 44 | if ((databitlen % 8) == 0) 45 | return (HashReturn)KeccakWidth1600_SpongeAbsorb(&instance->sponge, data, 46 | databitlen / 8); 47 | else { 48 | HashReturn ret = (HashReturn)KeccakWidth1600_SpongeAbsorb( 49 | &instance->sponge, data, databitlen / 8); 50 | if (ret == KECCAK_SUCCESS) { 51 | /* The last partial byte is assumed to be aligned on the least significant 52 | * bits */ 53 | unsigned char lastByte = data[databitlen / 8]; 54 | /* Concatenate the last few bits provided here with those of the suffix */ 55 | unsigned short delimitedLastBytes = 56 | (unsigned short)((unsigned short)(lastByte & 57 | ((1 << (databitlen % 8)) - 1)) | 58 | ((unsigned short)instance->delimitedSuffix 59 | << (databitlen % 8))); 60 | if ((delimitedLastBytes & 0xFF00) == 0x0000) { 61 | instance->delimitedSuffix = delimitedLastBytes & 0xFF; 62 | } else { 63 | unsigned char oneByte[1]; 64 | oneByte[0] = delimitedLastBytes & 0xFF; 65 | ret = (HashReturn)KeccakWidth1600_SpongeAbsorb(&instance->sponge, 66 | oneByte, 1); 67 | instance->delimitedSuffix = (delimitedLastBytes >> 8) & 0xFF; 68 | } 69 | } 70 | return ret; 71 | } 72 | } 73 | 74 | /* ---------------------------------------------------------------- */ 75 | 76 | HashReturn Keccak_HashFinal(Keccak_HashInstance *instance, 77 | BitSequence *hashval) { 78 | HashReturn ret = (HashReturn)KeccakWidth1600_SpongeAbsorbLastFewBits( 79 | &instance->sponge, instance->delimitedSuffix); 80 | if (ret == KECCAK_SUCCESS) 81 | return (HashReturn)KeccakWidth1600_SpongeSqueeze( 82 | &instance->sponge, hashval, instance->fixedOutputLength / 8); 83 | else 84 | return ret; 85 | } 86 | 87 | /* ---------------------------------------------------------------- */ 88 | 89 | HashReturn Keccak_HashSqueeze(Keccak_HashInstance *instance, BitSequence *data, 90 | BitLength databitlen) { 91 | if ((databitlen % 8) != 0) 92 | return KECCAK_FAIL; 93 | return (HashReturn)KeccakWidth1600_SpongeSqueeze(&instance->sponge, data, 94 | databitlen / 8); 95 | } 96 | -------------------------------------------------------------------------------- /keccak/KeccakHash.h: -------------------------------------------------------------------------------- 1 | /* 2 | The eXtended Keccak Code Package (XKCP) 3 | https://github.com/XKCP/XKCP 4 | 5 | Keccak, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van 6 | Assche. 7 | 8 | Implementation by the designers, hereby denoted as "the implementer". 9 | 10 | For more information, feedback or questions, please refer to the Keccak Team 11 | website: https://keccak.team/ 12 | 13 | To the extent possible under law, the implementer has waived all copyright 14 | and related or neighboring rights to the source code in this file. 15 | http://creativecommons.org/publicdomain/zero/1.0/ 16 | */ 17 | 18 | #ifndef _KeccakHashInterface_h_ 19 | #define _KeccakHashInterface_h_ 20 | 21 | #include 22 | #include 23 | 24 | #include "KeccakSponge.h" 25 | 26 | #ifndef _Keccak_BitTypes_ 27 | #define _Keccak_BitTypes_ 28 | typedef uint8_t BitSequence; 29 | 30 | typedef size_t BitLength; 31 | #endif 32 | 33 | typedef enum { 34 | KECCAK_SUCCESS = 0, 35 | KECCAK_FAIL = 1, 36 | KECCAK_BAD_HASHLEN = 2 37 | } HashReturn; 38 | 39 | typedef struct { 40 | KeccakWidth1600_SpongeInstance sponge; 41 | unsigned int fixedOutputLength; 42 | unsigned char delimitedSuffix; 43 | } Keccak_HashInstance; 44 | 45 | /** 46 | * Function to initialize the Keccak[r, c] sponge function instance used in 47 | * sequential hashing mode. 48 | * @param hashInstance Pointer to the hash instance to be initialized. 49 | * @param rate The value of the rate r. 50 | * @param capacity The value of the capacity c. 51 | * @param hashbitlen The desired number of output bits, 52 | * or 0 for an arbitrarily-long output. 53 | * @param delimitedSuffix Bits that will be automatically appended to the end 54 | * of the input message, as in domain separation. 55 | * This is a byte containing from 0 to 7 bits 56 | * formatted like the @a delimitedData parameter of 57 | * the Keccak_SpongeAbsorbLastFewBits() function. 58 | * @pre One must have r+c=1600 and the rate a multiple of 8 bits in this 59 | * implementation. 60 | * @return KECCAK_SUCCESS if successful, KECCAK_FAIL otherwise. 61 | */ 62 | HashReturn Keccak_HashInitialize(Keccak_HashInstance *hashInstance, 63 | unsigned int rate, unsigned int capacity, 64 | unsigned int hashbitlen, 65 | unsigned char delimitedSuffix); 66 | 67 | /** Macro to initialize a SHAKE128 instance as specified in the FIPS 202 68 | * standard. 69 | */ 70 | #define Keccak_HashInitialize_SHAKE128(hashInstance) \ 71 | Keccak_HashInitialize(hashInstance, 1344, 256, 0, 0x1F) 72 | 73 | /** Macro to initialize a SHAKE256 instance as specified in the FIPS 202 74 | * standard. 75 | */ 76 | #define Keccak_HashInitialize_SHAKE256(hashInstance) \ 77 | Keccak_HashInitialize(hashInstance, 1088, 512, 0, 0x1F) 78 | 79 | /** Macro to initialize a SHA3-224 instance as specified in the FIPS 202 80 | * standard. 81 | */ 82 | #define Keccak_HashInitialize_SHA3_224(hashInstance) \ 83 | Keccak_HashInitialize(hashInstance, 1152, 448, 224, 0x06) 84 | 85 | /** Macro to initialize a SHA3-256 instance as specified in the FIPS 202 86 | * standard. 87 | */ 88 | #define Keccak_HashInitialize_SHA3_256(hashInstance) \ 89 | Keccak_HashInitialize(hashInstance, 1088, 512, 256, 0x06) 90 | 91 | /** Macro to initialize a SHA3-384 instance as specified in the FIPS 202 92 | * standard. 93 | */ 94 | #define Keccak_HashInitialize_SHA3_384(hashInstance) \ 95 | Keccak_HashInitialize(hashInstance, 832, 768, 384, 0x06) 96 | 97 | /** Macro to initialize a SHA3-512 instance as specified in the FIPS 202 98 | * standard. 99 | */ 100 | #define Keccak_HashInitialize_SHA3_512(hashInstance) \ 101 | Keccak_HashInitialize(hashInstance, 576, 1024, 512, 0x06) 102 | 103 | /** 104 | * Function to give input data to be absorbed. 105 | * @param hashInstance Pointer to the hash instance initialized by 106 | * Keccak_HashInitialize(). 107 | * @param data Pointer to the input data. 108 | * When @a databitLen is not a multiple of 8, the last bits 109 | * of data must be in the least significant bits of the last byte (little-endian 110 | * convention). In this case, the (8 - @a databitLen mod 8) most significant 111 | * bits of the last byte are ignored. 112 | * @param databitLen The number of input bits provided in the input data. 113 | * @pre In the previous call to Keccak_HashUpdate(), databitlen was a 114 | * multiple of 8. 115 | * @return KECCAK_SUCCESS if successful, KECCAK_FAIL otherwise. 116 | */ 117 | HashReturn Keccak_HashUpdate(Keccak_HashInstance *hashInstance, 118 | const BitSequence *data, BitLength databitlen); 119 | 120 | /** 121 | * Function to call after all input blocks have been input and to get 122 | * output bits if the length was specified when calling Keccak_HashInitialize(). 123 | * @param hashInstance Pointer to the hash instance initialized by 124 | * Keccak_HashInitialize(). If @a hashbitlen was not 0 in the call to 125 | * Keccak_HashInitialize(), the number of output bits is equal to @a hashbitlen. 126 | * If @a hashbitlen was 0 in the call to Keccak_HashInitialize(), the output 127 | * bits must be extracted using the Keccak_HashSqueeze() function. 128 | * @param hashval Pointer to the buffer where to store the output data. 129 | * @return KECCAK_SUCCESS if successful, KECCAK_FAIL otherwise. 130 | */ 131 | HashReturn Keccak_HashFinal(Keccak_HashInstance *hashInstance, 132 | BitSequence *hashval); 133 | 134 | /** 135 | * Function to squeeze output data. 136 | * @param hashInstance Pointer to the hash instance initialized by 137 | * Keccak_HashInitialize(). 138 | * @param data Pointer to the buffer where to store the output data. 139 | * @param databitlen The number of output bits desired (must be a multiple of 140 | * 8). 141 | * @pre Keccak_HashFinal() must have been already called. 142 | * @pre @a databitlen is a multiple of 8. 143 | * @return KECCAK_SUCCESS if successful, KECCAK_FAIL otherwise. 144 | */ 145 | HashReturn Keccak_HashSqueeze(Keccak_HashInstance *hashInstance, 146 | BitSequence *data, BitLength databitlen); 147 | 148 | #endif 149 | -------------------------------------------------------------------------------- /keccak/KeccakHashtimes4.c: -------------------------------------------------------------------------------- 1 | /* 2 | Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen, 3 | Michaël Peeters, Gilles Van Assche and Ronny Van Keer, 4 | hereby denoted as "the implementer". 5 | 6 | For more information, feedback or questions, please refer to our website: 7 | https://keccak.team/ 8 | 9 | To the extent possible under law, the implementer has waived all copyright 10 | and related or neighboring rights to the source code in this file. 11 | http://creativecommons.org/publicdomain/zero/1.0/ 12 | */ 13 | 14 | #include 15 | #include "KeccakHashtimes4.h" 16 | 17 | /* ---------------------------------------------------------------- */ 18 | 19 | HashReturn Keccak_HashInitializetimes4(Keccak_HashInstancetimes4 *instance, unsigned int rate, unsigned int capacity, unsigned int hashbitlen, unsigned char delimitedSuffix) 20 | { 21 | HashReturn result; 22 | 23 | if (delimitedSuffix == 0) 24 | return KECCAK_FAIL; 25 | result = (HashReturn)KeccakWidth1600times4_SpongeInitialize(&instance->sponge, rate, capacity); 26 | if (result != KECCAK_SUCCESS) 27 | return result; 28 | instance->fixedOutputLength = hashbitlen; 29 | instance->delimitedSuffix = delimitedSuffix; 30 | return KECCAK_SUCCESS; 31 | } 32 | 33 | /* ---------------------------------------------------------------- */ 34 | 35 | HashReturn Keccak_HashUpdatetimes4(Keccak_HashInstancetimes4 *instance, const BitSequence **data, BitLength databitlen) 36 | { 37 | if ((databitlen % 8) != 0) 38 | return KECCAK_FAIL; 39 | return (HashReturn)KeccakWidth1600times4_SpongeAbsorb(&instance->sponge, data, databitlen/8); 40 | } 41 | 42 | /* ---------------------------------------------------------------- */ 43 | 44 | HashReturn Keccak_HashFinaltimes4(Keccak_HashInstancetimes4 *instance, BitSequence **hashval) 45 | { 46 | HashReturn ret = (HashReturn)KeccakWidth1600times4_SpongeAbsorbLastFewBits(&instance->sponge, instance->delimitedSuffix); 47 | if (ret == KECCAK_SUCCESS) 48 | return (HashReturn)KeccakWidth1600times4_SpongeSqueeze(&instance->sponge, hashval, instance->fixedOutputLength/8); 49 | else 50 | return ret; 51 | } 52 | 53 | /* ---------------------------------------------------------------- */ 54 | 55 | HashReturn Keccak_HashSqueezetimes4(Keccak_HashInstancetimes4 *instance, BitSequence **data, BitLength databitlen) 56 | { 57 | if ((databitlen % 8) != 0) 58 | return KECCAK_FAIL; 59 | return (HashReturn)KeccakWidth1600times4_SpongeSqueeze(&instance->sponge, data, databitlen/8); 60 | } 61 | -------------------------------------------------------------------------------- /keccak/KeccakHashtimes4.h: -------------------------------------------------------------------------------- 1 | /* 2 | Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen, 3 | Michaël Peeters, Gilles Van Assche and Ronny Van Keer, 4 | hereby denoted as "the implementer". 5 | 6 | For more information, feedback or questions, please refer to our website: 7 | https://keccak.team/ 8 | 9 | To the extent possible under law, the implementer has waived all copyright 10 | and related or neighboring rights to the source code in this file. 11 | http://creativecommons.org/publicdomain/zero/1.0/ 12 | */ 13 | 14 | #ifndef _KeccakHashInterfacetimes4_h_ 15 | #define _KeccakHashInterfacetimes4_h_ 16 | 17 | #include "KeccakHash.h" 18 | #include "KeccakSpongetimes4.h" 19 | 20 | typedef struct { 21 | KeccakWidth1600times4_SpongeInstance sponge; 22 | unsigned int fixedOutputLength; 23 | unsigned char delimitedSuffix; 24 | } Keccak_HashInstancetimes4; 25 | 26 | /** 27 | * Function to initialize the Keccak[r, c] sponge function instance used in 28 | * sequential hashing mode. 29 | * @param hashInstance Pointer to the hash instance to be initialized. 30 | * @param rate The value of the rate r. 31 | * @param capacity The value of the capacity c. 32 | * @param hashbitlen The desired number of output bits, 33 | * or 0 for an arbitrarily-long output. 34 | * @param delimitedSuffix Bits that will be automatically appended to the end 35 | * of the input message, as in domain separation. 36 | * This is a byte containing from 0 to 7 bits 37 | * formatted like the @a delimitedData parameter of 38 | * the Keccak_SpongeAbsorbLastFewBits() function. 39 | * @pre One must have r+c=1600 and the rate a multiple of 8 bits in this 40 | * implementation. 41 | * @return SUCCESS if successful, FAIL otherwise. 42 | */ 43 | HashReturn Keccak_HashInitializetimes4(Keccak_HashInstancetimes4 *hashInstance, 44 | unsigned int rate, unsigned int capacity, 45 | unsigned int hashbitlen, 46 | unsigned char delimitedSuffix); 47 | 48 | /** Macro to initialize a SHAKE128 instance as specified in the FIPS 202 49 | * standard. 50 | */ 51 | #define Keccak_HashInitializetimes4_SHAKE128(hashInstance) \ 52 | Keccak_HashInitializetimes4(hashInstance, 1344, 256, 0, 0x1F) 53 | 54 | /** Macro to initialize a SHAKE256 instance as specified in the FIPS 202 55 | * standard. 56 | */ 57 | #define Keccak_HashInitializetimes4_SHAKE256(hashInstance) \ 58 | Keccak_HashInitializetimes4(hashInstance, 1088, 512, 0, 0x1F) 59 | 60 | /** Macro to initialize a SHA3-224 instance as specified in the FIPS 202 61 | * standard. 62 | */ 63 | #define Keccak_HashInitializetimes4_SHA3_224(hashInstance) \ 64 | Keccak_HashInitializetimes4(hashInstance, 1152, 448, 224, 0x06) 65 | 66 | /** Macro to initialize a SHA3-256 instance as specified in the FIPS 202 67 | * standard. 68 | */ 69 | #define Keccak_HashInitializetimes4_SHA3_256(hashInstance) \ 70 | Keccak_HashInitializetimes4(hashInstance, 1088, 512, 256, 0x06) 71 | 72 | /** Macro to initialize a SHA3-384 instance as specified in the FIPS 202 73 | * standard. 74 | */ 75 | #define Keccak_HashInitializetimes4_SHA3_384(hashInstance) \ 76 | Keccak_HashInitializetimes4(hashInstance, 832, 768, 384, 0x06) 77 | 78 | /** Macro to initialize a SHA3-512 instance as specified in the FIPS 202 79 | * standard. 80 | */ 81 | #define Keccak_HashInitializetimes4_SHA3_512(hashInstance) \ 82 | Keccak_HashInitializetimes4(hashInstance, 576, 1024, 512, 0x06) 83 | 84 | /** 85 | * Function to give input data to be absorbed. 86 | * @param hashInstance Pointer to the hash instance initialized by 87 | * Keccak_HashInitialize(). 88 | * @param data Array of 4 pointers to the input data. 89 | * @param databitLen The number of input bits provided in the input data, must 90 | * be a multiple of 8. 91 | * @pre @a databitlen is a multiple of 8. 92 | * @return SUCCESS if successful, FAIL otherwise. 93 | */ 94 | HashReturn Keccak_HashUpdatetimes4(Keccak_HashInstancetimes4 *hashInstance, 95 | const BitSequence **data, 96 | BitLength databitlen); 97 | 98 | /** 99 | * Function to call after all input blocks have been input and to get 100 | * output bits if the length was specified when calling Keccak_HashInitialize(). 101 | * @param hashInstance Pointer to the hash instance initialized by 102 | * Keccak_HashInitialize(). If @a hashbitlen was not 0 in the call to 103 | * Keccak_HashInitialize(), the number of output bits is equal to @a hashbitlen. 104 | * If @a hashbitlen was 0 in the call to Keccak_HashInitialize(), the output 105 | * bits must be extracted using the Keccak_HashSqueeze() function. 106 | * @param hashval Pointer to the buffer where to store the output data. 107 | * @return SUCCESS if successful, FAIL otherwise. 108 | */ 109 | HashReturn Keccak_HashFinaltimes4(Keccak_HashInstancetimes4 *hashInstance, 110 | BitSequence **hashval); 111 | 112 | /** 113 | * Function to squeeze output data. 114 | * @param hashInstance Pointer to the hash instance initialized by 115 | * Keccak_HashInitialize(). 116 | * @param data Array of 4 pointers to the buffers where to store the 117 | * output data. 118 | * @param databitlen The number of output bits desired (must be a multiple of 119 | * 8). 120 | * @pre Keccak_HashFinal() must have been already called. 121 | * @pre @a databitlen is a multiple of 8. 122 | * @return SUCCESS if successful, FAIL otherwise. 123 | */ 124 | HashReturn Keccak_HashSqueezetimes4(Keccak_HashInstancetimes4 *hashInstance, 125 | BitSequence **data, BitLength databitlen); 126 | 127 | #endif 128 | -------------------------------------------------------------------------------- /keccak/KeccakSponge.c: -------------------------------------------------------------------------------- 1 | /* 2 | The eXtended Keccak Code Package (XKCP) 3 | https://github.com/XKCP/XKCP 4 | 5 | Keccak, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van 6 | Assche. 7 | 8 | Implementation by the designers, hereby denoted as "the implementer". 9 | 10 | For more information, feedback or questions, please refer to the Keccak Team 11 | website: https://keccak.team/ 12 | 13 | To the extent possible under law, the implementer has waived all copyright 14 | and related or neighboring rights to the source code in this file. 15 | http://creativecommons.org/publicdomain/zero/1.0/ 16 | */ 17 | 18 | #include "KeccakSponge.h" 19 | 20 | #include "KeccakP-1600-SnP.h" 21 | 22 | #define prefix KeccakWidth1600 23 | #define SnP KeccakP1600 24 | #define SnP_width 1600 25 | #define SnP_Permute KeccakP1600_Permute_24rounds 26 | #if defined(KeccakF1600_FastLoop_supported) 27 | #define SnP_FastLoop_Absorb KeccakF1600_FastLoop_Absorb 28 | #endif 29 | #include "KeccakSponge.inc" 30 | #undef prefix 31 | #undef SnP 32 | #undef SnP_width 33 | #undef SnP_Permute 34 | #undef SnP_FastLoop_Absorb 35 | 36 | #define prefix KeccakWidth1600_12rounds 37 | #define SnP KeccakP1600 38 | #define SnP_width 1600 39 | #define SnP_Permute KeccakP1600_Permute_12rounds 40 | #if defined(KeccakP1600_12rounds_FastLoop_supported) 41 | #define SnP_FastLoop_Absorb KeccakP1600_12rounds_FastLoop_Absorb 42 | #endif 43 | #include "KeccakSponge.inc" 44 | #undef prefix 45 | #undef SnP 46 | #undef SnP_width 47 | #undef SnP_Permute 48 | #undef SnP_FastLoop_Absorb 49 | -------------------------------------------------------------------------------- /keccak/KeccakSponge.h: -------------------------------------------------------------------------------- 1 | /* 2 | The eXtended Keccak Code Package (XKCP) 3 | https://github.com/XKCP/XKCP 4 | 5 | Keccak, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van 6 | Assche. 7 | 8 | Implementation by the designers, hereby denoted as "the implementer". 9 | 10 | For more information, feedback or questions, please refer to the Keccak Team 11 | website: https://keccak.team/ 12 | 13 | To the extent possible under law, the implementer has waived all copyright 14 | and related or neighboring rights to the source code in this file. 15 | http://creativecommons.org/publicdomain/zero/1.0/ 16 | */ 17 | 18 | #ifndef _KeccakSponge_h_ 19 | #define _KeccakSponge_h_ 20 | 21 | /* For the documentation, please follow the link: */ 22 | /* #include "KeccakSponge-documentation.h" */ 23 | 24 | #include "align.h" 25 | #include 26 | 27 | #define XKCP_DeclareSpongeStructure(prefix, size, alignment) \ 28 | ALIGN(alignment) typedef struct prefix##_SpongeInstanceStruct { \ 29 | unsigned char state[size]; \ 30 | unsigned int rate; \ 31 | unsigned int byteIOIndex; \ 32 | int squeezing; \ 33 | } prefix##_SpongeInstance; 34 | 35 | #define XKCP_DeclareSpongeFunctions(prefix) \ 36 | int prefix##_Sponge(unsigned int rate, unsigned int capacity, \ 37 | const unsigned char *input, size_t inputByteLen, \ 38 | unsigned char suffix, unsigned char *output, \ 39 | size_t outputByteLen); \ 40 | int prefix##_SpongeInitialize(prefix##_SpongeInstance *spongeInstance, \ 41 | unsigned int rate, unsigned int capacity); \ 42 | int prefix##_SpongeAbsorb(prefix##_SpongeInstance *spongeInstance, \ 43 | const unsigned char *data, size_t dataByteLen); \ 44 | int prefix##_SpongeAbsorbLastFewBits( \ 45 | prefix##_SpongeInstance *spongeInstance, unsigned char delimitedData); \ 46 | int prefix##_SpongeSqueeze(prefix##_SpongeInstance *spongeInstance, \ 47 | unsigned char *data, size_t dataByteLen); 48 | 49 | #include "KeccakP-1600-SnP.h" 50 | XKCP_DeclareSpongeStructure(KeccakWidth1600, KeccakP1600_stateSizeInBytes, 51 | KeccakP1600_stateAlignment) 52 | XKCP_DeclareSpongeFunctions(KeccakWidth1600) 53 | 54 | XKCP_DeclareSpongeStructure(KeccakWidth1600_12rounds, 55 | KeccakP1600_stateSizeInBytes, 56 | KeccakP1600_stateAlignment) 57 | XKCP_DeclareSpongeFunctions(KeccakWidth1600_12rounds) 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /keccak/KeccakSponge.inc: -------------------------------------------------------------------------------- 1 | /* 2 | The eXtended Keccak Code Package (XKCP) 3 | https://github.com/XKCP/XKCP 4 | 5 | Keccak, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche. 6 | 7 | Implementation by the designers, hereby denoted as "the implementer". 8 | 9 | For more information, feedback or questions, please refer to the Keccak Team website: 10 | https://keccak.team/ 11 | 12 | To the extent possible under law, the implementer has waived all copyright 13 | and related or neighboring rights to the source code in this file. 14 | http://creativecommons.org/publicdomain/zero/1.0/ 15 | */ 16 | 17 | #define JOIN0(a, b) a ## b 18 | #define JOIN(a, b) JOIN0(a, b) 19 | 20 | #define Sponge JOIN(prefix, _Sponge) 21 | #define SpongeInstance JOIN(prefix, _SpongeInstance) 22 | #define SpongeInitialize JOIN(prefix, _SpongeInitialize) 23 | #define SpongeAbsorb JOIN(prefix, _SpongeAbsorb) 24 | #define SpongeAbsorbLastFewBits JOIN(prefix, _SpongeAbsorbLastFewBits) 25 | #define SpongeSqueeze JOIN(prefix, _SpongeSqueeze) 26 | 27 | #define SnP_stateSizeInBytes JOIN(SnP, _stateSizeInBytes) 28 | #define SnP_stateAlignment JOIN(SnP, _stateAlignment) 29 | #define SnP_StaticInitialize JOIN(SnP, _StaticInitialize) 30 | #define SnP_Initialize JOIN(SnP, _Initialize) 31 | #define SnP_AddByte JOIN(SnP, _AddByte) 32 | #define SnP_AddBytes JOIN(SnP, _AddBytes) 33 | #define SnP_ExtractBytes JOIN(SnP, _ExtractBytes) 34 | 35 | int Sponge(unsigned int rate, unsigned int capacity, const unsigned char *input, size_t inputByteLen, unsigned char suffix, unsigned char *output, size_t outputByteLen) 36 | { 37 | ALIGN(SnP_stateAlignment) unsigned char state[SnP_stateSizeInBytes]; 38 | unsigned int partialBlock; 39 | const unsigned char *curInput = input; 40 | unsigned char *curOutput = output; 41 | unsigned int rateInBytes = rate/8; 42 | 43 | if (rate+capacity != SnP_width) 44 | return 1; 45 | if ((rate <= 0) || (rate > SnP_width) || ((rate % 8) != 0)) 46 | return 1; 47 | if (suffix == 0) 48 | return 1; 49 | 50 | /* Initialize the state */ 51 | SnP_StaticInitialize(); 52 | SnP_Initialize(state); 53 | 54 | /* First, absorb whole blocks */ 55 | #ifdef SnP_FastLoop_Absorb 56 | if (((rateInBytes % (SnP_width/200)) == 0) && (inputByteLen >= rateInBytes)) { 57 | /* fast lane: whole lane rate */ 58 | size_t j; 59 | j = SnP_FastLoop_Absorb(state, rateInBytes/(SnP_width/200), curInput, inputByteLen); 60 | curInput += j; 61 | inputByteLen -= j; 62 | } 63 | #endif 64 | while(inputByteLen >= (size_t)rateInBytes) { 65 | #ifdef KeccakReference 66 | displayBytes(1, "Block to be absorbed", curInput, rateInBytes); 67 | #endif 68 | SnP_AddBytes(state, curInput, 0, rateInBytes); 69 | SnP_Permute(state); 70 | curInput += rateInBytes; 71 | inputByteLen -= rateInBytes; 72 | } 73 | 74 | /* Then, absorb what remains */ 75 | partialBlock = (unsigned int)inputByteLen; 76 | #ifdef KeccakReference 77 | displayBytes(1, "Block to be absorbed (part)", curInput, partialBlock); 78 | #endif 79 | SnP_AddBytes(state, curInput, 0, partialBlock); 80 | 81 | /* Finally, absorb the suffix */ 82 | #ifdef KeccakReference 83 | { 84 | unsigned char delimitedData1[1]; 85 | delimitedData1[0] = suffix; 86 | displayBytes(1, "Block to be absorbed (last few bits + first bit of padding)", delimitedData1, 1); 87 | } 88 | #endif 89 | /* Last few bits, whose delimiter coincides with first bit of padding */ 90 | SnP_AddByte(state, suffix, partialBlock); 91 | /* If the first bit of padding is at position rate-1, we need a whole new block for the second bit of padding */ 92 | if ((suffix >= 0x80) && (partialBlock == (rateInBytes-1))) 93 | SnP_Permute(state); 94 | /* Second bit of padding */ 95 | SnP_AddByte(state, 0x80, rateInBytes-1); 96 | #ifdef KeccakReference 97 | { 98 | unsigned char block[SnP_width/8]; 99 | memset(block, 0, SnP_width/8); 100 | block[rateInBytes-1] = 0x80; 101 | displayBytes(1, "Second bit of padding", block, rateInBytes); 102 | } 103 | #endif 104 | SnP_Permute(state); 105 | #ifdef KeccakReference 106 | displayText(1, "--- Switching to squeezing phase ---"); 107 | #endif 108 | 109 | /* First, output whole blocks */ 110 | while(outputByteLen > (size_t)rateInBytes) { 111 | SnP_ExtractBytes(state, curOutput, 0, rateInBytes); 112 | SnP_Permute(state); 113 | #ifdef KeccakReference 114 | displayBytes(1, "Squeezed block", curOutput, rateInBytes); 115 | #endif 116 | curOutput += rateInBytes; 117 | outputByteLen -= rateInBytes; 118 | } 119 | 120 | /* Finally, output what remains */ 121 | partialBlock = (unsigned int)outputByteLen; 122 | SnP_ExtractBytes(state, curOutput, 0, partialBlock); 123 | #ifdef KeccakReference 124 | displayBytes(1, "Squeezed block (part)", curOutput, partialBlock); 125 | #endif 126 | 127 | return 0; 128 | } 129 | 130 | /* ---------------------------------------------------------------- */ 131 | /* ---------------------------------------------------------------- */ 132 | /* ---------------------------------------------------------------- */ 133 | 134 | int SpongeInitialize(SpongeInstance *instance, unsigned int rate, unsigned int capacity) 135 | { 136 | if (rate+capacity != SnP_width) 137 | return 1; 138 | if ((rate <= 0) || (rate > SnP_width) || ((rate % 8) != 0)) 139 | return 1; 140 | SnP_StaticInitialize(); 141 | SnP_Initialize(instance->state); 142 | instance->rate = rate; 143 | instance->byteIOIndex = 0; 144 | instance->squeezing = 0; 145 | 146 | return 0; 147 | } 148 | 149 | /* ---------------------------------------------------------------- */ 150 | 151 | int SpongeAbsorb(SpongeInstance *instance, const unsigned char *data, size_t dataByteLen) 152 | { 153 | size_t i, j; 154 | unsigned int partialBlock; 155 | const unsigned char *curData; 156 | unsigned int rateInBytes = instance->rate/8; 157 | 158 | if (instance->squeezing) 159 | return 1; /* Too late for additional input */ 160 | 161 | i = 0; 162 | curData = data; 163 | while(i < dataByteLen) { 164 | if ((instance->byteIOIndex == 0) && (dataByteLen >= (i + rateInBytes))) { 165 | #ifdef SnP_FastLoop_Absorb 166 | /* processing full blocks first */ 167 | if ((rateInBytes % (SnP_width/200)) == 0) { 168 | /* fast lane: whole lane rate */ 169 | j = SnP_FastLoop_Absorb(instance->state, rateInBytes/(SnP_width/200), curData, dataByteLen - i); 170 | i += j; 171 | curData += j; 172 | } 173 | else { 174 | #endif 175 | for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) { 176 | #ifdef KeccakReference 177 | displayBytes(1, "Block to be absorbed", curData, rateInBytes); 178 | #endif 179 | SnP_AddBytes(instance->state, curData, 0, rateInBytes); 180 | SnP_Permute(instance->state); 181 | curData+=rateInBytes; 182 | } 183 | i = dataByteLen - j; 184 | #ifdef SnP_FastLoop_Absorb 185 | } 186 | #endif 187 | } 188 | else { 189 | /* normal lane: using the message queue */ 190 | partialBlock = (unsigned int)(dataByteLen - i); 191 | if (partialBlock+instance->byteIOIndex > rateInBytes) 192 | partialBlock = rateInBytes-instance->byteIOIndex; 193 | #ifdef KeccakReference 194 | displayBytes(1, "Block to be absorbed (part)", curData, partialBlock); 195 | #endif 196 | i += partialBlock; 197 | 198 | SnP_AddBytes(instance->state, curData, instance->byteIOIndex, partialBlock); 199 | curData += partialBlock; 200 | instance->byteIOIndex += partialBlock; 201 | if (instance->byteIOIndex == rateInBytes) { 202 | SnP_Permute(instance->state); 203 | instance->byteIOIndex = 0; 204 | } 205 | } 206 | } 207 | return 0; 208 | } 209 | 210 | /* ---------------------------------------------------------------- */ 211 | 212 | int SpongeAbsorbLastFewBits(SpongeInstance *instance, unsigned char delimitedData) 213 | { 214 | unsigned int rateInBytes = instance->rate/8; 215 | 216 | if (delimitedData == 0) 217 | return 1; 218 | if (instance->squeezing) 219 | return 1; /* Too late for additional input */ 220 | 221 | #ifdef KeccakReference 222 | { 223 | unsigned char delimitedData1[1]; 224 | delimitedData1[0] = delimitedData; 225 | displayBytes(1, "Block to be absorbed (last few bits + first bit of padding)", delimitedData1, 1); 226 | } 227 | #endif 228 | /* Last few bits, whose delimiter coincides with first bit of padding */ 229 | SnP_AddByte(instance->state, delimitedData, instance->byteIOIndex); 230 | /* If the first bit of padding is at position rate-1, we need a whole new block for the second bit of padding */ 231 | if ((delimitedData >= 0x80) && (instance->byteIOIndex == (rateInBytes-1))) 232 | SnP_Permute(instance->state); 233 | /* Second bit of padding */ 234 | SnP_AddByte(instance->state, 0x80, rateInBytes-1); 235 | #ifdef KeccakReference 236 | { 237 | unsigned char block[SnP_width/8]; 238 | memset(block, 0, SnP_width/8); 239 | block[rateInBytes-1] = 0x80; 240 | displayBytes(1, "Second bit of padding", block, rateInBytes); 241 | } 242 | #endif 243 | SnP_Permute(instance->state); 244 | instance->byteIOIndex = 0; 245 | instance->squeezing = 1; 246 | #ifdef KeccakReference 247 | displayText(1, "--- Switching to squeezing phase ---"); 248 | #endif 249 | return 0; 250 | } 251 | 252 | /* ---------------------------------------------------------------- */ 253 | 254 | int SpongeSqueeze(SpongeInstance *instance, unsigned char *data, size_t dataByteLen) 255 | { 256 | size_t i, j; 257 | unsigned int partialBlock; 258 | unsigned int rateInBytes = instance->rate/8; 259 | unsigned char *curData; 260 | 261 | if (!instance->squeezing) 262 | SpongeAbsorbLastFewBits(instance, 0x01); 263 | 264 | i = 0; 265 | curData = data; 266 | while(i < dataByteLen) { 267 | if ((instance->byteIOIndex == rateInBytes) && (dataByteLen >= (i + rateInBytes))) { 268 | for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) { 269 | SnP_Permute(instance->state); 270 | SnP_ExtractBytes(instance->state, curData, 0, rateInBytes); 271 | #ifdef KeccakReference 272 | displayBytes(1, "Squeezed block", curData, rateInBytes); 273 | #endif 274 | curData+=rateInBytes; 275 | } 276 | i = dataByteLen - j; 277 | } 278 | else { 279 | /* normal lane: using the message queue */ 280 | if (instance->byteIOIndex == rateInBytes) { 281 | SnP_Permute(instance->state); 282 | instance->byteIOIndex = 0; 283 | } 284 | partialBlock = (unsigned int)(dataByteLen - i); 285 | if (partialBlock+instance->byteIOIndex > rateInBytes) 286 | partialBlock = rateInBytes-instance->byteIOIndex; 287 | i += partialBlock; 288 | 289 | SnP_ExtractBytes(instance->state, curData, instance->byteIOIndex, partialBlock); 290 | #ifdef KeccakReference 291 | displayBytes(1, "Squeezed block (part)", curData, partialBlock); 292 | #endif 293 | curData += partialBlock; 294 | instance->byteIOIndex += partialBlock; 295 | } 296 | } 297 | return 0; 298 | } 299 | 300 | /* ---------------------------------------------------------------- */ 301 | 302 | #undef Sponge 303 | #undef SpongeInstance 304 | #undef SpongeInitialize 305 | #undef SpongeAbsorb 306 | #undef SpongeAbsorbLastFewBits 307 | #undef SpongeSqueeze 308 | #undef SnP_stateSizeInBytes 309 | #undef SnP_stateAlignment 310 | #undef SnP_StaticInitialize 311 | #undef SnP_Initialize 312 | #undef SnP_AddByte 313 | #undef SnP_AddBytes 314 | #undef SnP_ExtractBytes 315 | -------------------------------------------------------------------------------- /keccak/KeccakSpongetimes4.c: -------------------------------------------------------------------------------- 1 | /* 2 | Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen, 3 | Michaël Peeters, Gilles Van Assche and Ronny Van Keer, 4 | hereby denoted as "the implementer". 5 | 6 | For more information, feedback or questions, please refer to our website: 7 | https://keccak.team/ 8 | 9 | To the extent possible under law, the implementer has waived all copyright 10 | and related or neighboring rights to the source code in this file. 11 | http://creativecommons.org/publicdomain/zero/1.0/ 12 | */ 13 | 14 | #include "KeccakSpongetimes4.h" 15 | 16 | #include "KeccakP-1600-times4-SnP.h" 17 | 18 | #define prefix KeccakWidth1600times4 19 | #define PlSnP KeccakP1600times4 20 | #define PlSnP_width 1600 21 | #define PlSnP_Permute KeccakP1600times4_PermuteAll_24rounds 22 | #if defined(KeccakF1600times4_FastLoop_supported) 23 | // can we enable fastloop absorb? 24 | //#define PlSnP_FastLoop_Absorb KeccakF1600times4_FastLoop_Absorb 25 | #endif 26 | #include "KeccakSpongetimes4.inc" 27 | #undef prefix 28 | #undef PlSnP 29 | #undef PlSnP_width 30 | #undef PlSnP_Permute 31 | #undef PlSnP_FastLoop_Absorb 32 | -------------------------------------------------------------------------------- /keccak/KeccakSpongetimes4.h: -------------------------------------------------------------------------------- 1 | /* 2 | Implementation by the Keccak Team, namely, Guido Bertoni, Joan Daemen, 3 | Michaël Peeters, Gilles Van Assche and Ronny Van Keer, 4 | hereby denoted as "the implementer". 5 | 6 | For more information, feedback or questions, please refer to our website: 7 | https://keccak.team/ 8 | 9 | To the extent possible under law, the implementer has waived all copyright 10 | and related or neighboring rights to the source code in this file. 11 | http://creativecommons.org/publicdomain/zero/1.0/ 12 | */ 13 | 14 | #ifndef _KeccakSpongeWidth1600times4_h_ 15 | #define _KeccakSpongeWidth1600times4_h_ 16 | 17 | #include "align.h" 18 | #include 19 | 20 | #define KCP_DeclareSpongeStructuretimes4(prefix, size, alignment) \ 21 | ALIGN(alignment) typedef struct prefix##_SpongeInstanceStruct { \ 22 | unsigned char state[size]; \ 23 | unsigned int rate; \ 24 | unsigned int byteIOIndex; \ 25 | int squeezing; \ 26 | } prefix##_SpongeInstance; 27 | 28 | #define KCP_DeclareSpongeFunctionstimes4(prefix) \ 29 | int prefix##_SpongeInitialize(prefix##_SpongeInstance *spongeInstance, \ 30 | unsigned int rate, unsigned int capacity); \ 31 | int prefix##_SpongeAbsorb(prefix##_SpongeInstance *spongeInstance, \ 32 | const unsigned char **data, size_t dataByteLen); \ 33 | int prefix##_SpongeAbsorbLastFewBits( \ 34 | prefix##_SpongeInstance *spongeInstance, unsigned char delimitedData); \ 35 | int prefix##_SpongeSqueeze(prefix##_SpongeInstance *spongeInstance, \ 36 | unsigned char **data, size_t dataByteLen); 37 | 38 | #include "KeccakP-1600-times4-SnP.h" 39 | KCP_DeclareSpongeStructuretimes4(KeccakWidth1600times4, 40 | KeccakP1600times4_statesSizeInBytes, 41 | KeccakP1600times4_statesAlignment) 42 | KCP_DeclareSpongeFunctionstimes4(KeccakWidth1600times4) 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /keccak/KeccakSpongetimes4.inc: -------------------------------------------------------------------------------- 1 | /* 2 | Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni, 3 | Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby 4 | denoted as "the implementer". 5 | 6 | For more information, feedback or questions, please refer to our websites: 7 | http://keccak.noekeon.org/ 8 | http://keyak.noekeon.org/ 9 | http://ketje.noekeon.org/ 10 | 11 | To the extent possible under law, the implementer has waived all copyright 12 | and related or neighboring rights to the source code in this file. 13 | http://creativecommons.org/publicdomain/zero/1.0/ 14 | */ 15 | 16 | #define JOIN0(a, b) a ## b 17 | #define JOIN(a, b) JOIN0(a, b) 18 | 19 | #define Sponge JOIN(prefix, _Sponge) 20 | #define SpongeInstance JOIN(prefix, _SpongeInstance) 21 | #define SpongeInitialize JOIN(prefix, _SpongeInitialize) 22 | #define SpongeAbsorb JOIN(prefix, _SpongeAbsorb) 23 | #define SpongeAbsorbLastFewBits JOIN(prefix, _SpongeAbsorbLastFewBits) 24 | #define SpongeSqueeze JOIN(prefix, _SpongeSqueeze) 25 | 26 | #define PlSnP_statesSizeInBytes JOIN(PlSnP, _statesSizeInBytes) 27 | #define PlSnP_statesAlignment JOIN(PlSnP, _statesAlignment) 28 | #define PlSnP_StaticInitialize JOIN(PlSnP, _StaticInitialize) 29 | #define PlSnP_InitializeAll JOIN(PlSnP, _InitializeAll) 30 | #define PlSnP_AddByte JOIN(PlSnP, _AddByte) 31 | #define PlSnP_AddBytes JOIN(PlSnP, _AddBytes) 32 | #define PlSnP_ExtractBytes JOIN(PlSnP, _ExtractBytes) 33 | 34 | /* ---------------------------------------------------------------- */ 35 | /* ---------------------------------------------------------------- */ 36 | /* ---------------------------------------------------------------- */ 37 | 38 | int SpongeInitialize(SpongeInstance *instance, unsigned int rate, unsigned int capacity) 39 | { 40 | if (rate+capacity != PlSnP_width) 41 | return 1; 42 | if ((rate <= 0) || (rate > PlSnP_width) || ((rate % 8) != 0)) 43 | return 1; 44 | PlSnP_StaticInitialize(); 45 | PlSnP_InitializeAll(instance->state); 46 | instance->rate = rate; 47 | instance->byteIOIndex = 0; 48 | instance->squeezing = 0; 49 | 50 | return 0; 51 | } 52 | 53 | /* ---------------------------------------------------------------- */ 54 | 55 | int SpongeAbsorb(SpongeInstance *instance, const unsigned char **data, size_t dataByteLen) 56 | { 57 | size_t i, j; 58 | unsigned int partialBlock; 59 | const unsigned char *curData[4]; 60 | unsigned int rateInBytes = instance->rate/8; 61 | 62 | if (instance->squeezing) 63 | return 1; /* Too late for additional input */ 64 | 65 | i = 0; 66 | if(dataByteLen > 0) { 67 | for (unsigned int instanceIndex = 0; instanceIndex < 4; instanceIndex++) { 68 | curData[instanceIndex] = data[instanceIndex]; 69 | } 70 | } 71 | while(i < dataByteLen) { 72 | if ((instance->byteIOIndex == 0) && (dataByteLen >= (i + rateInBytes))) { 73 | #ifdef PlSnP_FastLoop_Absorb 74 | /* processing full blocks first */ 75 | if ((rateInBytes % (PlSnP_width/200)) == 0) { 76 | /* fast lane: whole lane rate */ 77 | for(unsigned int instanceIndex = 0; instanceIndex < 4; instanceIndex++) { 78 | j = PlSnP_FastLoop_Absorb(instance->state, rateInBytes/(PlSnP_width/200), 0, 0, curData[instanceIndex], dataByteLen - i); 79 | curData[instanceIndex] += j; 80 | } 81 | i += j; 82 | } 83 | else { 84 | #endif 85 | for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) { 86 | for(unsigned int instanceIndex = 0; instanceIndex < 4; instanceIndex++) { 87 | PlSnP_AddBytes(instance->state, instanceIndex, curData[instanceIndex], 0, rateInBytes); 88 | curData[instanceIndex]+=rateInBytes; 89 | } 90 | PlSnP_Permute(instance->state); 91 | } 92 | i = dataByteLen - j; 93 | #ifdef PlSnP_FastLoop_Absorb 94 | } 95 | #endif 96 | } 97 | else { 98 | /* normal lane: using the message queue */ 99 | partialBlock = (unsigned int)(dataByteLen - i); 100 | if (partialBlock+instance->byteIOIndex > rateInBytes) 101 | partialBlock = rateInBytes-instance->byteIOIndex; 102 | i += partialBlock; 103 | 104 | for(unsigned int instanceIndex = 0; instanceIndex < 4; instanceIndex++) { 105 | PlSnP_AddBytes(instance->state, instanceIndex, curData[instanceIndex], instance->byteIOIndex, partialBlock); 106 | curData[instanceIndex] += partialBlock; 107 | } 108 | instance->byteIOIndex += partialBlock; 109 | if (instance->byteIOIndex == rateInBytes) { 110 | PlSnP_Permute(instance->state); 111 | instance->byteIOIndex = 0; 112 | } 113 | } 114 | } 115 | return 0; 116 | } 117 | 118 | /* ---------------------------------------------------------------- */ 119 | 120 | int SpongeAbsorbLastFewBits(SpongeInstance *instance, unsigned char delimitedData) 121 | { 122 | unsigned int rateInBytes = instance->rate/8; 123 | 124 | if (delimitedData == 0) 125 | return 1; 126 | if (instance->squeezing) 127 | return 1; /* Too late for additional input */ 128 | 129 | /* Last few bits, whose delimiter coincides with first bit of padding */ 130 | for(unsigned int instanceIndex = 0; instanceIndex < 4; instanceIndex++) { 131 | PlSnP_AddByte(instance->state, instanceIndex, delimitedData, instance->byteIOIndex); 132 | } 133 | 134 | /* If the first bit of padding is at position rate-1, we need a whole new block for the second bit of padding */ 135 | if ((delimitedData >= 0x80) && (instance->byteIOIndex == (rateInBytes-1))) 136 | PlSnP_Permute(instance->state); 137 | /* Second bit of padding */ 138 | for(unsigned int instanceIndex = 0; instanceIndex < 4; instanceIndex++) { 139 | PlSnP_AddByte(instance->state, instanceIndex, 0x80, rateInBytes - 1); 140 | } 141 | PlSnP_Permute(instance->state); 142 | instance->byteIOIndex = 0; 143 | instance->squeezing = 1; 144 | return 0; 145 | } 146 | 147 | /* ---------------------------------------------------------------- */ 148 | 149 | int SpongeSqueeze(SpongeInstance *instance, unsigned char **data, size_t dataByteLen) 150 | { 151 | size_t i, j; 152 | unsigned int partialBlock; 153 | unsigned int rateInBytes = instance->rate/8; 154 | unsigned char *curData[4] = { NULL, NULL, NULL, NULL}; 155 | 156 | if (!instance->squeezing) 157 | SpongeAbsorbLastFewBits(instance, 0x01); 158 | 159 | i = 0; 160 | if(dataByteLen > 0) { 161 | for (unsigned int instanceIndex = 0; instanceIndex < 4; instanceIndex++) { 162 | curData[instanceIndex] = data[instanceIndex]; 163 | } 164 | } 165 | while(i < dataByteLen) { 166 | if ((instance->byteIOIndex == rateInBytes) && (dataByteLen >= (i + rateInBytes))) { 167 | for(j=dataByteLen-i; j>=rateInBytes; j-=rateInBytes) { 168 | PlSnP_Permute(instance->state); 169 | for(unsigned int instanceIndex = 0; instanceIndex < 4; instanceIndex++) { 170 | PlSnP_ExtractBytes(instance->state, instanceIndex, curData[instanceIndex], 0, rateInBytes); 171 | curData[instanceIndex]+=rateInBytes; 172 | } 173 | } 174 | i = dataByteLen - j; 175 | } 176 | else { 177 | /* normal lane: using the message queue */ 178 | if (instance->byteIOIndex == rateInBytes) { 179 | PlSnP_Permute(instance->state); 180 | instance->byteIOIndex = 0; 181 | } 182 | partialBlock = (unsigned int)(dataByteLen - i); 183 | if (partialBlock+instance->byteIOIndex > rateInBytes) 184 | partialBlock = rateInBytes-instance->byteIOIndex; 185 | i += partialBlock; 186 | 187 | for(unsigned int instanceIndex = 0; instanceIndex < 4; instanceIndex++) { 188 | PlSnP_ExtractBytes(instance->state, instanceIndex, curData[instanceIndex], instance->byteIOIndex, partialBlock); 189 | curData[instanceIndex] += partialBlock; 190 | } 191 | instance->byteIOIndex += partialBlock; 192 | } 193 | } 194 | return 0; 195 | } 196 | 197 | /* ---------------------------------------------------------------- */ 198 | 199 | #undef Sponge 200 | #undef SpongeInstance 201 | #undef SpongeInitialize 202 | #undef SpongeAbsorb 203 | #undef SpongeAbsorbLastFewBits 204 | #undef SpongeSqueeze 205 | #undef PlSnP_statesSizeInBytes 206 | #undef PlSnP_statesAlignment 207 | #undef PlSnP_StaticInitialize 208 | #undef PlSnP_InitializeAll 209 | #undef PlSnP_AddByte 210 | #undef PlSnP_AddBytes 211 | #undef PlSnP_ExtractBytes 212 | -------------------------------------------------------------------------------- /keccak/SnP-Relaned.h: -------------------------------------------------------------------------------- 1 | /* 2 | The eXtended Keccak Code Package (XKCP) 3 | https://github.com/XKCP/XKCP 4 | 5 | Implementation by Gilles Van Assche and Ronny Van Keer, hereby denoted as "the implementer". 6 | 7 | For more information, feedback or questions, please refer to the Keccak Team website: 8 | https://keccak.team/ 9 | 10 | To the extent possible under law, the implementer has waived all copyright 11 | and related or neighboring rights to the source code in this file. 12 | http://creativecommons.org/publicdomain/zero/1.0/ 13 | 14 | --- 15 | 16 | This file contains macros that help implement a permutation in a SnP-compatible way. 17 | It converts an implementation that implement state input/output functions 18 | in a lane-oriented fashion (i.e., using SnP_AddLanes() and SnP_AddBytesInLane, 19 | and similarly for Overwite, Extract and ExtractAndAdd) to the byte-oriented SnP. 20 | Please refer to SnP-documentation.h for more details. 21 | */ 22 | 23 | #ifndef _SnP_Relaned_h_ 24 | #define _SnP_Relaned_h_ 25 | 26 | #define SnP_AddBytes(state, data, offset, length, SnP_AddLanes, SnP_AddBytesInLane, SnP_laneLengthInBytes) \ 27 | { \ 28 | if ((offset) == 0) { \ 29 | SnP_AddLanes(state, data, (length)/SnP_laneLengthInBytes); \ 30 | SnP_AddBytesInLane(state, \ 31 | (length)/SnP_laneLengthInBytes, \ 32 | (data)+((length)/SnP_laneLengthInBytes)*SnP_laneLengthInBytes, \ 33 | 0, \ 34 | (length)%SnP_laneLengthInBytes); \ 35 | } \ 36 | else { \ 37 | unsigned int _sizeLeft = (length); \ 38 | unsigned int _lanePosition = (offset)/SnP_laneLengthInBytes; \ 39 | unsigned int _offsetInLane = (offset)%SnP_laneLengthInBytes; \ 40 | const unsigned char *_curData = (data); \ 41 | while(_sizeLeft > 0) { \ 42 | unsigned int _bytesInLane = SnP_laneLengthInBytes - _offsetInLane; \ 43 | if (_bytesInLane > _sizeLeft) \ 44 | _bytesInLane = _sizeLeft; \ 45 | SnP_AddBytesInLane(state, _lanePosition, _curData, _offsetInLane, _bytesInLane); \ 46 | _sizeLeft -= _bytesInLane; \ 47 | _lanePosition++; \ 48 | _offsetInLane = 0; \ 49 | _curData += _bytesInLane; \ 50 | } \ 51 | } \ 52 | } 53 | 54 | #define SnP_OverwriteBytes(state, data, offset, length, SnP_OverwriteLanes, SnP_OverwriteBytesInLane, SnP_laneLengthInBytes) \ 55 | { \ 56 | if ((offset) == 0) { \ 57 | SnP_OverwriteLanes(state, data, (length)/SnP_laneLengthInBytes); \ 58 | SnP_OverwriteBytesInLane(state, \ 59 | (length)/SnP_laneLengthInBytes, \ 60 | (data)+((length)/SnP_laneLengthInBytes)*SnP_laneLengthInBytes, \ 61 | 0, \ 62 | (length)%SnP_laneLengthInBytes); \ 63 | } \ 64 | else { \ 65 | unsigned int _sizeLeft = (length); \ 66 | unsigned int _lanePosition = (offset)/SnP_laneLengthInBytes; \ 67 | unsigned int _offsetInLane = (offset)%SnP_laneLengthInBytes; \ 68 | const unsigned char *_curData = (data); \ 69 | while(_sizeLeft > 0) { \ 70 | unsigned int _bytesInLane = SnP_laneLengthInBytes - _offsetInLane; \ 71 | if (_bytesInLane > _sizeLeft) \ 72 | _bytesInLane = _sizeLeft; \ 73 | SnP_OverwriteBytesInLane(state, _lanePosition, _curData, _offsetInLane, _bytesInLane); \ 74 | _sizeLeft -= _bytesInLane; \ 75 | _lanePosition++; \ 76 | _offsetInLane = 0; \ 77 | _curData += _bytesInLane; \ 78 | } \ 79 | } \ 80 | } 81 | 82 | #define SnP_ExtractBytes(state, data, offset, length, SnP_ExtractLanes, SnP_ExtractBytesInLane, SnP_laneLengthInBytes) \ 83 | { \ 84 | if ((offset) == 0) { \ 85 | SnP_ExtractLanes(state, data, (length)/SnP_laneLengthInBytes); \ 86 | SnP_ExtractBytesInLane(state, \ 87 | (length)/SnP_laneLengthInBytes, \ 88 | (data)+((length)/SnP_laneLengthInBytes)*SnP_laneLengthInBytes, \ 89 | 0, \ 90 | (length)%SnP_laneLengthInBytes); \ 91 | } \ 92 | else { \ 93 | unsigned int _sizeLeft = (length); \ 94 | unsigned int _lanePosition = (offset)/SnP_laneLengthInBytes; \ 95 | unsigned int _offsetInLane = (offset)%SnP_laneLengthInBytes; \ 96 | unsigned char *_curData = (data); \ 97 | while(_sizeLeft > 0) { \ 98 | unsigned int _bytesInLane = SnP_laneLengthInBytes - _offsetInLane; \ 99 | if (_bytesInLane > _sizeLeft) \ 100 | _bytesInLane = _sizeLeft; \ 101 | SnP_ExtractBytesInLane(state, _lanePosition, _curData, _offsetInLane, _bytesInLane); \ 102 | _sizeLeft -= _bytesInLane; \ 103 | _lanePosition++; \ 104 | _offsetInLane = 0; \ 105 | _curData += _bytesInLane; \ 106 | } \ 107 | } \ 108 | } 109 | 110 | #define SnP_ExtractAndAddBytes(state, input, output, offset, length, SnP_ExtractAndAddLanes, SnP_ExtractAndAddBytesInLane, SnP_laneLengthInBytes) \ 111 | { \ 112 | if ((offset) == 0) { \ 113 | SnP_ExtractAndAddLanes(state, input, output, (length)/SnP_laneLengthInBytes); \ 114 | SnP_ExtractAndAddBytesInLane(state, \ 115 | (length)/SnP_laneLengthInBytes, \ 116 | (input)+((length)/SnP_laneLengthInBytes)*SnP_laneLengthInBytes, \ 117 | (output)+((length)/SnP_laneLengthInBytes)*SnP_laneLengthInBytes, \ 118 | 0, \ 119 | (length)%SnP_laneLengthInBytes); \ 120 | } \ 121 | else { \ 122 | unsigned int _sizeLeft = (length); \ 123 | unsigned int _lanePosition = (offset)/SnP_laneLengthInBytes; \ 124 | unsigned int _offsetInLane = (offset)%SnP_laneLengthInBytes; \ 125 | const unsigned char *_curInput = (input); \ 126 | unsigned char *_curOutput = (output); \ 127 | while(_sizeLeft > 0) { \ 128 | unsigned int _bytesInLane = SnP_laneLengthInBytes - _offsetInLane; \ 129 | if (_bytesInLane > _sizeLeft) \ 130 | _bytesInLane = _sizeLeft; \ 131 | SnP_ExtractAndAddBytesInLane(state, _lanePosition, _curInput, _curOutput, _offsetInLane, _bytesInLane); \ 132 | _sizeLeft -= _bytesInLane; \ 133 | _lanePosition++; \ 134 | _offsetInLane = 0; \ 135 | _curInput += _bytesInLane; \ 136 | _curOutput += _bytesInLane; \ 137 | } \ 138 | } \ 139 | } 140 | 141 | #endif 142 | -------------------------------------------------------------------------------- /keccak/align.h: -------------------------------------------------------------------------------- 1 | /* 2 | The eXtended Keccak Code Package (XKCP) 3 | https://github.com/XKCP/XKCP 4 | 5 | Implementation by Gilles Van Assche and Ronny Van Keer, hereby denoted as "the 6 | implementer". 7 | 8 | For more information, feedback or questions, please refer to the Keccak Team 9 | website: https://keccak.team/ 10 | 11 | To the extent possible under law, the implementer has waived all copyright 12 | and related or neighboring rights to the source code in this file. 13 | http://creativecommons.org/publicdomain/zero/1.0/ 14 | */ 15 | 16 | #ifndef _align_h_ 17 | #define _align_h_ 18 | 19 | /* on Mac OS-X and possibly others, ALIGN(x) is defined in param.h, and -Werror 20 | * chokes on the redef. */ 21 | #ifdef ALIGN 22 | #undef ALIGN 23 | #endif 24 | 25 | #if defined(__GNUC__) 26 | #define ALIGN(x) __attribute__((aligned(x))) 27 | #elif defined(_MSC_VER) 28 | #define ALIGN(x) __declspec(align(x)) 29 | #elif defined(__ARMCC_VERSION) 30 | #define ALIGN(x) __align(x) 31 | #else 32 | #define ALIGN(x) 33 | #endif 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /keccak/avx2/KeccakP-1600-SnP.h: -------------------------------------------------------------------------------- 1 | /* 2 | The eXtended Keccak Code Package (XKCP) 3 | https://github.com/XKCP/XKCP 4 | 5 | The Keccak-p permutations, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche. 6 | 7 | Implementation by Ronny Van Keer, hereby denoted as "the implementer". 8 | 9 | For more information, feedback or questions, please refer to the Keccak Team website: 10 | https://keccak.team/ 11 | 12 | To the extent possible under law, the implementer has waived all copyright 13 | and related or neighboring rights to the source code in this file. 14 | http://creativecommons.org/publicdomain/zero/1.0/ 15 | 16 | --- 17 | 18 | Please refer to SnP-documentation.h for more details. 19 | */ 20 | 21 | #ifndef _KeccakP_1600_SnP_h_ 22 | #define _KeccakP_1600_SnP_h_ 23 | 24 | #include 25 | 26 | #define KeccakP1600_implementation "AVX2 optimized implementation" 27 | #define KeccakP1600_stateSizeInBytes 200 28 | #define KeccakP1600_stateAlignment 32 29 | #define KeccakF1600_FastLoop_supported 30 | #define KeccakP1600_12rounds_FastLoop_supported 31 | 32 | #define KeccakP1600_StaticInitialize() 33 | void KeccakP1600_Initialize(void *state); 34 | void KeccakP1600_AddByte(void *state, unsigned char data, unsigned int offset); 35 | void KeccakP1600_AddBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length); 36 | void KeccakP1600_OverwriteBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length); 37 | void KeccakP1600_OverwriteWithZeroes(void *state, unsigned int byteCount); 38 | void KeccakP1600_Permute_Nrounds(void *state, unsigned int nrounds); 39 | void KeccakP1600_Permute_12rounds(void *state); 40 | void KeccakP1600_Permute_24rounds(void *state); 41 | void KeccakP1600_ExtractBytes(const void *state, unsigned char *data, unsigned int offset, unsigned int length); 42 | void KeccakP1600_ExtractAndAddBytes(const void *state, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length); 43 | size_t KeccakF1600_FastLoop_Absorb(void *state, unsigned int laneCount, const unsigned char *data, size_t dataByteLen); 44 | size_t KeccakP1600_12rounds_FastLoop_Absorb(void *state, unsigned int laneCount, const unsigned char *data, size_t dataByteLen); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /keccak/avx2/KeccakP-1600-times4-SnP.h: -------------------------------------------------------------------------------- 1 | /* 2 | The Keccak-p permutations, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche. 3 | 4 | Implementation by Gilles Van Assche and Ronny Van Keer, hereby denoted as "the implementer". 5 | 6 | For more information, feedback or questions, please refer to the Keccak Team website: 7 | https://keccak.team/ 8 | 9 | To the extent possible under law, the implementer has waived all copyright 10 | and related or neighboring rights to the source code in this file. 11 | http://creativecommons.org/publicdomain/zero/1.0/ 12 | 13 | --- 14 | 15 | Please refer to PlSnP-documentation.h for more details. 16 | */ 17 | 18 | #ifndef _KeccakP_1600_times4_SnP_h_ 19 | #define _KeccakP_1600_times4_SnP_h_ 20 | 21 | #include 22 | #include "SIMD256-config.h" 23 | 24 | #define KeccakP1600times4_implementation "256-bit SIMD implementation (" KeccakP1600times4_implementation_config ")" 25 | #define KeccakP1600times4_statesSizeInBytes 800 26 | #define KeccakP1600times4_statesAlignment 32 27 | #define KeccakF1600times4_FastLoop_supported 28 | #define KeccakP1600times4_12rounds_FastLoop_supported 29 | #define KeccakF1600times4_FastKravatte_supported 30 | 31 | #include 32 | 33 | #define KeccakP1600times4_StaticInitialize() 34 | void KeccakP1600times4_InitializeAll(void *states); 35 | #define KeccakP1600times4_AddByte(states, instanceIndex, byte, offset) \ 36 | ((unsigned char*)(states))[(instanceIndex)*8 + ((offset)/8)*4*8 + (offset)%8] ^= (byte) 37 | void KeccakP1600times4_AddBytes(void *states, unsigned int instanceIndex, const unsigned char *data, unsigned int offset, unsigned int length); 38 | void KeccakP1600times4_AddLanesAll(void *states, const unsigned char *data, unsigned int laneCount, unsigned int laneOffset); 39 | void KeccakP1600times4_OverwriteBytes(void *states, unsigned int instanceIndex, const unsigned char *data, unsigned int offset, unsigned int length); 40 | void KeccakP1600times4_OverwriteLanesAll(void *states, const unsigned char *data, unsigned int laneCount, unsigned int laneOffset); 41 | void KeccakP1600times4_OverwriteWithZeroes(void *states, unsigned int instanceIndex, unsigned int byteCount); 42 | void KeccakP1600times4_PermuteAll_4rounds(void *states); 43 | void KeccakP1600times4_PermuteAll_6rounds(void *states); 44 | void KeccakP1600times4_PermuteAll_12rounds(void *states); 45 | void KeccakP1600times4_PermuteAll_24rounds(void *states); 46 | void KeccakP1600times4_ExtractBytes(const void *states, unsigned int instanceIndex, unsigned char *data, unsigned int offset, unsigned int length); 47 | void KeccakP1600times4_ExtractLanesAll(const void *states, unsigned char *data, unsigned int laneCount, unsigned int laneOffset); 48 | void KeccakP1600times4_ExtractAndAddBytes(const void *states, unsigned int instanceIndex, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length); 49 | void KeccakP1600times4_ExtractAndAddLanesAll(const void *states, const unsigned char *input, unsigned char *output, unsigned int laneCount, unsigned int laneOffset); 50 | size_t KeccakF1600times4_FastLoop_Absorb(void *states, unsigned int laneCount, unsigned int laneOffsetParallel, unsigned int laneOffsetSerial, const unsigned char *data, size_t dataByteLen); 51 | size_t KeccakP1600times4_12rounds_FastLoop_Absorb(void *states, unsigned int laneCount, unsigned int laneOffsetParallel, unsigned int laneOffsetSerial, const unsigned char *data, size_t dataByteLen); 52 | size_t KeccakP1600times4_KravatteCompress(uint64_t *xAccu, uint64_t *kRoll, const unsigned char *input, size_t inputByteLen); 53 | size_t KeccakP1600times4_KravatteExpand(uint64_t *yAccu, const uint64_t *kRoll, unsigned char *output, size_t outputByteLen); 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /keccak/avx2/KeccakP-1600-unrolling.macros: -------------------------------------------------------------------------------- 1 | /* 2 | The eXtended Keccak Code Package (XKCP) 3 | https://github.com/XKCP/XKCP 4 | 5 | The Keccak-p permutations, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche. 6 | 7 | Implementation by Gilles Van Assche and Ronny Van Keer, hereby denoted as "the implementer". 8 | 9 | For more information, feedback or questions, please refer to the Keccak Team website: 10 | https://keccak.team/ 11 | 12 | To the extent possible under law, the implementer has waived all copyright 13 | and related or neighboring rights to the source code in this file. 14 | http://creativecommons.org/publicdomain/zero/1.0/ 15 | */ 16 | 17 | #if (defined(FullUnrolling)) 18 | #define rounds24 \ 19 | prepareTheta \ 20 | thetaRhoPiChiIotaPrepareTheta( 0, A, E) \ 21 | thetaRhoPiChiIotaPrepareTheta( 1, E, A) \ 22 | thetaRhoPiChiIotaPrepareTheta( 2, A, E) \ 23 | thetaRhoPiChiIotaPrepareTheta( 3, E, A) \ 24 | thetaRhoPiChiIotaPrepareTheta( 4, A, E) \ 25 | thetaRhoPiChiIotaPrepareTheta( 5, E, A) \ 26 | thetaRhoPiChiIotaPrepareTheta( 6, A, E) \ 27 | thetaRhoPiChiIotaPrepareTheta( 7, E, A) \ 28 | thetaRhoPiChiIotaPrepareTheta( 8, A, E) \ 29 | thetaRhoPiChiIotaPrepareTheta( 9, E, A) \ 30 | thetaRhoPiChiIotaPrepareTheta(10, A, E) \ 31 | thetaRhoPiChiIotaPrepareTheta(11, E, A) \ 32 | thetaRhoPiChiIotaPrepareTheta(12, A, E) \ 33 | thetaRhoPiChiIotaPrepareTheta(13, E, A) \ 34 | thetaRhoPiChiIotaPrepareTheta(14, A, E) \ 35 | thetaRhoPiChiIotaPrepareTheta(15, E, A) \ 36 | thetaRhoPiChiIotaPrepareTheta(16, A, E) \ 37 | thetaRhoPiChiIotaPrepareTheta(17, E, A) \ 38 | thetaRhoPiChiIotaPrepareTheta(18, A, E) \ 39 | thetaRhoPiChiIotaPrepareTheta(19, E, A) \ 40 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \ 41 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \ 42 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \ 43 | thetaRhoPiChiIota(23, E, A) \ 44 | 45 | #define rounds12 \ 46 | prepareTheta \ 47 | thetaRhoPiChiIotaPrepareTheta(12, A, E) \ 48 | thetaRhoPiChiIotaPrepareTheta(13, E, A) \ 49 | thetaRhoPiChiIotaPrepareTheta(14, A, E) \ 50 | thetaRhoPiChiIotaPrepareTheta(15, E, A) \ 51 | thetaRhoPiChiIotaPrepareTheta(16, A, E) \ 52 | thetaRhoPiChiIotaPrepareTheta(17, E, A) \ 53 | thetaRhoPiChiIotaPrepareTheta(18, A, E) \ 54 | thetaRhoPiChiIotaPrepareTheta(19, E, A) \ 55 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \ 56 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \ 57 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \ 58 | thetaRhoPiChiIota(23, E, A) \ 59 | 60 | #define rounds6 \ 61 | prepareTheta \ 62 | thetaRhoPiChiIotaPrepareTheta(18, A, E) \ 63 | thetaRhoPiChiIotaPrepareTheta(19, E, A) \ 64 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \ 65 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \ 66 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \ 67 | thetaRhoPiChiIota(23, E, A) \ 68 | 69 | #define rounds4 \ 70 | prepareTheta \ 71 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \ 72 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \ 73 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \ 74 | thetaRhoPiChiIota(23, E, A) \ 75 | 76 | #elif (Unrolling == 12) 77 | #define rounds24 \ 78 | prepareTheta \ 79 | for(i=0; i<24; i+=12) { \ 80 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 81 | thetaRhoPiChiIotaPrepareTheta(i+ 1, E, A) \ 82 | thetaRhoPiChiIotaPrepareTheta(i+ 2, A, E) \ 83 | thetaRhoPiChiIotaPrepareTheta(i+ 3, E, A) \ 84 | thetaRhoPiChiIotaPrepareTheta(i+ 4, A, E) \ 85 | thetaRhoPiChiIotaPrepareTheta(i+ 5, E, A) \ 86 | thetaRhoPiChiIotaPrepareTheta(i+ 6, A, E) \ 87 | thetaRhoPiChiIotaPrepareTheta(i+ 7, E, A) \ 88 | thetaRhoPiChiIotaPrepareTheta(i+ 8, A, E) \ 89 | thetaRhoPiChiIotaPrepareTheta(i+ 9, E, A) \ 90 | thetaRhoPiChiIotaPrepareTheta(i+10, A, E) \ 91 | thetaRhoPiChiIotaPrepareTheta(i+11, E, A) \ 92 | } \ 93 | 94 | #define rounds12 \ 95 | prepareTheta \ 96 | thetaRhoPiChiIotaPrepareTheta(12, A, E) \ 97 | thetaRhoPiChiIotaPrepareTheta(13, E, A) \ 98 | thetaRhoPiChiIotaPrepareTheta(14, A, E) \ 99 | thetaRhoPiChiIotaPrepareTheta(15, E, A) \ 100 | thetaRhoPiChiIotaPrepareTheta(16, A, E) \ 101 | thetaRhoPiChiIotaPrepareTheta(17, E, A) \ 102 | thetaRhoPiChiIotaPrepareTheta(18, A, E) \ 103 | thetaRhoPiChiIotaPrepareTheta(19, E, A) \ 104 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \ 105 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \ 106 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \ 107 | thetaRhoPiChiIota(23, E, A) \ 108 | 109 | #define rounds6 \ 110 | prepareTheta \ 111 | thetaRhoPiChiIotaPrepareTheta(18, A, E) \ 112 | thetaRhoPiChiIotaPrepareTheta(19, E, A) \ 113 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \ 114 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \ 115 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \ 116 | thetaRhoPiChiIota(23, E, A) \ 117 | 118 | #define rounds4 \ 119 | prepareTheta \ 120 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \ 121 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \ 122 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \ 123 | thetaRhoPiChiIota(23, E, A) \ 124 | 125 | #elif (Unrolling == 6) 126 | #define rounds24 \ 127 | prepareTheta \ 128 | for(i=0; i<24; i+=6) { \ 129 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 130 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 131 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ 132 | thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \ 133 | thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \ 134 | thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \ 135 | } \ 136 | 137 | #define rounds12 \ 138 | prepareTheta \ 139 | for(i=12; i<24; i+=6) { \ 140 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 141 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 142 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ 143 | thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \ 144 | thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \ 145 | thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \ 146 | } \ 147 | 148 | #define rounds6 \ 149 | prepareTheta \ 150 | thetaRhoPiChiIotaPrepareTheta(18, A, E) \ 151 | thetaRhoPiChiIotaPrepareTheta(19, E, A) \ 152 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \ 153 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \ 154 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \ 155 | thetaRhoPiChiIota(23, E, A) \ 156 | 157 | #define rounds4 \ 158 | prepareTheta \ 159 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \ 160 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \ 161 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \ 162 | thetaRhoPiChiIota(23, E, A) \ 163 | 164 | #elif (Unrolling == 4) 165 | #define rounds24 \ 166 | prepareTheta \ 167 | for(i=0; i<24; i+=4) { \ 168 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 169 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 170 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ 171 | thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \ 172 | } \ 173 | 174 | #define rounds12 \ 175 | prepareTheta \ 176 | for(i=12; i<24; i+=4) { \ 177 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 178 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 179 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ 180 | thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \ 181 | } \ 182 | 183 | #define rounds6 \ 184 | prepareTheta \ 185 | for(i=18; i<24; i+=2) { \ 186 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 187 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 188 | } \ 189 | 190 | #define rounds4 \ 191 | prepareTheta \ 192 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \ 193 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \ 194 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \ 195 | thetaRhoPiChiIota(23, E, A) \ 196 | 197 | #elif (Unrolling == 3) 198 | #define rounds24 \ 199 | prepareTheta \ 200 | for(i=0; i<24; i+=3) { \ 201 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 202 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 203 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ 204 | copyStateVariables(A, E) \ 205 | } \ 206 | 207 | #define rounds12 \ 208 | prepareTheta \ 209 | for(i=12; i<24; i+=3) { \ 210 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 211 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 212 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ 213 | copyStateVariables(A, E) \ 214 | } \ 215 | 216 | #define rounds6 \ 217 | prepareTheta \ 218 | for(i=18; i<24; i+=3) { \ 219 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 220 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 221 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ 222 | copyStateVariables(A, E) \ 223 | } \ 224 | 225 | #define rounds4 \ 226 | prepareTheta \ 227 | for(i=20; i<24; i+=2) { \ 228 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 229 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 230 | } \ 231 | 232 | #elif (Unrolling == 2) 233 | #define rounds24 \ 234 | prepareTheta \ 235 | for(i=0; i<24; i+=2) { \ 236 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 237 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 238 | } \ 239 | 240 | #define rounds12 \ 241 | prepareTheta \ 242 | for(i=12; i<24; i+=2) { \ 243 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 244 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 245 | } \ 246 | 247 | #define rounds6 \ 248 | prepareTheta \ 249 | for(i=18; i<24; i+=2) { \ 250 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 251 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 252 | } \ 253 | 254 | #define rounds4 \ 255 | prepareTheta \ 256 | for(i=20; i<24; i+=2) { \ 257 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 258 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 259 | } \ 260 | 261 | #elif (Unrolling == 1) 262 | #define rounds24 \ 263 | prepareTheta \ 264 | for(i=0; i<24; i++) { \ 265 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 266 | copyStateVariables(A, E) \ 267 | } \ 268 | 269 | #define rounds12 \ 270 | prepareTheta \ 271 | for(i=12; i<24; i++) { \ 272 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 273 | copyStateVariables(A, E) \ 274 | } \ 275 | 276 | #define rounds6 \ 277 | prepareTheta \ 278 | for(i=18; i<24; i++) { \ 279 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 280 | copyStateVariables(A, E) \ 281 | } \ 282 | 283 | #define rounds4 \ 284 | prepareTheta \ 285 | for(i=20; i<24; i++) { \ 286 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 287 | copyStateVariables(A, E) \ 288 | } \ 289 | 290 | #else 291 | #error "Unrolling is not correctly specified!" 292 | #endif 293 | 294 | #define roundsN(__nrounds) \ 295 | prepareTheta \ 296 | i = 24 - (__nrounds); \ 297 | if ((i&1) != 0) { \ 298 | thetaRhoPiChiIotaPrepareTheta(i, A, E) \ 299 | copyStateVariables(A, E) \ 300 | ++i; \ 301 | } \ 302 | for( /* empty */; i<24; i+=2) { \ 303 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 304 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 305 | } 306 | -------------------------------------------------------------------------------- /keccak/avx2/SIMD256-config.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file defines some parameters of the implementation in the parent directory. 3 | */ 4 | 5 | #define KeccakP1600times4_implementation_config "AVX2, all rounds unrolled" 6 | #define KeccakP1600times4_fullUnrolling 7 | #define KeccakP1600times4_useAVX2 8 | 9 | /* target attribute */ 10 | #ifndef __has_attribute 11 | #define __has_attribute(a) 0 12 | #endif 13 | #if defined(__GNUC__) || __has_attribute(target) 14 | #define ATTRIBUTE_TARGET_AVX2 __attribute__((target(("avx2")))) 15 | #else 16 | #define ATTRIBUTE_TARGET_AVX2 17 | #endif 18 | 19 | -------------------------------------------------------------------------------- /keccak/opt64/KeccakP-1600-SnP.h: -------------------------------------------------------------------------------- 1 | /* 2 | The eXtended Keccak Code Package (XKCP) 3 | https://github.com/XKCP/XKCP 4 | 5 | The Keccak-p permutations, designed by Guido Bertoni, Joan Daemen, Michaël 6 | Peeters and Gilles Van Assche. 7 | 8 | Implementation by Gilles Van Assche and Ronny Van Keer, hereby denoted as "the 9 | implementer". 10 | 11 | For more information, feedback or questions, please refer to the Keccak Team 12 | website: https://keccak.team/ 13 | 14 | To the extent possible under law, the implementer has waived all copyright 15 | and related or neighboring rights to the source code in this file. 16 | http://creativecommons.org/publicdomain/zero/1.0/ 17 | 18 | --- 19 | 20 | Please refer to SnP-documentation.h for more details. 21 | */ 22 | 23 | #ifndef _KeccakP_1600_SnP_h_ 24 | #define _KeccakP_1600_SnP_h_ 25 | 26 | #include "KeccakP-1600-opt64-config.h" 27 | #include "portable_endian.h" 28 | 29 | #define KeccakP1600_implementation \ 30 | "generic 64-bit optimized implementation " \ 31 | "(" KeccakP1600_implementation_config ")" 32 | #define KeccakP1600_stateSizeInBytes 200 33 | #define KeccakP1600_stateAlignment 8 34 | #define KeccakF1600_FastLoop_supported 35 | #define KeccakP1600_12rounds_FastLoop_supported 36 | 37 | #include 38 | 39 | #define KeccakP1600_StaticInitialize() 40 | void KeccakP1600_Initialize(void *state); 41 | #if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN) 42 | #define KeccakP1600_AddByte(state, byte, offset) \ 43 | ((unsigned char *)(state))[(offset)] ^= (byte) 44 | #else 45 | void KeccakP1600_AddByte(void *state, unsigned char data, unsigned int offset); 46 | #endif 47 | void KeccakP1600_AddBytes(void *state, const unsigned char *data, 48 | unsigned int offset, unsigned int length); 49 | void KeccakP1600_OverwriteBytes(void *state, const unsigned char *data, 50 | unsigned int offset, unsigned int length); 51 | void KeccakP1600_OverwriteWithZeroes(void *state, unsigned int byteCount); 52 | void KeccakP1600_Permute_Nrounds(void *state, unsigned int nrounds); 53 | void KeccakP1600_Permute_12rounds(void *state); 54 | void KeccakP1600_Permute_24rounds(void *state); 55 | void KeccakP1600_ExtractBytes(const void *state, unsigned char *data, 56 | unsigned int offset, unsigned int length); 57 | void KeccakP1600_ExtractAndAddBytes(const void *state, 58 | const unsigned char *input, 59 | unsigned char *output, unsigned int offset, 60 | unsigned int length); 61 | size_t KeccakF1600_FastLoop_Absorb(void *state, unsigned int laneCount, 62 | const unsigned char *data, 63 | size_t dataByteLen); 64 | size_t KeccakP1600_12rounds_FastLoop_Absorb(void *state, unsigned int laneCount, 65 | const unsigned char *data, 66 | size_t dataByteLen); 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /keccak/opt64/KeccakP-1600-opt64-config.h: -------------------------------------------------------------------------------- 1 | /* 2 | This file defines some parameters of the implementation in the parent directory. 3 | */ 4 | 5 | #define KeccakP1600_implementation_config "all rounds unrolled" 6 | #define KeccakP1600_fullUnrolling 7 | -------------------------------------------------------------------------------- /keccak/opt64/KeccakP-1600-times4-SnP.h: -------------------------------------------------------------------------------- 1 | /* 2 | The Keccak-p permutations, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche. 3 | 4 | Implementation by Gilles Van Assche, hereby denoted as "the implementer". 5 | 6 | For more information, feedback or questions, please refer to the Keccak Team website: 7 | https://keccak.team/ 8 | 9 | To the extent possible under law, the implementer has waived all copyright 10 | and related or neighboring rights to the source code in this file. 11 | http://creativecommons.org/publicdomain/zero/1.0/ 12 | 13 | --- 14 | 15 | Please refer to PlSnP-documentation.h for more details. 16 | */ 17 | 18 | #ifndef _KeccakP_1600_times4_SnP_h_ 19 | #define _KeccakP_1600_times4_SnP_h_ 20 | 21 | #include "KeccakP-1600-SnP.h" 22 | 23 | #define KeccakP1600times4_implementation "fallback on serial implementation (" KeccakP1600_implementation ")" 24 | #define KeccakP1600times4_statesSizeInBytes (((KeccakP1600_stateSizeInBytes+(KeccakP1600_stateAlignment-1))/KeccakP1600_stateAlignment)*KeccakP1600_stateAlignment*4) 25 | #define KeccakP1600times4_statesAlignment KeccakP1600_stateAlignment 26 | #define KeccakP1600times4_isFallback 27 | 28 | void KeccakP1600times4_StaticInitialize( void ); 29 | void KeccakP1600times4_InitializeAll(void *states); 30 | void KeccakP1600times4_AddByte(void *states, unsigned int instanceIndex, unsigned char data, unsigned int offset); 31 | void KeccakP1600times4_AddBytes(void *states, unsigned int instanceIndex, const unsigned char *data, unsigned int offset, unsigned int length); 32 | void KeccakP1600times4_AddLanesAll(void *states, const unsigned char *data, unsigned int laneCount, unsigned int laneOffset); 33 | void KeccakP1600times4_OverwriteBytes(void *states, unsigned int instanceIndex, const unsigned char *data, unsigned int offset, unsigned int length); 34 | void KeccakP1600times4_OverwriteLanesAll(void *states, const unsigned char *data, unsigned int laneCount, unsigned int laneOffset); 35 | void KeccakP1600times4_OverwriteWithZeroes(void *states, unsigned int instanceIndex, unsigned int byteCount); 36 | void KeccakP1600times4_PermuteAll_4rounds(void *states); 37 | void KeccakP1600times4_PermuteAll_6rounds(void *states); 38 | void KeccakP1600times4_PermuteAll_12rounds(void *states); 39 | void KeccakP1600times4_PermuteAll_24rounds(void *states); 40 | void KeccakP1600times4_ExtractBytes(const void *states, unsigned int instanceIndex, unsigned char *data, unsigned int offset, unsigned int length); 41 | void KeccakP1600times4_ExtractLanesAll(const void *states, unsigned char *data, unsigned int laneCount, unsigned int laneOffset); 42 | void KeccakP1600times4_ExtractAndAddBytes(const void *states, unsigned int instanceIndex, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length); 43 | void KeccakP1600times4_ExtractAndAddLanesAll(const void *states, const unsigned char *input, unsigned char *output, unsigned int laneCount, unsigned int laneOffset); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /keccak/opt64/KeccakP-1600-times4-on1.c: -------------------------------------------------------------------------------- 1 | /* 2 | The Keccak-p permutations, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche. 3 | 4 | Implementation by Gilles Van Assche, hereby denoted as "the implementer". 5 | 6 | For more information, feedback or questions, please refer to the Keccak Team website: 7 | https://keccak.team/ 8 | 9 | To the extent possible under law, the implementer has waived all copyright 10 | and related or neighboring rights to the source code in this file. 11 | http://creativecommons.org/publicdomain/zero/1.0/ 12 | 13 | --- 14 | 15 | This file implements Keccak-p[1600]×4 in a PlSnP-compatible way. 16 | Please refer to PlSnP-documentation.h for more details. 17 | 18 | This implementation comes with KeccakP-1600-times4-SnP.h in the same folder. 19 | Please refer to LowLevel.build for the exact list of other files it must be combined with. 20 | */ 21 | 22 | #include "KeccakP-1600-SnP.h" 23 | 24 | #define prefix KeccakP1600times4 25 | #define PlSnP_baseParallelism 1 26 | #define PlSnP_targetParallelism 4 27 | #define SnP_laneLengthInBytes 8 28 | #define SnP KeccakP1600 29 | #define SnP_Permute KeccakP1600_Permute_24rounds 30 | #define SnP_Permute_12rounds KeccakP1600_Permute_12rounds 31 | #define SnP_Permute_Nrounds KeccakP1600_Permute_Nrounds 32 | #define PlSnP_PermuteAll KeccakP1600times4_PermuteAll_24rounds 33 | #define PlSnP_PermuteAll_12rounds KeccakP1600times4_PermuteAll_12rounds 34 | #define PlSnP_PermuteAll_6rounds KeccakP1600times4_PermuteAll_6rounds 35 | #define PlSnP_PermuteAll_4rounds KeccakP1600times4_PermuteAll_4rounds 36 | 37 | #include "PlSnP-Fallback.inc" 38 | -------------------------------------------------------------------------------- /keccak/opt64/KeccakP-1600-unrolling.macros: -------------------------------------------------------------------------------- 1 | /* 2 | The eXtended Keccak Code Package (XKCP) 3 | https://github.com/XKCP/XKCP 4 | 5 | The Keccak-p permutations, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche. 6 | 7 | Implementation by Gilles Van Assche and Ronny Van Keer, hereby denoted as "the implementer". 8 | 9 | For more information, feedback or questions, please refer to the Keccak Team website: 10 | https://keccak.team/ 11 | 12 | To the extent possible under law, the implementer has waived all copyright 13 | and related or neighboring rights to the source code in this file. 14 | http://creativecommons.org/publicdomain/zero/1.0/ 15 | */ 16 | 17 | #if (defined(FullUnrolling)) 18 | #define rounds24 \ 19 | prepareTheta \ 20 | thetaRhoPiChiIotaPrepareTheta( 0, A, E) \ 21 | thetaRhoPiChiIotaPrepareTheta( 1, E, A) \ 22 | thetaRhoPiChiIotaPrepareTheta( 2, A, E) \ 23 | thetaRhoPiChiIotaPrepareTheta( 3, E, A) \ 24 | thetaRhoPiChiIotaPrepareTheta( 4, A, E) \ 25 | thetaRhoPiChiIotaPrepareTheta( 5, E, A) \ 26 | thetaRhoPiChiIotaPrepareTheta( 6, A, E) \ 27 | thetaRhoPiChiIotaPrepareTheta( 7, E, A) \ 28 | thetaRhoPiChiIotaPrepareTheta( 8, A, E) \ 29 | thetaRhoPiChiIotaPrepareTheta( 9, E, A) \ 30 | thetaRhoPiChiIotaPrepareTheta(10, A, E) \ 31 | thetaRhoPiChiIotaPrepareTheta(11, E, A) \ 32 | thetaRhoPiChiIotaPrepareTheta(12, A, E) \ 33 | thetaRhoPiChiIotaPrepareTheta(13, E, A) \ 34 | thetaRhoPiChiIotaPrepareTheta(14, A, E) \ 35 | thetaRhoPiChiIotaPrepareTheta(15, E, A) \ 36 | thetaRhoPiChiIotaPrepareTheta(16, A, E) \ 37 | thetaRhoPiChiIotaPrepareTheta(17, E, A) \ 38 | thetaRhoPiChiIotaPrepareTheta(18, A, E) \ 39 | thetaRhoPiChiIotaPrepareTheta(19, E, A) \ 40 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \ 41 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \ 42 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \ 43 | thetaRhoPiChiIota(23, E, A) \ 44 | 45 | #define rounds12 \ 46 | prepareTheta \ 47 | thetaRhoPiChiIotaPrepareTheta(12, A, E) \ 48 | thetaRhoPiChiIotaPrepareTheta(13, E, A) \ 49 | thetaRhoPiChiIotaPrepareTheta(14, A, E) \ 50 | thetaRhoPiChiIotaPrepareTheta(15, E, A) \ 51 | thetaRhoPiChiIotaPrepareTheta(16, A, E) \ 52 | thetaRhoPiChiIotaPrepareTheta(17, E, A) \ 53 | thetaRhoPiChiIotaPrepareTheta(18, A, E) \ 54 | thetaRhoPiChiIotaPrepareTheta(19, E, A) \ 55 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \ 56 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \ 57 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \ 58 | thetaRhoPiChiIota(23, E, A) \ 59 | 60 | #define rounds6 \ 61 | prepareTheta \ 62 | thetaRhoPiChiIotaPrepareTheta(18, A, E) \ 63 | thetaRhoPiChiIotaPrepareTheta(19, E, A) \ 64 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \ 65 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \ 66 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \ 67 | thetaRhoPiChiIota(23, E, A) \ 68 | 69 | #define rounds4 \ 70 | prepareTheta \ 71 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \ 72 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \ 73 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \ 74 | thetaRhoPiChiIota(23, E, A) \ 75 | 76 | #elif (Unrolling == 12) 77 | #define rounds24 \ 78 | prepareTheta \ 79 | for(i=0; i<24; i+=12) { \ 80 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 81 | thetaRhoPiChiIotaPrepareTheta(i+ 1, E, A) \ 82 | thetaRhoPiChiIotaPrepareTheta(i+ 2, A, E) \ 83 | thetaRhoPiChiIotaPrepareTheta(i+ 3, E, A) \ 84 | thetaRhoPiChiIotaPrepareTheta(i+ 4, A, E) \ 85 | thetaRhoPiChiIotaPrepareTheta(i+ 5, E, A) \ 86 | thetaRhoPiChiIotaPrepareTheta(i+ 6, A, E) \ 87 | thetaRhoPiChiIotaPrepareTheta(i+ 7, E, A) \ 88 | thetaRhoPiChiIotaPrepareTheta(i+ 8, A, E) \ 89 | thetaRhoPiChiIotaPrepareTheta(i+ 9, E, A) \ 90 | thetaRhoPiChiIotaPrepareTheta(i+10, A, E) \ 91 | thetaRhoPiChiIotaPrepareTheta(i+11, E, A) \ 92 | } \ 93 | 94 | #define rounds12 \ 95 | prepareTheta \ 96 | thetaRhoPiChiIotaPrepareTheta(12, A, E) \ 97 | thetaRhoPiChiIotaPrepareTheta(13, E, A) \ 98 | thetaRhoPiChiIotaPrepareTheta(14, A, E) \ 99 | thetaRhoPiChiIotaPrepareTheta(15, E, A) \ 100 | thetaRhoPiChiIotaPrepareTheta(16, A, E) \ 101 | thetaRhoPiChiIotaPrepareTheta(17, E, A) \ 102 | thetaRhoPiChiIotaPrepareTheta(18, A, E) \ 103 | thetaRhoPiChiIotaPrepareTheta(19, E, A) \ 104 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \ 105 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \ 106 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \ 107 | thetaRhoPiChiIota(23, E, A) \ 108 | 109 | #define rounds6 \ 110 | prepareTheta \ 111 | thetaRhoPiChiIotaPrepareTheta(18, A, E) \ 112 | thetaRhoPiChiIotaPrepareTheta(19, E, A) \ 113 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \ 114 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \ 115 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \ 116 | thetaRhoPiChiIota(23, E, A) \ 117 | 118 | #define rounds4 \ 119 | prepareTheta \ 120 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \ 121 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \ 122 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \ 123 | thetaRhoPiChiIota(23, E, A) \ 124 | 125 | #elif (Unrolling == 6) 126 | #define rounds24 \ 127 | prepareTheta \ 128 | for(i=0; i<24; i+=6) { \ 129 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 130 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 131 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ 132 | thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \ 133 | thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \ 134 | thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \ 135 | } \ 136 | 137 | #define rounds12 \ 138 | prepareTheta \ 139 | for(i=12; i<24; i+=6) { \ 140 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 141 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 142 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ 143 | thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \ 144 | thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \ 145 | thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \ 146 | } \ 147 | 148 | #define rounds6 \ 149 | prepareTheta \ 150 | thetaRhoPiChiIotaPrepareTheta(18, A, E) \ 151 | thetaRhoPiChiIotaPrepareTheta(19, E, A) \ 152 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \ 153 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \ 154 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \ 155 | thetaRhoPiChiIota(23, E, A) \ 156 | 157 | #define rounds4 \ 158 | prepareTheta \ 159 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \ 160 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \ 161 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \ 162 | thetaRhoPiChiIota(23, E, A) \ 163 | 164 | #elif (Unrolling == 4) 165 | #define rounds24 \ 166 | prepareTheta \ 167 | for(i=0; i<24; i+=4) { \ 168 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 169 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 170 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ 171 | thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \ 172 | } \ 173 | 174 | #define rounds12 \ 175 | prepareTheta \ 176 | for(i=12; i<24; i+=4) { \ 177 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 178 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 179 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ 180 | thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \ 181 | } \ 182 | 183 | #define rounds6 \ 184 | prepareTheta \ 185 | for(i=18; i<24; i+=2) { \ 186 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 187 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 188 | } \ 189 | 190 | #define rounds4 \ 191 | prepareTheta \ 192 | thetaRhoPiChiIotaPrepareTheta(20, A, E) \ 193 | thetaRhoPiChiIotaPrepareTheta(21, E, A) \ 194 | thetaRhoPiChiIotaPrepareTheta(22, A, E) \ 195 | thetaRhoPiChiIota(23, E, A) \ 196 | 197 | #elif (Unrolling == 3) 198 | #define rounds24 \ 199 | prepareTheta \ 200 | for(i=0; i<24; i+=3) { \ 201 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 202 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 203 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ 204 | copyStateVariables(A, E) \ 205 | } \ 206 | 207 | #define rounds12 \ 208 | prepareTheta \ 209 | for(i=12; i<24; i+=3) { \ 210 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 211 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 212 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ 213 | copyStateVariables(A, E) \ 214 | } \ 215 | 216 | #define rounds6 \ 217 | prepareTheta \ 218 | for(i=18; i<24; i+=3) { \ 219 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 220 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 221 | thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ 222 | copyStateVariables(A, E) \ 223 | } \ 224 | 225 | #define rounds4 \ 226 | prepareTheta \ 227 | for(i=20; i<24; i+=2) { \ 228 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 229 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 230 | } \ 231 | 232 | #elif (Unrolling == 2) 233 | #define rounds24 \ 234 | prepareTheta \ 235 | for(i=0; i<24; i+=2) { \ 236 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 237 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 238 | } \ 239 | 240 | #define rounds12 \ 241 | prepareTheta \ 242 | for(i=12; i<24; i+=2) { \ 243 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 244 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 245 | } \ 246 | 247 | #define rounds6 \ 248 | prepareTheta \ 249 | for(i=18; i<24; i+=2) { \ 250 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 251 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 252 | } \ 253 | 254 | #define rounds4 \ 255 | prepareTheta \ 256 | for(i=20; i<24; i+=2) { \ 257 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 258 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 259 | } \ 260 | 261 | #elif (Unrolling == 1) 262 | #define rounds24 \ 263 | prepareTheta \ 264 | for(i=0; i<24; i++) { \ 265 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 266 | copyStateVariables(A, E) \ 267 | } \ 268 | 269 | #define rounds12 \ 270 | prepareTheta \ 271 | for(i=12; i<24; i++) { \ 272 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 273 | copyStateVariables(A, E) \ 274 | } \ 275 | 276 | #define rounds6 \ 277 | prepareTheta \ 278 | for(i=18; i<24; i++) { \ 279 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 280 | copyStateVariables(A, E) \ 281 | } \ 282 | 283 | #define rounds4 \ 284 | prepareTheta \ 285 | for(i=20; i<24; i++) { \ 286 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 287 | copyStateVariables(A, E) \ 288 | } \ 289 | 290 | #else 291 | #error "Unrolling is not correctly specified!" 292 | #endif 293 | 294 | #define roundsN(__nrounds) \ 295 | prepareTheta \ 296 | i = 24 - (__nrounds); \ 297 | if ((i&1) != 0) { \ 298 | thetaRhoPiChiIotaPrepareTheta(i, A, E) \ 299 | copyStateVariables(A, E) \ 300 | ++i; \ 301 | } \ 302 | for( /* empty */; i<24; i+=2) { \ 303 | thetaRhoPiChiIotaPrepareTheta(i , A, E) \ 304 | thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ 305 | } 306 | -------------------------------------------------------------------------------- /keccak/opt64/PlSnP-Fallback.inc: -------------------------------------------------------------------------------- 1 | /* 2 | Implementation by Gilles Van Assche, hereby denoted as "the implementer". 3 | 4 | For more information, feedback or questions, please refer to our website: 5 | https://keccak.team/ 6 | 7 | To the extent possible under law, the implementer has waived all copyright 8 | and related or neighboring rights to the source code in this file. 9 | http://creativecommons.org/publicdomain/zero/1.0/ 10 | 11 | --- 12 | 13 | This file contains macros that help make a PlSnP-compatible implementation by 14 | serially falling back on a SnP-compatible implementation or on a PlSnP-compatible 15 | implementation of lower parallism degree. 16 | 17 | Please refer to PlSnP-documentation.h for more details. 18 | */ 19 | 20 | /* expect PlSnP_baseParallelism, PlSnP_targetParallelism */ 21 | /* expect SnP_stateSizeInBytes, SnP_stateAlignment */ 22 | /* expect prefix */ 23 | /* expect SnP_* */ 24 | 25 | #define JOIN0(a, b) a ## b 26 | #define JOIN(a, b) JOIN0(a, b) 27 | 28 | #define PlSnP_StaticInitialize JOIN(prefix, _StaticInitialize) 29 | #define PlSnP_InitializeAll JOIN(prefix, _InitializeAll) 30 | #define PlSnP_AddByte JOIN(prefix, _AddByte) 31 | #define PlSnP_AddBytes JOIN(prefix, _AddBytes) 32 | #define PlSnP_AddLanesAll JOIN(prefix, _AddLanesAll) 33 | #define PlSnP_OverwriteBytes JOIN(prefix, _OverwriteBytes) 34 | #define PlSnP_OverwriteLanesAll JOIN(prefix, _OverwriteLanesAll) 35 | #define PlSnP_OverwriteWithZeroes JOIN(prefix, _OverwriteWithZeroes) 36 | #define PlSnP_ExtractBytes JOIN(prefix, _ExtractBytes) 37 | #define PlSnP_ExtractLanesAll JOIN(prefix, _ExtractLanesAll) 38 | #define PlSnP_ExtractAndAddBytes JOIN(prefix, _ExtractAndAddBytes) 39 | #define PlSnP_ExtractAndAddLanesAll JOIN(prefix, _ExtractAndAddLanesAll) 40 | 41 | #if (PlSnP_baseParallelism == 1) 42 | #define SnP_stateSizeInBytes JOIN(SnP, _stateSizeInBytes) 43 | #define SnP_stateAlignment JOIN(SnP, _stateAlignment) 44 | #else 45 | #define SnP_stateSizeInBytes JOIN(SnP, _statesSizeInBytes) 46 | #define SnP_stateAlignment JOIN(SnP, _statesAlignment) 47 | #endif 48 | #define PlSnP_factor ((PlSnP_targetParallelism)/(PlSnP_baseParallelism)) 49 | #define SnP_stateOffset (((SnP_stateSizeInBytes+(SnP_stateAlignment-1))/SnP_stateAlignment)*SnP_stateAlignment) 50 | #define stateWithIndex(i) ((unsigned char *)states+((i)*SnP_stateOffset)) 51 | 52 | #define SnP_StaticInitialize JOIN(SnP, _StaticInitialize) 53 | #define SnP_Initialize JOIN(SnP, _Initialize) 54 | #define SnP_InitializeAll JOIN(SnP, _InitializeAll) 55 | #define SnP_AddByte JOIN(SnP, _AddByte) 56 | #define SnP_AddBytes JOIN(SnP, _AddBytes) 57 | #define SnP_AddLanesAll JOIN(SnP, _AddLanesAll) 58 | #define SnP_OverwriteBytes JOIN(SnP, _OverwriteBytes) 59 | #define SnP_OverwriteLanesAll JOIN(SnP, _OverwriteLanesAll) 60 | #define SnP_OverwriteWithZeroes JOIN(SnP, _OverwriteWithZeroes) 61 | #define SnP_ExtractBytes JOIN(SnP, _ExtractBytes) 62 | #define SnP_ExtractLanesAll JOIN(SnP, _ExtractLanesAll) 63 | #define SnP_ExtractAndAddBytes JOIN(SnP, _ExtractAndAddBytes) 64 | #define SnP_ExtractAndAddLanesAll JOIN(SnP, _ExtractAndAddLanesAll) 65 | 66 | void PlSnP_StaticInitialize( void ) 67 | { 68 | SnP_StaticInitialize(); 69 | } 70 | 71 | void PlSnP_InitializeAll(void *states) 72 | { 73 | unsigned int i; 74 | 75 | for(i=0; i 22 | 23 | #elif defined(__APPLE__) 24 | 25 | #include 26 | 27 | #define htobe16(x) OSSwapHostToBigInt16(x) 28 | #define htole16(x) OSSwapHostToLittleInt16(x) 29 | #define be16toh(x) OSSwapBigToHostInt16(x) 30 | #define le16toh(x) OSSwapLittleToHostInt16(x) 31 | 32 | #define htobe32(x) OSSwapHostToBigInt32(x) 33 | #define htole32(x) OSSwapHostToLittleInt32(x) 34 | #define be32toh(x) OSSwapBigToHostInt32(x) 35 | #define le32toh(x) OSSwapLittleToHostInt32(x) 36 | 37 | #define htobe64(x) OSSwapHostToBigInt64(x) 38 | #define htole64(x) OSSwapHostToLittleInt64(x) 39 | #define be64toh(x) OSSwapBigToHostInt64(x) 40 | #define le64toh(x) OSSwapLittleToHostInt64(x) 41 | 42 | #define __BYTE_ORDER BYTE_ORDER 43 | #define __BIG_ENDIAN BIG_ENDIAN 44 | #define __LITTLE_ENDIAN LITTLE_ENDIAN 45 | #define __PDP_ENDIAN PDP_ENDIAN 46 | 47 | #elif defined(__OpenBSD__) 48 | 49 | #include 50 | 51 | #elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) 52 | 53 | #include 54 | 55 | #define be16toh(x) betoh16(x) 56 | #define le16toh(x) letoh16(x) 57 | 58 | #define be32toh(x) betoh32(x) 59 | #define le32toh(x) letoh32(x) 60 | 61 | #define be64toh(x) betoh64(x) 62 | #define le64toh(x) letoh64(x) 63 | 64 | #elif defined(__WINDOWS__) 65 | 66 | #include 67 | 68 | #if BYTE_ORDER == LITTLE_ENDIAN 69 | 70 | #if defined(_MSC_VER) 71 | #include 72 | #define htobe16(x) _byteswap_ushort(x) 73 | #define htole16(x) (x) 74 | #define be16toh(x) _byteswap_ushort(x) 75 | #define le16toh(x) (x) 76 | 77 | #define htobe32(x) _byteswap_ulong(x) 78 | #define htole32(x) (x) 79 | #define be32toh(x) _byteswap_ulong(x) 80 | #define le32toh(x) (x) 81 | 82 | #define htobe64(x) _byteswap_uint64(x) 83 | #define htole64(x) (x) 84 | #define be64toh(x) _byteswap_uint64(x) 85 | #define le64toh(x) (x) 86 | 87 | #elif defined(__GNUC__) || defined(__clang__) 88 | 89 | #define htobe16(x) __builtin_bswap16(x) 90 | #define htole16(x) (x) 91 | #define be16toh(x) __builtin_bswap16(x) 92 | #define le16toh(x) (x) 93 | 94 | #define htobe32(x) __builtin_bswap32(x) 95 | #define htole32(x) (x) 96 | #define be32toh(x) __builtin_bswap32(x) 97 | #define le32toh(x) (x) 98 | 99 | #define htobe64(x) __builtin_bswap64(x) 100 | #define htole64(x) (x) 101 | #define be64toh(x) __builtin_bswap64(x) 102 | #define le64toh(x) (x) 103 | #else 104 | #error platform not supported 105 | #endif 106 | 107 | #else 108 | 109 | #error byte order not supported 110 | 111 | #endif 112 | 113 | #define __BYTE_ORDER BYTE_ORDER 114 | #define __BIG_ENDIAN BIG_ENDIAN 115 | #define __LITTLE_ENDIAN LITTLE_ENDIAN 116 | #define __PDP_ENDIAN PDP_ENDIAN 117 | 118 | #else 119 | 120 | #error platform not supported 121 | 122 | #endif 123 | 124 | #endif -------------------------------------------------------------------------------- /macros.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the optimized implementation of the Picnic signature 3 | * scheme. 4 | * See the accompanying documentation for complete details. 5 | * The code is provided under the MIT license: 6 | * 7 | * Copyright (c) 2019-2020 Sebastian Ramacher, AIT 8 | * Copyright (c) 2016-2020 Graz University of Technology 9 | * Copyright (c) 2017 Angela Promitzer 10 | 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the ""Software""), to 13 | * deal in the Software without restriction, including without limitation the 14 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 15 | * sell copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in 19 | * all copies or substantial portions of the Software. 20 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | */ 28 | 29 | #ifndef PICNIC_MACROS_H 30 | #define PICNIC_MACROS_H 31 | 32 | /* __FUNCTION__ generates a warning on Linux with -Wpedantic and newer versions 33 | * of GCC (tested with 5.4). So we use __func__ in all source and define it on 34 | * Windows. 35 | */ 36 | #if defined(__WINDOWS__) 37 | #define __func__ __FUNCTION__ 38 | #endif 39 | 40 | /* compatibility with clang and other compilers */ 41 | #if !defined(__has_attribute) 42 | #define __has_attribute(a) 0 43 | #endif 44 | 45 | #if !defined(__has_builtin) 46 | #define __has_builtin(b) 0 47 | #endif 48 | 49 | /* gcc version check macro */ 50 | #if defined(__GNUC__) && defined(__GNUC_MINOR__) 51 | #define GNUC_CHECK(maj, min) \ 52 | (((__GNUC__ << 20) + (__GNUC_MINOR__ << 10)) >= \ 53 | (((maj) << 20) + ((min) << 10))) 54 | #else 55 | #define GNUC_CHECK(maj, min) 0 56 | #endif 57 | 58 | /* glibc version check macro */ 59 | #if defined(__GLIBC__) 60 | #define GLIBC_CHECK(maj, min) __GLIBC_PREREQ(maj, min) 61 | #else 62 | #define GLIBC_CHECK(maj, min) 0 63 | #endif 64 | 65 | /* FreeBSD version check macro */ 66 | #if defined(__FreeBSD__) 67 | #define FREEBSD_CHECK(maj, min) (__FreeBSD__ >= (maj)) 68 | #else 69 | #define FREEBSD_CHECK(maj, min) 0 70 | #endif 71 | 72 | /* NetBSD version check macro */ 73 | #if defined(__NetBSD__) 74 | #include 75 | #define NETBSD_CHECK(maj, min) \ 76 | (__NetBSD_Version__ >= ((maj)*1000000000 + (min)*10000000)) 77 | #else 78 | #define NETBSD_CHECK(maj, min) 0 79 | #endif 80 | 81 | /* Apple version check macro */ 82 | #if defined(__APPLE__) 83 | #include 84 | #define MACOSX_CHECK(maj, min, rev) \ 85 | (__MAC_OS_X_VERSION_MIN_REQUIRED >= ((maj)*10000 + (min)*100 + (rev))) 86 | #else 87 | #define MACOSX_CHECK(maj, min, rev) 0 88 | #endif 89 | 90 | #ifndef MIN 91 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) 92 | #endif 93 | 94 | #ifndef MAX 95 | #define MAX(a, b) ((a) > (b) ? (a) : (b)) 96 | #endif 97 | 98 | /* assume */ 99 | #if GNUC_CHECK(4, 5) || __has_builtin(__builtin_unreachable) 100 | #define ASSUME(p) \ 101 | if (!(p)) \ 102 | __builtin_unreachable() 103 | #elif defined(_MSC_VER) 104 | #define ASSUME(p) __assume(p) 105 | #else 106 | #define ASSUME(p) (void)(p) 107 | #endif 108 | 109 | /* nonnull attribute */ 110 | #if GNUC_CHECK(3, 3) || __has_attribute(nonnull) 111 | #define ATTR_NONNULL __attribute__((nonnull)) 112 | #define ATTR_NONNULL_ARG(i) __attribute__((nonnull(i))) 113 | #else 114 | #define ATTR_NONNULL 115 | #define ATTR_NONNULL_ARG(i) 116 | #endif 117 | 118 | /* destructor attribute */ 119 | #if GNUC_CHECK(2, 7) || __has_attribute(destructor) 120 | #define ATTR_DTOR __attribute__((destructor)) 121 | #else 122 | #define ATTR_DTOR 123 | #endif 124 | 125 | /* assumed aligned attribute */ 126 | #if GNUC_CHECK(4, 9) || __has_attribute(assume_aligned) 127 | #define ATTR_ASSUME_ALIGNED(i) __attribute__((assume_aligned(i))) 128 | #else 129 | #define ATTR_ASSUME_ALIGNED(i) 130 | #endif 131 | 132 | /* aligned attribute */ 133 | /* note that C11's alignas will only do the job once DR 444 is implemented */ 134 | #if GNUC_CHECK(4, 9) || __has_attribute(aligned) 135 | #define ATTR_ALIGNED(i) __attribute__((aligned((i)))) 136 | #define HAVE_USEFUL_ATTR_ALIGNED 137 | /* #elif defined(_MSC_VER) 138 | #define ATTR_ALIGNED(i) __declspec(align((i))) 139 | #define HAVE_USEFUL_ATTR_ALIGNED */ 140 | #else 141 | #define ATTR_ALIGNED(i) 142 | #endif 143 | 144 | /* round size to meet alignment requirements */ 145 | #define ALIGNT(s, t) (((s) + sizeof(t) - 1) & ~(sizeof(t) - 1)) 146 | #define ALIGNU64T(s) ALIGNT(s, uint64_t) 147 | 148 | /* unreachable builtin */ 149 | #if GNUC_CHECK(4, 5) || __has_builtin(__builtin_unreachable) 150 | #define UNREACHABLE __builtin_unreachable() 151 | /* #elif defined(_MSC_VER) 152 | #define UNREACHABLE __assume(0) */ 153 | #endif 154 | 155 | /* assume aligned builtin */ 156 | #if GNUC_CHECK(4, 9) || __has_builtin(__builtin_assume_aligned) 157 | #define ASSUME_ALIGNED(p, a) __builtin_assume_aligned((p), (a)) 158 | #elif defined(UNREACHABLE) && defined(HAVE_USEFUL_ATTR_ALIGNED) 159 | #define ASSUME_ALIGNED(p, a) \ 160 | (((((uintptr_t)(p)) % (a)) == 0) ? (p) : (UNREACHABLE, (p))) 161 | #else 162 | #define ASSUME_ALIGNED(p, a) (p) 163 | #endif 164 | 165 | /* always inline attribute */ 166 | #if GNUC_CHECK(4, 0) || __has_attribute(always_inline) 167 | #define ATTR_ALWAYS_INLINE __attribute__((always_inline)) 168 | #elif defined(_MSC_VER) 169 | #define ATTR_ALWAYS_INLINE __forceinline 170 | #else 171 | #define ATTR_ALWAYS_INLINE 172 | #endif 173 | 174 | /* pure attribute */ 175 | #if defined(__GNUC__) || __has_attribute(pure) 176 | #define ATTR_PURE __attribute__((pure)) 177 | #else 178 | #define ATTR_PURE 179 | #endif 180 | 181 | /* const attribute */ 182 | #if defined(__GNUC__) || __has_attribute(const) 183 | #define ATTR_CONST __attribute__((const)) 184 | #else 185 | #define ATTR_CONST 186 | #endif 187 | 188 | /* target attribute */ 189 | #if defined(__GNUC__) || __has_attribute(target) 190 | #define ATTR_TARGET(x) __attribute__((target((x)))) 191 | #else 192 | #define ATTR_TARGET(x) 193 | #endif 194 | 195 | /* artificial attribute */ 196 | #if GNUC_CHECK(4, 7) || __has_attribute(__artificial__) 197 | #define ATTR_ARTIFICIAL __attribute__((__artificial__)) 198 | #else 199 | #define ATTR_ARTIFICIAL 200 | #endif 201 | 202 | #define ATTR_TARGET_AVX2 ATTR_TARGET("avx2,bmi2") 203 | #define ATTR_TARGET_SSE2 ATTR_TARGET("sse2") 204 | 205 | #define FN_ATTRIBUTES_AVX2 ATTR_ARTIFICIAL ATTR_ALWAYS_INLINE ATTR_TARGET_AVX2 206 | #define FN_ATTRIBUTES_SSE2 ATTR_ARTIFICIAL ATTR_ALWAYS_INLINE ATTR_TARGET_SSE2 207 | #define FN_ATTRIBUTES_NEON ATTR_ARTIFICIAL ATTR_ALWAYS_INLINE 208 | 209 | #define FN_ATTRIBUTES_AVX2_PURE FN_ATTRIBUTES_AVX2 ATTR_PURE 210 | #define FN_ATTRIBUTES_SSE2_PURE FN_ATTRIBUTES_SSE2 ATTR_PURE 211 | #define FN_ATTRIBUTES_NEON_PURE FN_ATTRIBUTES_NEON ATTR_PURE 212 | 213 | #define FN_ATTRIBUTES_AVX2_CONST FN_ATTRIBUTES_AVX2 ATTR_CONST 214 | #define FN_ATTRIBUTES_SSE2_CONST FN_ATTRIBUTES_SSE2 ATTR_CONST 215 | #define FN_ATTRIBUTES_NEON_CONST FN_ATTRIBUTES_NEON ATTR_CONST 216 | 217 | /* concatenation */ 218 | #define CONCAT2(a, b) a##_##b 219 | #define CONCAT(a, b) CONCAT2(a, b) 220 | 221 | /* helper macros/functions for checked integer subtraction */ 222 | #if GNUC_CHECK(5, 0) || __has_builtin(__builtin_add_overflow) 223 | #define sub_overflow_size_t(x, y, diff) __builtin_sub_overflow(x, y, diff) 224 | #else 225 | #include 226 | #include 227 | 228 | ATTR_ARTIFICIAL 229 | static inline bool sub_overflow_size_t(const size_t x, const size_t y, 230 | size_t *diff) { 231 | *diff = x - y; 232 | return x < y; 233 | } 234 | #endif 235 | 236 | #include 237 | 238 | /* helper functions for parity computations */ 239 | #if GNUC_CHECK(4, 9) || __has_builtin(__builtin_parity) 240 | ATTR_CONST ATTR_ARTIFICIAL static inline uint8_t parity64_uint8(uint8_t in) { 241 | return __builtin_parity(in); 242 | } 243 | 244 | ATTR_CONST ATTR_ARTIFICIAL static inline uint16_t parity64_uint16(uint16_t in) { 245 | return __builtin_parity(in); 246 | } 247 | 248 | ATTR_CONST ATTR_ARTIFICIAL static inline uint64_t parity64_uint64(uint64_t in) { 249 | return __builtin_parityll(in); 250 | } 251 | #else 252 | ATTR_CONST ATTR_ARTIFICIAL static inline uint8_t parity64_uint8(uint8_t in) { 253 | /* byte parity from: 254 | * https://graphics.stanford.edu/~seander/bithacks.html#ParityWith64Bits */ 255 | return (((in * UINT64_C(0x0101010101010101)) & UINT64_C(0x8040201008040201)) % 256 | 0x1FF) & 257 | 1; 258 | } 259 | 260 | ATTR_CONST ATTR_ARTIFICIAL static inline uint16_t parity64_uint16(uint16_t in) { 261 | in ^= in >> 1; 262 | in ^= in >> 2; 263 | in = (in & 0x1111) * 0x1111; 264 | return (in >> 12) & 1; 265 | } 266 | 267 | ATTR_CONST ATTR_ARTIFICIAL static inline uint64_t parity64_uint64(uint64_t in) { 268 | in ^= in >> 1; 269 | in ^= in >> 2; 270 | in = (in & 0x1111111111111111) * 0x1111111111111111; 271 | return (in >> 60) & 1; 272 | } 273 | #endif 274 | 275 | /* helper functions to compute number of leading zeroes */ 276 | #if GNUC_CHECK(4, 7) || __has_builtin(__builtin_clz) 277 | ATTR_CONST ATTR_ARTIFICIAL static inline uint32_t clz(uint32_t x) { 278 | return x ? __builtin_clz(x) : 32; 279 | } 280 | #else 281 | /* Number of leading zeroes of x. 282 | * From the book 283 | * H.S. Warren, *Hacker's Delight*, Pearson Education, 2003. 284 | * http://www.hackersdelight.org/hdcodetxt/nlz.c.txt 285 | */ 286 | ATTR_CONST ATTR_ARTIFICIAL static inline uint32_t clz(uint32_t x) { 287 | if (!x) { 288 | return 32; 289 | } 290 | 291 | uint32_t n = 1; 292 | if (!(x >> 16)) { 293 | n = n + 16; 294 | x = x << 16; 295 | } 296 | if (!(x >> 24)) { 297 | n = n + 8; 298 | x = x << 8; 299 | } 300 | if (!(x >> 28)) { 301 | n = n + 4; 302 | x = x << 4; 303 | } 304 | if (!(x >> 30)) { 305 | n = n + 2; 306 | x = x << 2; 307 | } 308 | n = n - (x >> 31); 309 | 310 | return n; 311 | } 312 | #endif 313 | 314 | ATTR_CONST ATTR_ARTIFICIAL static inline uint32_t ceil_log2(uint32_t x) { 315 | if (!x) { 316 | return 0; 317 | } 318 | return 32 - clz(x - 1); 319 | } 320 | 321 | #if defined(__WIN32__) 322 | #define SIZET_FMT "%Iu" 323 | #else 324 | #define SIZET_FMT "%zu" 325 | #endif 326 | 327 | /* crypto_declassify wrapper */ 328 | #if defined(TIMECOP) 329 | #include "crypto_declassify.h" 330 | #define picnic_declassify(x, len) crypto_declassify(x, len) 331 | #elif defined(WITH_VALGRIND) 332 | #include 333 | #define picnic_declassify(x, len) VALGRIND_MAKE_MEM_DEFINED(x, len) 334 | #else 335 | #define picnic_declassify(x, len) 336 | #endif 337 | 338 | #endif 339 | -------------------------------------------------------------------------------- /portable_endian.h: -------------------------------------------------------------------------------- 1 | // "License": Public Domain 2 | // I, Mathias Panzenboeck, place this file hereby into the public domain. Use it 3 | // at your own risk for whatever you like. In case there are jurisdictions that 4 | // don't support putting things in the public domain you can also consider it to 5 | // be "dual licensed" under the BSD, MIT and Apache licenses, if you want to. 6 | // This code is trivial anyway. Consider it an example on how to get the endian 7 | // conversion functions on different platforms. 8 | 9 | #ifndef PORTABLE_ENDIAN_H__ 10 | #define PORTABLE_ENDIAN_H__ 11 | 12 | #if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && \ 13 | !defined(__WINDOWS__) 14 | 15 | #define __WINDOWS__ 16 | 17 | #endif 18 | 19 | #if defined(__linux__) || defined(__CYGWIN__) 20 | 21 | #include 22 | 23 | #elif defined(__APPLE__) 24 | 25 | #include 26 | 27 | #define htobe16(x) OSSwapHostToBigInt16(x) 28 | #define htole16(x) OSSwapHostToLittleInt16(x) 29 | #define be16toh(x) OSSwapBigToHostInt16(x) 30 | #define le16toh(x) OSSwapLittleToHostInt16(x) 31 | 32 | #define htobe32(x) OSSwapHostToBigInt32(x) 33 | #define htole32(x) OSSwapHostToLittleInt32(x) 34 | #define be32toh(x) OSSwapBigToHostInt32(x) 35 | #define le32toh(x) OSSwapLittleToHostInt32(x) 36 | 37 | #define htobe64(x) OSSwapHostToBigInt64(x) 38 | #define htole64(x) OSSwapHostToLittleInt64(x) 39 | #define be64toh(x) OSSwapBigToHostInt64(x) 40 | #define le64toh(x) OSSwapLittleToHostInt64(x) 41 | 42 | #define __BYTE_ORDER BYTE_ORDER 43 | #define __BIG_ENDIAN BIG_ENDIAN 44 | #define __LITTLE_ENDIAN LITTLE_ENDIAN 45 | #define __PDP_ENDIAN PDP_ENDIAN 46 | 47 | #elif defined(__OpenBSD__) 48 | 49 | #include 50 | 51 | #elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) 52 | 53 | #include 54 | 55 | #define be16toh(x) betoh16(x) 56 | #define le16toh(x) letoh16(x) 57 | 58 | #define be32toh(x) betoh32(x) 59 | #define le32toh(x) letoh32(x) 60 | 61 | #define be64toh(x) betoh64(x) 62 | #define le64toh(x) letoh64(x) 63 | 64 | #elif defined(__WINDOWS__) 65 | 66 | #include 67 | 68 | #if BYTE_ORDER == LITTLE_ENDIAN 69 | 70 | #if defined(_MSC_VER) 71 | #include 72 | #define htobe16(x) _byteswap_ushort(x) 73 | #define htole16(x) (x) 74 | #define be16toh(x) _byteswap_ushort(x) 75 | #define le16toh(x) (x) 76 | 77 | #define htobe32(x) _byteswap_ulong(x) 78 | #define htole32(x) (x) 79 | #define be32toh(x) _byteswap_ulong(x) 80 | #define le32toh(x) (x) 81 | 82 | #define htobe64(x) _byteswap_uint64(x) 83 | #define htole64(x) (x) 84 | #define be64toh(x) _byteswap_uint64(x) 85 | #define le64toh(x) (x) 86 | 87 | #elif defined(__GNUC__) || defined(__clang__) 88 | 89 | #define htobe16(x) __builtin_bswap16(x) 90 | #define htole16(x) (x) 91 | #define be16toh(x) __builtin_bswap16(x) 92 | #define le16toh(x) (x) 93 | 94 | #define htobe32(x) __builtin_bswap32(x) 95 | #define htole32(x) (x) 96 | #define be32toh(x) __builtin_bswap32(x) 97 | #define le32toh(x) (x) 98 | 99 | #define htobe64(x) __builtin_bswap64(x) 100 | #define htole64(x) (x) 101 | #define be64toh(x) __builtin_bswap64(x) 102 | #define le64toh(x) (x) 103 | #else 104 | #error platform not supported 105 | #endif 106 | 107 | #else 108 | 109 | #error byte order not supported 110 | 111 | #endif 112 | 113 | #define __BYTE_ORDER BYTE_ORDER 114 | #define __BIG_ENDIAN BIG_ENDIAN 115 | #define __LITTLE_ENDIAN LITTLE_ENDIAN 116 | #define __PDP_ENDIAN PDP_ENDIAN 117 | 118 | #else 119 | 120 | #error platform not supported 121 | 122 | #endif 123 | 124 | #endif -------------------------------------------------------------------------------- /randomness.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the optimized implementation of the Picnic signature 3 | * scheme. 4 | * See the accompanying documentation for complete details. 5 | * The code is provided under the MIT license: 6 | * 7 | * Copyright (c) 2019-2020 Sebastian Ramacher, AIT 8 | * Copyright (c) 2016-2020 Graz University of Technology 9 | * Copyright (c) 2017 Angela Promitzer 10 | 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the ""Software""), to 13 | * deal in the Software without restriction, including without limitation the 14 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 15 | * sell copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in 19 | * all copies or substantial portions of the Software. 20 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | */ 28 | 29 | #include "randomness.h" 30 | 31 | #if defined(__linux__) && (__GLIBC__ > 2 || __GLIBC_MINOR__ >= 25) 32 | #include 33 | 34 | int rand_bytes(uint8_t *dst, size_t len) { 35 | const ssize_t ret = getrandom(dst, len, GRND_NONBLOCK); 36 | if (ret < 0 || (size_t)ret != len) { 37 | return 0; 38 | } 39 | return 1; 40 | } 41 | #elif defined(__APPLE__) && defined(HAVE_APPLE_FRAMEWORK) 42 | #include 43 | 44 | int rand_bytes(uint8_t *dst, size_t len) { 45 | if (SecRandomCopyBytes(kSecRandomDefault, len, dst) == errSecSuccess) { 46 | return 1; 47 | } 48 | return 0; 49 | } 50 | #elif defined(__linux__) || defined(__APPLE__) 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | 57 | #if defined(__linux__) 58 | #include 59 | #include 60 | #endif 61 | 62 | #if !defined(O_NOFOLLOW) 63 | #define O_NOFOLLOW 0 64 | #endif 65 | #if !defined(O_CLOEXEC) 66 | #define O_CLOEXEC 0 67 | #endif 68 | 69 | int rand_bytes(uint8_t *dst, size_t len) { 70 | int fd; 71 | while ((fd = open("/dev/urandom", O_RDONLY | O_NOFOLLOW | O_CLOEXEC, 0)) == 72 | -1) { 73 | // check if we should restart 74 | if (errno != EINTR) { 75 | return 0; 76 | } 77 | } 78 | #if O_CLOEXEC == 0 79 | fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); 80 | #endif 81 | 82 | #if defined(__linux__) 83 | int cnt = 0; 84 | if (ioctl(fd, RNDGETENTCNT, &cnt) == -1) { 85 | // not ready 86 | close(fd); 87 | return 0; 88 | } 89 | #endif 90 | 91 | while (len) { 92 | const ssize_t ret = read(fd, dst, len); 93 | if (ret == -1) { 94 | if (errno == EAGAIN || errno == EINTR) { 95 | // retry 96 | continue; 97 | } 98 | close(fd); 99 | return 0; 100 | } 101 | 102 | dst += ret; 103 | len -= ret; 104 | } 105 | 106 | close(fd); 107 | return 1; 108 | } 109 | #elif defined(_WIN16) || defined(_WIN32) || defined(_WIN64) 110 | #include 111 | 112 | int rand_bytes(uint8_t *dst, size_t len) { 113 | if (len > ULONG_MAX) { 114 | return 0; 115 | } 116 | if (!BCRYPT_SUCCESS(BCryptGenRandom(NULL, dst, (ULONG)len, 117 | BCRYPT_USE_SYSTEM_PREFERRED_RNG))) { 118 | return 0; 119 | } 120 | return 1; 121 | } 122 | #else 123 | #error "Unsupported OS! Please implement rand_bytes." 124 | #endif 125 | -------------------------------------------------------------------------------- /randomness.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the optimized implementation of the Picnic signature 3 | * scheme. 4 | * See the accompanying documentation for complete details. 5 | * The code is provided under the MIT license: 6 | * 7 | * Copyright (c) 2019-2020 Sebastian Ramacher, AIT 8 | * Copyright (c) 2016-2020 Graz University of Technology 9 | * Copyright (c) 2017 Angela Promitzer 10 | 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the ""Software""), to 13 | * deal in the Software without restriction, including without limitation the 14 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 15 | * sell copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in 19 | * all copies or substantial portions of the Software. 20 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | */ 28 | 29 | #ifndef RANDOMNESS_H 30 | #define RANDOMNESS_H 31 | 32 | #include 33 | #include 34 | 35 | int rand_bytes(uint8_t *dst, size_t len); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /tape.cpp: -------------------------------------------------------------------------------- 1 | #include "tape.h" 2 | 3 | RandomTape::RandomTape(const gsl::span &seed, 4 | const banquet_salt_t &salt, size_t rep_index, 5 | size_t party_index) { 6 | hash_init(&ctx, seed.size() * 2); 7 | hash_update(&ctx, seed.data(), seed.size()); 8 | hash_update(&ctx, salt.data(), salt.size()); 9 | hash_update_uint16_le(&ctx, (uint16_t)rep_index); 10 | hash_update_uint16_le(&ctx, (uint16_t)party_index); 11 | hash_final(&ctx); 12 | } 13 | 14 | void RandomTape::squeeze_bytes(uint8_t *out, size_t len) { 15 | hash_squeeze(&ctx, out, len); 16 | } 17 | 18 | void RandomTapes::generate_4_tapes(size_t repetition, size_t start_party, 19 | const banquet_salt_t &salt, 20 | const gsl::span &seed0, 21 | const gsl::span &seed1, 22 | const gsl::span &seed2, 23 | const gsl::span &seed3) { 24 | 25 | hash_context_x4 ctx; 26 | hash_init_x4(&ctx, seed0.size() * 2); 27 | hash_update_x4_4(&ctx, seed0.data(), seed1.data(), seed2.data(), seed3.data(), 28 | seed0.size()); 29 | hash_update_x4_1(&ctx, salt.data(), salt.size()); 30 | hash_update_x4_uint16_le(&ctx, (uint16_t)repetition); 31 | const uint16_t parties[4] = { 32 | (uint16_t)(start_party), (uint16_t)(start_party + 1), 33 | (uint16_t)(start_party + 2), (uint16_t)(start_party + 3)}; 34 | hash_update_x4_uint16s_le(&ctx, parties); 35 | hash_final_x4(&ctx); 36 | hash_squeeze_x4_4(&ctx, random_tapes.get(repetition, parties[0]).data(), 37 | random_tapes.get(repetition, parties[1]).data(), 38 | random_tapes.get(repetition, parties[2]).data(), 39 | random_tapes.get(repetition, parties[3]).data(), 40 | random_tape_size); 41 | } 42 | void RandomTapes::generate_tape(size_t repetition, size_t party, 43 | const banquet_salt_t &salt, 44 | const gsl::span &seed) { 45 | hash_context ctx; 46 | hash_init(&ctx, seed.size() * 2); 47 | hash_update(&ctx, seed.data(), seed.size()); 48 | hash_update(&ctx, salt.data(), salt.size()); 49 | hash_update_uint16_le(&ctx, (uint16_t)repetition); 50 | hash_update_uint16_le(&ctx, (uint16_t)party); 51 | hash_final(&ctx); 52 | hash_squeeze(&ctx, random_tapes.get(repetition, party).data(), 53 | random_tape_size); 54 | } 55 | 56 | gsl::span RandomTapes::get_bytes(size_t repetition, size_t party, 57 | size_t start, size_t len) { 58 | auto tape = random_tapes.get(repetition, party); 59 | return tape.subspan(start, len); 60 | } -------------------------------------------------------------------------------- /tape.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "banquet.h" 4 | extern "C" { 5 | #include "kdf_shake.h" 6 | } 7 | #include "gsl-lite.hpp" 8 | #include "tree.h" 9 | #include 10 | 11 | class RandomTape { 12 | private: 13 | /* data */ 14 | hash_context ctx; 15 | 16 | public: 17 | RandomTape(const gsl::span &seed, const banquet_salt_t &salt, 18 | size_t rep_index, size_t party_index); 19 | ~RandomTape() = default; 20 | 21 | void squeeze_bytes(uint8_t *out, size_t len); 22 | }; 23 | 24 | class RandomTapes { 25 | private: 26 | /* data */ 27 | RepByteContainer random_tapes; 28 | size_t random_tape_size; 29 | 30 | public: 31 | RandomTapes(size_t num_repetitions, size_t num_parties, 32 | size_t random_tape_size) 33 | : random_tapes(num_repetitions, num_parties, random_tape_size), 34 | random_tape_size(random_tape_size){}; 35 | ~RandomTapes() = default; 36 | 37 | void generate_4_tapes(size_t repetition, size_t start_party, 38 | const banquet_salt_t &salt, 39 | const gsl::span &seed0, 40 | const gsl::span &seed1, 41 | const gsl::span &seed2, 42 | const gsl::span &seed3); 43 | void generate_tape(size_t repetition, size_t party, 44 | const banquet_salt_t &salt, 45 | const gsl::span &seed); 46 | gsl::span get_bytes(size_t repetition, size_t party, size_t start, 47 | size_t len); 48 | }; -------------------------------------------------------------------------------- /tests/aes_test.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #include 3 | 4 | #include "../aes.h" 5 | 6 | TEST_CASE("AES-128 KAT", "[aes]") { 7 | const std::vector key = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 8 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 9 | 0xff, 0xff, 0xff, 0xff}; 10 | const std::vector plaintext = {0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 11 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 12 | 0x00, 0x00, 0x00, 0x00}; 13 | const std::vector ciphertext_expected = { 14 | 0x0b, 0x5a, 0x81, 0x4d, 0x95, 0x60, 0x1c, 0xc7, 15 | 0xef, 0xe7, 0x12, 0x28, 0x3e, 0x05, 0xef, 0x8f}; 16 | 17 | std::vector ct; 18 | 19 | REQUIRE(AES128::aes_128(key, plaintext, ct) == true); 20 | REQUIRE(ct == ciphertext_expected); 21 | } 22 | 23 | TEST_CASE("AES-192 KAT", "[aes]") { 24 | const std::vector key = { 25 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 26 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 27 | std::vector plaintext = {0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 28 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 29 | 0x00, 0x00, 0x00, 0x00}; 30 | plaintext.insert(plaintext.end(), plaintext.begin(), 31 | plaintext.begin() + plaintext.size()); 32 | std::vector ciphertext_expected = { 33 | 0x15, 0xc5, 0x99, 0x50, 0xf7, 0x9f, 0x74, 0x21, 34 | 0x4b, 0xc8, 0xfc, 0x50, 0x7c, 0x5f, 0x9b, 0xa6}; 35 | ciphertext_expected.insert( 36 | ciphertext_expected.end(), ciphertext_expected.begin(), 37 | ciphertext_expected.begin() + ciphertext_expected.size()); 38 | 39 | std::vector ct; 40 | 41 | REQUIRE(AES192::aes_192(key, plaintext, ct) == true); 42 | REQUIRE(ct == ciphertext_expected); 43 | } 44 | 45 | TEST_CASE("AES-256 KAT", "[aes]") { 46 | const std::vector key = { 47 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 48 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 49 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 50 | std::vector plaintext = {0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 51 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 52 | 0x00, 0x00, 0x00, 0x00}; 53 | plaintext.insert(plaintext.end(), plaintext.begin(), 54 | plaintext.begin() + plaintext.size()); 55 | 56 | std::vector ciphertext_expected = { 57 | 0x0b, 0x5c, 0xe5, 0x2a, 0x5c, 0xfc, 0x30, 0x02, 58 | 0x19, 0x22, 0x26, 0x92, 0x07, 0xb7, 0xd9, 0x66}; 59 | ciphertext_expected.insert( 60 | ciphertext_expected.end(), ciphertext_expected.begin(), 61 | ciphertext_expected.begin() + ciphertext_expected.size()); 62 | 63 | std::vector ct; 64 | 65 | REQUIRE(AES256::aes_256(key, plaintext, ct) == true); 66 | REQUIRE(ct == ciphertext_expected); 67 | } 68 | 69 | TEST_CASE("AES-128 normal is equal to sbox-saving", "[aes]") { 70 | const std::vector key = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 71 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 72 | 0xff, 0xff, 0xff, 0xff}; 73 | const std::vector plaintext = {0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 74 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 75 | 0x00, 0x00, 0x00, 0x00}; 76 | const std::vector ciphertext_expected = { 77 | 0x0b, 0x5a, 0x81, 0x4d, 0x95, 0x60, 0x1c, 0xc7, 78 | 0xef, 0xe7, 0x12, 0x28, 0x3e, 0x05, 0xef, 0x8f}; 79 | 80 | std::vector ct; 81 | std::vector ct2; 82 | 83 | REQUIRE(AES128::aes_128(key, plaintext, ct) == true); 84 | std::pair, std::vector> sbox_states = 85 | AES128::aes_128_with_sbox_output(key, plaintext, ct2); 86 | REQUIRE(ct == ciphertext_expected); 87 | REQUIRE(ct == ct2); 88 | REQUIRE(sbox_states.first.size() == AES128::NUM_SBOXES); 89 | REQUIRE(sbox_states.second.size() == AES128::NUM_SBOXES); 90 | } 91 | 92 | TEST_CASE("AES-192 normal is equal to sbox-saving", "[aes]") { 93 | const std::vector key = { 94 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 95 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 96 | std::vector plaintext = {0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 97 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 98 | 0x00, 0x00, 0x00, 0x00}; 99 | plaintext.insert(plaintext.end(), plaintext.begin(), 100 | plaintext.begin() + plaintext.size()); 101 | std::vector ciphertext_expected = { 102 | 0x15, 0xc5, 0x99, 0x50, 0xf7, 0x9f, 0x74, 0x21, 103 | 0x4b, 0xc8, 0xfc, 0x50, 0x7c, 0x5f, 0x9b, 0xa6}; 104 | ciphertext_expected.insert( 105 | ciphertext_expected.end(), ciphertext_expected.begin(), 106 | ciphertext_expected.begin() + ciphertext_expected.size()); 107 | 108 | std::vector ct; 109 | std::vector ct2; 110 | 111 | REQUIRE(AES192::aes_192(key, plaintext, ct) == true); 112 | std::pair, std::vector> sbox_states = 113 | AES192::aes_192_with_sbox_output(key, plaintext, ct2); 114 | REQUIRE(ct == ciphertext_expected); 115 | REQUIRE(ct == ct2); 116 | REQUIRE(sbox_states.first.size() == AES192::NUM_SBOXES); 117 | REQUIRE(sbox_states.second.size() == AES192::NUM_SBOXES); 118 | } 119 | 120 | TEST_CASE("AES-256 normal is equal to sbox-saving", "[aes]") { 121 | const std::vector key = { 122 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 123 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 124 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 125 | std::vector plaintext = {0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 126 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 127 | 0x00, 0x00, 0x00, 0x00}; 128 | plaintext.insert(plaintext.end(), plaintext.begin(), 129 | plaintext.begin() + plaintext.size()); 130 | std::vector ciphertext_expected = { 131 | 0x0b, 0x5c, 0xe5, 0x2a, 0x5c, 0xfc, 0x30, 0x02, 132 | 0x19, 0x22, 0x26, 0x92, 0x07, 0xb7, 0xd9, 0x66}; 133 | ciphertext_expected.insert( 134 | ciphertext_expected.end(), ciphertext_expected.begin(), 135 | ciphertext_expected.begin() + ciphertext_expected.size()); 136 | 137 | std::vector ct; 138 | std::vector ct2; 139 | 140 | REQUIRE(AES256::aes_256(key, plaintext, ct) == true); 141 | std::pair, std::vector> sbox_states = 142 | AES256::aes_256_with_sbox_output(key, plaintext, ct2); 143 | REQUIRE(ct == ciphertext_expected); 144 | REQUIRE(ct == ct2); 145 | REQUIRE(sbox_states.first.size() == AES256::NUM_SBOXES); 146 | REQUIRE(sbox_states.second.size() == AES256::NUM_SBOXES); 147 | } -------------------------------------------------------------------------------- /tests/field_test.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #include 3 | 4 | #include "../field.h" 5 | #include "utils.h" 6 | 7 | #include 8 | 9 | TEST_CASE("Basic Arithmetic in all fields", "[field]") { 10 | banquet_params_t params[] = {Banquet_L1_Param1, Banquet_L1_Param3, 11 | Banquet_L1_Param4}; 12 | for (auto param : params) { 13 | field::GF2E::init_extension_field(banquet_instance_get(param)); 14 | field::GF2E zero; 15 | field::GF2E one(1); 16 | field::GF2E x(2); 17 | field::GF2E x_2(4); 18 | 19 | REQUIRE(one + zero == one); 20 | REQUIRE(zero + one == one); 21 | REQUIRE(zero + zero == zero); 22 | REQUIRE(one + one == zero); 23 | 24 | REQUIRE(one * one == one); 25 | REQUIRE(zero * one == zero); 26 | REQUIRE(one * zero == zero); 27 | REQUIRE(zero * zero == zero); 28 | 29 | REQUIRE(x * one == x); 30 | REQUIRE(x * x == x_2); 31 | } 32 | } 33 | TEST_CASE("Modular Arithmetic GF(2^32)", "[field]") { 34 | field::GF2E::init_extension_field(banquet_instance_get(Banquet_L1_Param1)); 35 | field::GF2E a, b; 36 | a.set_coeff(31); 37 | a.set_coeff(29); 38 | a.set_coeff(28); 39 | a.set_coeff(24); 40 | a.set_coeff(23); 41 | a.set_coeff(21); 42 | a.set_coeff(19); 43 | a.set_coeff(15); 44 | a.set_coeff(14); 45 | a.set_coeff(9); 46 | a.set_coeff(8); 47 | a.set_coeff(0); 48 | 49 | b.set_coeff(29); 50 | b.set_coeff(27); 51 | b.set_coeff(26); 52 | b.set_coeff(25); 53 | b.set_coeff(20); 54 | b.set_coeff(17); 55 | b.set_coeff(14); 56 | b.set_coeff(11); 57 | b.set_coeff(10); 58 | b.set_coeff(5); 59 | b.set_coeff(3); 60 | b.set_coeff(2); 61 | field::GF2E a_int(2980627201), b_int(772951084); 62 | REQUIRE(a == a_int); 63 | REQUIRE(b == b_int); 64 | 65 | field::GF2E ab(3895706975); 66 | field::GF2E a_2(2846443116); 67 | field::GF2E b_2(234130046); 68 | REQUIRE(a * b == ab); 69 | REQUIRE(a * a == a_2); 70 | REQUIRE(b * b == b_2); 71 | } 72 | 73 | TEST_CASE("Modular Arithmetic GF(2^40)", "[field]") { 74 | field::GF2E::init_extension_field(banquet_instance_get(Banquet_L1_Param3)); 75 | field::GF2E a(683080732428ULL), b(437065243549ULL); 76 | 77 | field::GF2E ab(916833885315ULL); 78 | field::GF2E a_2(224904587486ULL); 79 | field::GF2E b_2(153370336291ULL); 80 | REQUIRE(a * b == ab); 81 | REQUIRE(a * a == a_2); 82 | REQUIRE(b * b == b_2); 83 | } 84 | 85 | TEST_CASE("Modular Arithmetic GF(2^48)", "[field]") { 86 | field::GF2E::init_extension_field(banquet_instance_get(Banquet_L1_Param4)); 87 | field::GF2E a(94834555057164ULL), b(119504161027501ULL); 88 | 89 | field::GF2E ab(130190305526807ULL); 90 | field::GF2E a_2(187414204277907ULL); 91 | field::GF2E b_2(119412372920018ULL); 92 | REQUIRE(a * b == ab); 93 | REQUIRE(a * a == a_2); 94 | REQUIRE(b * b == b_2); 95 | } 96 | 97 | TEST_CASE("NTL to_bytes = custom to_bytes", "[field]") { 98 | field::GF2E::init_extension_field(banquet_instance_get(Banquet_L1_Param1)); 99 | utils::init_extension_field(banquet_instance_get(Banquet_L1_Param1)); 100 | field::GF2E a, b; 101 | a.set_coeff(31); 102 | a.set_coeff(29); 103 | a.set_coeff(28); 104 | a.set_coeff(24); 105 | a.set_coeff(23); 106 | a.set_coeff(21); 107 | a.set_coeff(19); 108 | a.set_coeff(15); 109 | a.set_coeff(14); 110 | a.set_coeff(9); 111 | a.set_coeff(8); 112 | a.set_coeff(0); 113 | 114 | b.set_coeff(29); 115 | b.set_coeff(27); 116 | b.set_coeff(26); 117 | b.set_coeff(25); 118 | b.set_coeff(20); 119 | b.set_coeff(17); 120 | b.set_coeff(14); 121 | b.set_coeff(11); 122 | b.set_coeff(10); 123 | b.set_coeff(5); 124 | b.set_coeff(3); 125 | b.set_coeff(2); 126 | GF2X c, d; 127 | SetCoeff(c, 31); 128 | SetCoeff(c, 29); 129 | SetCoeff(c, 28); 130 | SetCoeff(c, 24); 131 | SetCoeff(c, 23); 132 | SetCoeff(c, 21); 133 | SetCoeff(c, 19); 134 | SetCoeff(c, 15); 135 | SetCoeff(c, 14); 136 | SetCoeff(c, 9); 137 | SetCoeff(c, 8); 138 | SetCoeff(c, 0); 139 | GF2E c_e = conv(c); 140 | 141 | SetCoeff(d, 29); 142 | SetCoeff(d, 27); 143 | SetCoeff(d, 26); 144 | SetCoeff(d, 25); 145 | SetCoeff(d, 20); 146 | SetCoeff(d, 17); 147 | SetCoeff(d, 14); 148 | SetCoeff(d, 11); 149 | SetCoeff(d, 10); 150 | SetCoeff(d, 5); 151 | SetCoeff(d, 3); 152 | SetCoeff(d, 2); 153 | GF2E d_e = conv(d); 154 | 155 | const GF2X &poly_rep_c = rep(c_e); 156 | std::vector buffer_c(4); 157 | BytesFromGF2X(buffer_c.data(), poly_rep_c, buffer_c.size()); 158 | const GF2X &poly_rep_d = rep(d_e); 159 | std::vector buffer_d(4); 160 | BytesFromGF2X(buffer_d.data(), poly_rep_d, buffer_d.size()); 161 | 162 | std::vector buffer_a(4); 163 | a.to_bytes(buffer_a.data()); 164 | std::vector buffer_b(4); 165 | b.to_bytes(buffer_b.data()); 166 | REQUIRE(buffer_a == buffer_c); 167 | REQUIRE(buffer_b == buffer_d); 168 | } 169 | TEST_CASE("NTL to custom conversion", "[field]") { 170 | banquet_params_t params[] = {Banquet_L1_Param1, Banquet_L1_Param3, 171 | Banquet_L1_Param4}; 172 | for (auto param : params) { 173 | utils::init_extension_field(banquet_instance_get(param)); 174 | field::GF2E::init_extension_field(banquet_instance_get(param)); 175 | field::GF2E a, b; 176 | a.set_coeff(31); 177 | a.set_coeff(29); 178 | a.set_coeff(28); 179 | a.set_coeff(24); 180 | a.set_coeff(23); 181 | a.set_coeff(21); 182 | a.set_coeff(19); 183 | a.set_coeff(15); 184 | a.set_coeff(14); 185 | a.set_coeff(9); 186 | a.set_coeff(8); 187 | a.set_coeff(0); 188 | 189 | b.set_coeff(29); 190 | b.set_coeff(27); 191 | b.set_coeff(26); 192 | b.set_coeff(25); 193 | b.set_coeff(20); 194 | b.set_coeff(17); 195 | b.set_coeff(14); 196 | b.set_coeff(11); 197 | b.set_coeff(10); 198 | b.set_coeff(5); 199 | b.set_coeff(3); 200 | b.set_coeff(2); 201 | 202 | field::GF2E ab = a * b; 203 | GF2E a_ntl = utils::custom_to_ntl(a); 204 | GF2E ab_ntl = utils::custom_to_ntl(ab); 205 | GF2E b_ntl = ab_ntl / a_ntl; 206 | field::GF2E b2 = utils::ntl_to_custom(b_ntl); 207 | REQUIRE(b == b2); 208 | } 209 | } 210 | TEST_CASE("NTL inverse == custom", "[field]") { 211 | banquet_params_t params[] = {Banquet_L1_Param1, Banquet_L1_Param3, 212 | Banquet_L1_Param4}; 213 | for (auto param : params) { 214 | utils::init_extension_field(banquet_instance_get(param)); 215 | field::GF2E::init_extension_field(banquet_instance_get(param)); 216 | field::GF2E a; 217 | a.set_coeff(31); 218 | a.set_coeff(29); 219 | a.set_coeff(28); 220 | a.set_coeff(24); 221 | a.set_coeff(23); 222 | a.set_coeff(21); 223 | a.set_coeff(19); 224 | a.set_coeff(15); 225 | a.set_coeff(14); 226 | a.set_coeff(9); 227 | a.set_coeff(8); 228 | a.set_coeff(0); 229 | 230 | field::GF2E b = a.inverse(); 231 | field::GF2E c = utils::ntl_to_custom(inv(utils::custom_to_ntl(a))); 232 | std::cout << utils::custom_to_ntl(a) << ", " << utils::custom_to_ntl(b) 233 | << ", " << utils::custom_to_ntl(c) << "\n"; 234 | std::cout << utils::custom_to_ntl(a * b) << ", " 235 | << utils::custom_to_ntl(a * c) << ", " 236 | << utils::custom_to_ntl(a) * utils::custom_to_ntl(c) << "\n"; 237 | REQUIRE(b == c); 238 | REQUIRE(a * b == field::GF2E(1)); 239 | } 240 | } 241 | TEST_CASE("NTL interpolation == custom", "[field]") { 242 | field::GF2E::init_extension_field(banquet_instance_get(Banquet_L1_Param1)); 243 | utils::init_extension_field(banquet_instance_get(Banquet_L1_Param1)); 244 | 245 | std::vector a = field::get_first_n_field_elements(100); 246 | vec_GF2E b = utils::get_first_n_field_elements(100); 247 | for (size_t i = 0; i < 100; i++) { 248 | REQUIRE(a[i] == utils::ntl_to_custom(b[i])); 249 | } 250 | std::vector a_from_roots = field::build_from_roots(a); 251 | GF2EX b_from_roots = BuildFromRoots(b); 252 | REQUIRE(a_from_roots.size() == (size_t)b_from_roots.rep.length()); 253 | for (size_t j = 0; j < a_from_roots.size(); j++) { 254 | REQUIRE(a_from_roots[j] == utils::ntl_to_custom(b_from_roots[j])); 255 | } 256 | 257 | std::vector> a_lag = 258 | field::precompute_lagrange_polynomials(a); 259 | std::vector b_lag = utils::precompute_lagrange_polynomials(b); 260 | 261 | REQUIRE(a_lag.size() == b_lag.size()); 262 | for (size_t i = 0; i < a_lag.size(); i++) { 263 | REQUIRE(a_lag[i].size() == (size_t)b_lag[i].rep.length()); 264 | for (size_t j = 0; j < a_lag[i].size(); j++) { 265 | REQUIRE(a_lag[i][j] == utils::ntl_to_custom(b_lag[i][j])); 266 | } 267 | } 268 | } -------------------------------------------------------------------------------- /tests/tree_test.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #include 3 | 4 | #include "../banquet.h" 5 | #include "../tree.h" 6 | 7 | TEST_CASE("Tree is constructed", "[tree]") { 8 | std::vector seed = {0, 1, 2, 3, 4, 5, 6, 7, 9 | 8, 9, 10, 11, 12, 13, 14, 15}; 10 | banquet_salt_t salt = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; 11 | SeedTree tree(seed, 64, salt, 0); 12 | for (size_t idx = 0; idx < 64; idx++) { 13 | REQUIRE(tree.get_leaf(idx)); 14 | } 15 | } 16 | 17 | TEST_CASE("Reveallist is constructed", "[tree]") { 18 | std::vector seed = {0, 1, 2, 3, 4, 5, 6, 7, 19 | 8, 9, 10, 11, 12, 13, 14, 15}; 20 | banquet_salt_t salt = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; 21 | SeedTree tree(seed, 64, salt, 0); 22 | reveal_list_t reveal_list = tree.reveal_all_but(0); 23 | REQUIRE(reveal_list.second == 0); 24 | REQUIRE(reveal_list.first.size() == 6); 25 | } 26 | 27 | TEST_CASE("Reveallist can reconstruct tree", "[tree]") { 28 | std::vector seed = {0, 1, 2, 3, 4, 5, 6, 7, 29 | 8, 9, 10, 11, 12, 13, 14, 15}; 30 | banquet_salt_t salt = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; 31 | SeedTree tree(seed, 64, salt, 0); 32 | reveal_list_t reveal_list = tree.reveal_all_but(0); 33 | SeedTree tree2(reveal_list, 64, salt, 0); 34 | 35 | REQUIRE(tree2.get_leaf(0).has_value() == false); 36 | for (size_t idx = 1; idx < 64; idx++) { 37 | REQUIRE(tree.get_leaf(idx).value() == tree2.get_leaf(idx).value()); 38 | } 39 | } -------------------------------------------------------------------------------- /tests/util_test.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #include 3 | 4 | #include "../banquet.h" 5 | #include "utils.h" 6 | #include 7 | #include 8 | 9 | TEST_CASE("Precomputed Lagrange Interpolation", "[util]") { 10 | const banquet_instance_t &instance = banquet_instance_get(Banquet_L1_Param1); 11 | utils::init_extension_field(instance); 12 | size_t dimension = 20; 13 | vec_GF2E x_values; 14 | vec_GF2E y_values1; 15 | vec_GF2E y_values2; 16 | for (size_t i = 0; i < dimension; i++) { 17 | x_values.append(random_GF2E()); 18 | y_values1.append(random_GF2E()); 19 | y_values2.append(random_GF2E()); 20 | } 21 | 22 | // builtin interpolate 23 | GF2EX poly1 = interpolate(x_values, y_values1); 24 | GF2EX poly2 = interpolate(x_values, y_values2); 25 | // precomputed interpolate 26 | auto precomputation = utils::precompute_lagrange_polynomials(x_values); 27 | GF2EX poly1_with_precom = 28 | utils::interpolate_with_precomputation(precomputation, y_values1); 29 | GF2EX poly2_with_precom = 30 | utils::interpolate_with_precomputation(precomputation, y_values2); 31 | 32 | REQUIRE(poly1 == poly1_with_precom); 33 | REQUIRE(poly2 == poly2_with_precom); 34 | } 35 | 36 | TEST_CASE("Basic Lifting tests", "[util]") { 37 | const banquet_instance_t &instance = banquet_instance_get(Banquet_L1_Param1); 38 | utils::init_extension_field(instance); 39 | uint8_t a = 3; 40 | uint8_t b = 246; 41 | 42 | GF2E a_lifted, b_lifted; 43 | GF2X tmp; 44 | // a_lifted should be y^30 + y^23 + y^21 + y^18 + y^14 + y^13 + y^11 + y^9 + 45 | // y^7 + y^6 + y^5 + y^4 + y^3 + y + 1 46 | SetCoeff(tmp, 30); 47 | SetCoeff(tmp, 23); 48 | SetCoeff(tmp, 21); 49 | SetCoeff(tmp, 18); 50 | SetCoeff(tmp, 14); 51 | SetCoeff(tmp, 13); 52 | SetCoeff(tmp, 11); 53 | SetCoeff(tmp, 9); 54 | SetCoeff(tmp, 7); 55 | SetCoeff(tmp, 6); 56 | SetCoeff(tmp, 5); 57 | SetCoeff(tmp, 4); 58 | SetCoeff(tmp, 3); 59 | SetCoeff(tmp, 1); 60 | SetCoeff(tmp, 0); 61 | a_lifted = conv(tmp); 62 | clear(tmp); 63 | // b_lifted should be y^30 + y^29 + y^27 + y^26 + y^25 + y^19 + y^18 + y^17 + 64 | // y^14 + y^13 + y^12 + y^10 + y^8 + y^7 + y^4 + y^2 + y 65 | SetCoeff(tmp, 30); 66 | SetCoeff(tmp, 29); 67 | SetCoeff(tmp, 27); 68 | SetCoeff(tmp, 26); 69 | SetCoeff(tmp, 25); 70 | SetCoeff(tmp, 19); 71 | SetCoeff(tmp, 18); 72 | SetCoeff(tmp, 17); 73 | SetCoeff(tmp, 14); 74 | SetCoeff(tmp, 13); 75 | SetCoeff(tmp, 12); 76 | SetCoeff(tmp, 10); 77 | SetCoeff(tmp, 8); 78 | SetCoeff(tmp, 7); 79 | SetCoeff(tmp, 4); 80 | SetCoeff(tmp, 2); 81 | SetCoeff(tmp, 1); 82 | b_lifted = conv(tmp); 83 | GF2E one; 84 | set(one); 85 | 86 | REQUIRE(utils::lift_uint8_t(a) == a_lifted); 87 | REQUIRE(utils::lift_uint8_t(b) == b_lifted); 88 | REQUIRE(a_lifted * b_lifted == one); 89 | } 90 | -------------------------------------------------------------------------------- /tests/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace NTL; 8 | 9 | namespace utils { 10 | 11 | static GF2X modulus; 12 | static std::array lifting_lut; 13 | 14 | static void init_lifting_lut(const GF2E &generator) { 15 | clear(lifting_lut[0]); // lut(0) = 0 16 | set(lifting_lut[1]); // lut(1) = 1 17 | 18 | GF2E pow = generator; 19 | for (size_t bit = 1; bit < 8; bit++) { 20 | size_t start = (1ULL << bit); 21 | // copy last half of LUT and add current generator power 22 | for (size_t idx = 0; idx < start; idx++) { 23 | lifting_lut[start + idx] = lifting_lut[idx] + pow; 24 | } 25 | pow = pow * generator; 26 | } 27 | } 28 | 29 | void init_extension_field(const banquet_instance_t &instance) { 30 | switch (instance.lambda) { 31 | case 4: { 32 | // modulus = x^32 + x^7 + x^3 + x^2 + 1 33 | clear(modulus); 34 | SetCoeff(modulus, 32); 35 | SetCoeff(modulus, 7); 36 | SetCoeff(modulus, 3); 37 | SetCoeff(modulus, 2); 38 | SetCoeff(modulus, 0); 39 | // Ring morphism: 40 | // From: Finite Field in x of size 2^8 41 | // To: Finite Field in y of size 2^32 42 | // Defn: x |--> y^30 + y^23 + y^21 + y^18 + y^14 + y^13 + y^11 + y^9 + y^7 43 | // + y^6 + y^5 + y^4 + y^3 + y 44 | GF2X gen; 45 | clear(gen); 46 | SetCoeff(gen, 30); 47 | SetCoeff(gen, 23); 48 | SetCoeff(gen, 21); 49 | SetCoeff(gen, 18); 50 | SetCoeff(gen, 14); 51 | SetCoeff(gen, 13); 52 | SetCoeff(gen, 11); 53 | SetCoeff(gen, 9); 54 | SetCoeff(gen, 7); 55 | SetCoeff(gen, 6); 56 | SetCoeff(gen, 5); 57 | SetCoeff(gen, 4); 58 | SetCoeff(gen, 3); 59 | SetCoeff(gen, 1); 60 | 61 | GF2E::init(modulus); 62 | init_lifting_lut(conv(gen)); 63 | } break; 64 | case 5: { 65 | // modulus = x^40 + x^5 + x^4 + x^3 + 1 66 | clear(modulus); 67 | SetCoeff(modulus, 40); 68 | SetCoeff(modulus, 5); 69 | SetCoeff(modulus, 4); 70 | SetCoeff(modulus, 3); 71 | SetCoeff(modulus, 0); 72 | // Ring morphism: 73 | // From: Finite Field in x of size 2^8 74 | // To: Finite Field in y of size 2^40 75 | // Defn: x |--> y^31 + y^30 + y^27 + y^25 + y^22 + y^21 + y^20 + y^18 + 76 | // y^15 + y^9 + y^6 + y^4 + y^2 77 | GF2X gen; 78 | clear(gen); 79 | SetCoeff(gen, 31); 80 | SetCoeff(gen, 30); 81 | SetCoeff(gen, 27); 82 | SetCoeff(gen, 25); 83 | SetCoeff(gen, 22); 84 | SetCoeff(gen, 21); 85 | SetCoeff(gen, 20); 86 | SetCoeff(gen, 18); 87 | SetCoeff(gen, 15); 88 | SetCoeff(gen, 9); 89 | SetCoeff(gen, 6); 90 | SetCoeff(gen, 4); 91 | SetCoeff(gen, 2); 92 | 93 | GF2E::init(modulus); 94 | init_lifting_lut(conv(gen)); 95 | } break; 96 | case 6: { 97 | // modulus = x^48 + x^5 + x^3 + x^2 + 1 98 | clear(modulus); 99 | SetCoeff(modulus, 48); 100 | SetCoeff(modulus, 5); 101 | SetCoeff(modulus, 3); 102 | SetCoeff(modulus, 2); 103 | SetCoeff(modulus, 0); 104 | // Ring morphism: 105 | // From: Finite Field in x of size 2^8 106 | // To: Finite Field in y of size 2^48 107 | // Defn: x |--> y^45 + y^43 + y^40 + y^37 + y^36 + y^35 + y^34 + y^33 + 108 | // y^31 + y^30 + y^29 + y^28 + y^24 + y^21 + y^20 + y^19 + y^16 + y^14 + 109 | // y^13 + y^11 + y^10 + y^7 + y^3 + y^2 110 | GF2X gen; 111 | clear(gen); 112 | SetCoeff(gen, 45); 113 | SetCoeff(gen, 43); 114 | SetCoeff(gen, 40); 115 | SetCoeff(gen, 37); 116 | SetCoeff(gen, 36); 117 | SetCoeff(gen, 35); 118 | SetCoeff(gen, 34); 119 | SetCoeff(gen, 33); 120 | SetCoeff(gen, 31); 121 | SetCoeff(gen, 30); 122 | SetCoeff(gen, 29); 123 | SetCoeff(gen, 28); 124 | SetCoeff(gen, 24); 125 | SetCoeff(gen, 21); 126 | SetCoeff(gen, 20); 127 | SetCoeff(gen, 19); 128 | SetCoeff(gen, 16); 129 | SetCoeff(gen, 14); 130 | SetCoeff(gen, 13); 131 | SetCoeff(gen, 11); 132 | SetCoeff(gen, 10); 133 | SetCoeff(gen, 7); 134 | SetCoeff(gen, 3); 135 | SetCoeff(gen, 2); 136 | 137 | GF2E::init(modulus); 138 | init_lifting_lut(conv(gen)); 139 | } break; 140 | default: 141 | throw std::runtime_error( 142 | "modulus for that specific lambda not implemented."); 143 | } 144 | } 145 | 146 | const GF2E &lift_uint8_t(uint8_t value) { return lifting_lut[value]; } 147 | 148 | GF2E GF2E_from_bytes(const std::vector &value) { 149 | // assumes value is already smaller than current modulus 150 | GF2X inner = GF2XFromBytes(value.data(), value.size()); 151 | // GF2E result(INIT_NO_ALLOC); 152 | // result.LoopHole() = inner; 153 | // return result; 154 | return conv(inner); 155 | } 156 | 157 | vec_GF2E get_first_n_field_elements(size_t n) { 158 | vec_GF2E result; 159 | result.SetLength(n); 160 | GF2X gen; 161 | SetX(gen); 162 | for (size_t i = 0; i < n; i++) { 163 | result[i] = conv(gen); 164 | gen = MulByX(gen); 165 | } 166 | return result; 167 | } 168 | std::vector precompute_lagrange_polynomials(const vec_GF2E &x_values) { 169 | size_t m = x_values.length(); 170 | std::vector precomputed_lagrange_polynomials; 171 | precomputed_lagrange_polynomials.reserve(m); 172 | 173 | GF2EX full_poly = BuildFromRoots(x_values); 174 | GF2EX lagrange_poly; 175 | GF2EX missing_term; 176 | SetX(missing_term); 177 | for (size_t k = 0; k < m; k++) { 178 | SetCoeff(missing_term, 0, -x_values[k]); 179 | lagrange_poly = full_poly / missing_term; 180 | lagrange_poly = lagrange_poly / eval(lagrange_poly, x_values[k]); 181 | precomputed_lagrange_polynomials.push_back(lagrange_poly); 182 | } 183 | 184 | return precomputed_lagrange_polynomials; 185 | } 186 | 187 | GF2EX interpolate_with_precomputation( 188 | const std::vector &precomputed_lagrange_polynomials, 189 | const vec_GF2E &y_values) { 190 | if (precomputed_lagrange_polynomials.size() != (size_t)y_values.length()) 191 | throw std::runtime_error("invalid sizes for interpolation"); 192 | 193 | GF2EX res; 194 | size_t m = y_values.length(); 195 | for (size_t k = 0; k < m; k++) { 196 | res += precomputed_lagrange_polynomials[k] * y_values[k]; 197 | } 198 | return res; 199 | } 200 | field::GF2E ntl_to_custom(const GF2E &element) { 201 | const GF2X &poly_rep = rep(element); 202 | std::vector buffer(8); 203 | BytesFromGF2X(buffer.data(), poly_rep, buffer.size()); 204 | field::GF2E a; 205 | a.from_bytes(buffer.data()); 206 | return a; 207 | } 208 | GF2E custom_to_ntl(const field::GF2E &element) { 209 | std::vector buffer(8); 210 | element.to_bytes(buffer.data()); 211 | GF2X inner = GF2XFromBytes(buffer.data(), buffer.size()); 212 | return conv(inner); 213 | } 214 | } // namespace utils 215 | -------------------------------------------------------------------------------- /tests/utils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../banquet.h" 4 | #include "../field.h" 5 | #include 6 | #include 7 | 8 | using namespace NTL; 9 | 10 | namespace utils { 11 | field::GF2E ntl_to_custom(const GF2E &element); 12 | GF2E custom_to_ntl(const field::GF2E &element); 13 | void init_extension_field(const banquet_instance_t &instance); 14 | const GF2E &lift_uint8_t(uint8_t value); 15 | GF2E GF2E_from_bytes(const std::vector &value); 16 | 17 | vec_GF2E get_first_n_field_elements(size_t n); 18 | std::vector precompute_lagrange_polynomials(const vec_GF2E &x_values); 19 | GF2EX interpolate_with_precomputation( 20 | const std::vector &precomputed_lagrange_polynomials, 21 | const vec_GF2E &y_values); 22 | 23 | } // namespace utils -------------------------------------------------------------------------------- /tools/bench.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Part of this file is is based on the optimized implementation of the Picnic 3 | * signature scheme. 4 | * See the accompanying documentation for complete details. 5 | * The code is provided under the MIT license: 6 | * 7 | * Copyright (c) 2019-2020 Sebastian Ramacher, AIT 8 | * Copyright (c) 2016-2020 Graz University of Technology 9 | * Copyright (c) 2017 Angela Promitzer 10 | 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the ""Software""), to 13 | * deal in the Software without restriction, including without limitation the 14 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 15 | * sell copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in 19 | * all copies or substantial portions of the Software. 20 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | */ 28 | 29 | #ifdef HAVE_CONFIG_H 30 | #include 31 | #endif 32 | 33 | #include "../banquet.h" 34 | #include "bench_timing.h" 35 | #include "bench_utils.h" 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | struct timing_and_size_t { 44 | uint64_t keygen, sign, serialize, deserialize, verify, size; 45 | }; 46 | 47 | static void print_timings(const std::vector &timings) { 48 | printf("keygen,sign,verify,size,serialize,deserialize\n"); 49 | for (const auto &timing : timings) { 50 | printf("%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64 51 | ",%" PRIu64 "\n", 52 | timing.keygen, timing.sign, timing.verify, timing.size, 53 | timing.serialize, timing.deserialize); 54 | } 55 | } 56 | 57 | static void bench_sign_and_verify(const bench_options_t *options) { 58 | static const uint8_t m[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 59 | 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 60 | 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}; 61 | 62 | std::vector timings(options->iter); 63 | 64 | timing_context_t ctx; 65 | if (!timing_init(&ctx)) { 66 | printf("Failed to initialize timing functionality.\n"); 67 | return; 68 | } 69 | const banquet_instance_t &instance = banquet_instance_get(options->params); 70 | printf( 71 | "Instance: N=%d, tau=%d, lambda=%d, m1=%d, m2=%d, AES-Keylen=Seclvl=%d\n", 72 | instance.num_MPC_parties, instance.num_rounds, instance.lambda, 73 | instance.m1, instance.m2, instance.aes_params.key_size); 74 | 75 | for (unsigned int i = 0; i != options->iter; ++i) { 76 | timing_and_size_t &timing = timings[i]; 77 | 78 | uint64_t start_time = timing_read(&ctx); 79 | banquet_keypair_t keypair = banquet_keygen(instance); 80 | 81 | uint64_t tmp_time = timing_read(&ctx); 82 | timing.keygen = tmp_time - start_time; 83 | start_time = timing_read(&ctx); 84 | 85 | banquet_signature_t signature = 86 | banquet_sign(instance, keypair, m, sizeof(m)); 87 | 88 | tmp_time = timing_read(&ctx); 89 | timing.sign = tmp_time - start_time; 90 | start_time = timing_read(&ctx); 91 | std::vector serialized = 92 | banquet_serialize_signature(instance, signature); 93 | tmp_time = timing_read(&ctx); 94 | timing.serialize = tmp_time - start_time; 95 | timing.size = serialized.size(); 96 | 97 | start_time = timing_read(&ctx); 98 | banquet_signature_t deserialized = 99 | banquet_deserialize_signature(instance, serialized); 100 | tmp_time = timing_read(&ctx); 101 | timing.deserialize = tmp_time - start_time; 102 | start_time = timing_read(&ctx); 103 | bool ok = 104 | banquet_verify(instance, keypair.second, deserialized, m, sizeof(m)); 105 | tmp_time = timing_read(&ctx); 106 | timing.verify = tmp_time - start_time; 107 | if (!ok) 108 | std::cerr << "failed to verify signature" << std::endl; 109 | } 110 | 111 | timing_close(&ctx); 112 | print_timings(timings); 113 | } 114 | 115 | int main(int argc, char **argv) { 116 | bench_options_t opts = {PARAMETER_SET_INVALID, 0}; 117 | int ret = parse_args(&opts, argc, argv) ? 0 : -1; 118 | 119 | if (!ret) { 120 | bench_sign_and_verify(&opts); 121 | } 122 | 123 | return ret; 124 | } 125 | -------------------------------------------------------------------------------- /tools/bench_free.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Part of this file is is based on the optimized implementation of the Picnic 3 | * signature scheme. 4 | * See the accompanying documentation for complete details. 5 | * The code is provided under the MIT license: 6 | * 7 | * Copyright (c) 2019-2020 Sebastian Ramacher, AIT 8 | * Copyright (c) 2016-2020 Graz University of Technology 9 | * Copyright (c) 2017 Angela Promitzer 10 | 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the ""Software""), to 13 | * deal in the Software without restriction, including without limitation the 14 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 15 | * sell copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in 19 | * all copies or substantial portions of the Software. 20 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | */ 28 | 29 | #ifdef HAVE_CONFIG_H 30 | #include 31 | #endif 32 | 33 | #include "../banquet.h" 34 | #include "bench_timing.h" 35 | #include "bench_utils.h" 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | struct timing_and_size_t { 44 | uint64_t keygen, sign, serialize, deserialize, verify, size; 45 | }; 46 | 47 | static void print_timings(const std::vector &timings) { 48 | printf("keygen,sign,verify,size,serialize,deserialize\n"); 49 | for (const auto &timing : timings) { 50 | printf("%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64 51 | ",%" PRIu64 "\n", 52 | timing.keygen, timing.sign, timing.verify, timing.size, 53 | timing.serialize, timing.deserialize); 54 | } 55 | } 56 | 57 | static void bench_sign_and_verify_free(const bench_options_free_t *options) { 58 | static const uint8_t m[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 59 | 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 60 | 23, 24, 25, 26, 27, 28, 29, 30, 31, 32}; 61 | 62 | std::vector timings(options->iter); 63 | 64 | timing_context_t ctx; 65 | if (!timing_init(&ctx)) { 66 | printf("Failed to initialize timing functionality.\n"); 67 | return; 68 | } 69 | banquet_instance_t instance; 70 | instance.digest_size = 2 * options->kappa; 71 | instance.seed_size = options->kappa; 72 | switch (options->kappa) { 73 | case 16: 74 | instance.aes_params = {16, 16, 1, 200}; 75 | break; 76 | case 24: 77 | instance.aes_params = {24, 16, 2, 416}; 78 | break; 79 | case 32: 80 | instance.aes_params = {32, 16, 2, 500}; 81 | break; 82 | default: 83 | printf("invalid kappa, choose 16,24,32\n"); 84 | } 85 | instance.m1 = options->m1; 86 | instance.m2 = options->m2; 87 | instance.lambda = options->lambda; 88 | instance.num_MPC_parties = options->N; 89 | instance.num_rounds = options->tau; 90 | printf( 91 | "Instance: N=%d, tau=%d, lambda=%d, m1=%d, m2=%d, AES-Keylen=Seclvl=%d\n", 92 | instance.num_MPC_parties, instance.num_rounds, instance.lambda, 93 | instance.m1, instance.m2, instance.aes_params.key_size); 94 | if (instance.m1 * instance.m2 != instance.aes_params.num_sboxes) { 95 | printf("invalid m1 and m2 for chosen seclvl\n"); 96 | return; 97 | } 98 | 99 | for (unsigned int i = 0; i != options->iter; ++i) { 100 | timing_and_size_t &timing = timings[i]; 101 | 102 | uint64_t start_time = timing_read(&ctx); 103 | banquet_keypair_t keypair = banquet_keygen(instance); 104 | 105 | uint64_t tmp_time = timing_read(&ctx); 106 | timing.keygen = tmp_time - start_time; 107 | start_time = timing_read(&ctx); 108 | 109 | banquet_signature_t signature = 110 | banquet_sign(instance, keypair, m, sizeof(m)); 111 | 112 | tmp_time = timing_read(&ctx); 113 | timing.sign = tmp_time - start_time; 114 | start_time = timing_read(&ctx); 115 | std::vector serialized = 116 | banquet_serialize_signature(instance, signature); 117 | tmp_time = timing_read(&ctx); 118 | timing.serialize = tmp_time - start_time; 119 | timing.size = serialized.size(); 120 | 121 | start_time = timing_read(&ctx); 122 | banquet_signature_t deserialized = 123 | banquet_deserialize_signature(instance, serialized); 124 | tmp_time = timing_read(&ctx); 125 | timing.deserialize = tmp_time - start_time; 126 | start_time = timing_read(&ctx); 127 | bool ok = 128 | banquet_verify(instance, keypair.second, deserialized, m, sizeof(m)); 129 | tmp_time = timing_read(&ctx); 130 | timing.verify = tmp_time - start_time; 131 | if (!ok) 132 | std::cerr << "failed to verify signature" << std::endl; 133 | } 134 | 135 | timing_close(&ctx); 136 | print_timings(timings); 137 | } 138 | 139 | int main(int argc, char **argv) { 140 | bench_options_free_t opts = {0, 0, 0, 0, 0, 0, 0}; 141 | int ret = parse_args_free(&opts, argc, argv) ? 0 : -1; 142 | 143 | if (!ret) { 144 | bench_sign_and_verify_free(&opts); 145 | } 146 | 147 | return ret; 148 | } 149 | -------------------------------------------------------------------------------- /tools/bench_timing.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the optimized implementation of the Picnic 3 | * signature scheme. 4 | * See the accompanying documentation for complete details. 5 | * The code is provided under the MIT license: 6 | * 7 | * Copyright (c) 2019-2020 Sebastian Ramacher, AIT 8 | * Copyright (c) 2016-2020 Graz University of Technology 9 | * Copyright (c) 2017 Angela Promitzer 10 | 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the ""Software""), to 13 | * deal in the Software without restriction, including without limitation the 14 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 15 | * sell copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in 19 | * all copies or substantial portions of the Software. 20 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | */ 28 | 29 | #include "bench_timing.h" 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | #if defined(__linux__) && defined(__aarch64__) 36 | #include 37 | #include 38 | 39 | /* Based on code from https://github.com/IAIK/armageddon/tree/master/libflush 40 | * 41 | * Copyright (c) 2015-2016 Moritz Lipp 42 | * 43 | * This software is provided 'as-is', without any express or implied 44 | * warranty. In no event will the authors be held liable for any damages 45 | * arising from the use of this software. 46 | * 47 | * Permission is granted to anyone to use this software for any purpose, 48 | * including commercial applications, and to alter it and redistribute it 49 | * freely, subject to the following restrictions: 50 | * 51 | * 1. The origin of this software must not be misrepresented; you must not 52 | * claim that you wrote the original software. If you use this software 53 | * in a product, an acknowledgment in the product documentation would be 54 | * appreciated but is not required. 55 | * 56 | * 2. Altered source versions must be plainly marked as such, and must not be 57 | * misrepresented as being the original software. 58 | * 59 | * 3. This notice may not be removed or altered from any source 60 | * distribution. */ 61 | 62 | #define ARMV8_PMCR_E (1 << 0) /* Enable all counters */ 63 | #define ARMV8_PMCR_P (1 << 1) /* Reset all counters */ 64 | #define ARMV8_PMCR_C (1 << 2) /* Cycle counter reset */ 65 | 66 | #define ARMV8_PMUSERENR_EN (1 << 0) /* EL0 access enable */ 67 | #define ARMV8_PMUSERENR_CR (1 << 2) /* Cycle counter read enable */ 68 | #define ARMV8_PMUSERENR_ER (1 << 3) /* Event counter read enable */ 69 | 70 | #define ARMV8_PMCNTENSET_EL0_EN \ 71 | (1 << 31) /* Performance Monitors Count Enable Set register */ 72 | 73 | static void armv8_close(timing_context_t *ctx) { 74 | (void)ctx; 75 | uint32_t value = 0; 76 | uint32_t mask = 0; 77 | 78 | /* Disable Performance Counter */ 79 | asm volatile("MRS %0, PMCR_EL0" : "=r"(value)); 80 | mask = 0; 81 | mask |= ARMV8_PMCR_E; /* Enable */ 82 | mask |= ARMV8_PMCR_C; /* Cycle counter reset */ 83 | mask |= ARMV8_PMCR_P; /* Reset all counters */ 84 | asm volatile("MSR PMCR_EL0, %0" : : "r"(value & ~mask)); 85 | 86 | /* Disable cycle counter register */ 87 | asm volatile("MRS %0, PMCNTENSET_EL0" : "=r"(value)); 88 | mask = 0; 89 | mask |= ARMV8_PMCNTENSET_EL0_EN; 90 | asm volatile("MSR PMCNTENSET_EL0, %0" : : "r"(value & ~mask)); 91 | } 92 | 93 | static uint64_t armv8_read(timing_context_t *ctx) { 94 | (void)ctx; 95 | uint64_t result = 0; 96 | asm volatile("MRS %0, PMCCNTR_EL0" : "=r"(result)); 97 | return result; 98 | } 99 | 100 | static sigjmp_buf jmpbuf; 101 | static volatile sig_atomic_t armv8_sigill = 0; 102 | 103 | static void armv8_sigill_handler(int sig) { 104 | (void)sig; 105 | armv8_sigill = 1; 106 | // Return to sigsetjump 107 | siglongjmp(jmpbuf, 1); 108 | } 109 | 110 | static bool armv8_init(timing_context_t *ctx) { 111 | if (armv8_sigill) { 112 | return false; 113 | } 114 | 115 | struct sigaction act, oldact; 116 | memset(&act, 0, sizeof(act)); 117 | act.sa_handler = &armv8_sigill_handler; 118 | if (sigaction(SIGILL, &act, &oldact) < 0) { 119 | return false; 120 | } 121 | 122 | if (sigsetjmp(jmpbuf, 1)) { 123 | // Returned from armv8_sigill_handler 124 | sigaction(SIGILL, &oldact, NULL); 125 | return false; 126 | } 127 | 128 | uint32_t value = 0; 129 | 130 | /* Enable Performance Counter */ 131 | asm volatile("MRS %0, PMCR_EL0" : "=r"(value)); 132 | value |= ARMV8_PMCR_E; /* Enable */ 133 | value |= ARMV8_PMCR_C; /* Cycle counter reset */ 134 | value |= ARMV8_PMCR_P; /* Reset all counters */ 135 | asm volatile("MSR PMCR_EL0, %0" : : "r"(value)); 136 | 137 | /* Enable cycle counter register */ 138 | asm volatile("MRS %0, PMCNTENSET_EL0" : "=r"(value)); 139 | value |= ARMV8_PMCNTENSET_EL0_EN; 140 | asm volatile("MSR PMCNTENSET_EL0, %0" : : "r"(value)); 141 | 142 | // Restore old signal handler 143 | sigaction(SIGILL, &oldact, NULL); 144 | 145 | ctx->read = armv8_read; 146 | ctx->close = armv8_close; 147 | 148 | return true; 149 | } 150 | #endif 151 | 152 | #if defined(__linux__) 153 | #include 154 | #include 155 | #include 156 | #include 157 | 158 | static void perf_close(timing_context_t *ctx) { 159 | if (ctx->data.fd != -1) { 160 | close(ctx->data.fd); 161 | ctx->data.fd = -1; 162 | } 163 | } 164 | 165 | static uint64_t perf_read(timing_context_t *ctx) { 166 | uint64_t tmp_time; 167 | if (read(ctx->data.fd, &tmp_time, sizeof(tmp_time)) != sizeof(tmp_time)) { 168 | return UINT64_MAX; 169 | } 170 | 171 | return tmp_time; 172 | } 173 | 174 | static int perf_event_open(struct perf_event_attr *event, pid_t pid, int cpu, 175 | int gfd, unsigned long flags) { 176 | const long fd = syscall(__NR_perf_event_open, event, pid, cpu, gfd, flags); 177 | if (fd > INT_MAX) { 178 | /* too large to handle, but should never happen */ 179 | return -1; 180 | } 181 | 182 | return fd; 183 | } 184 | 185 | static bool perf_init(timing_context_t *ctx) { 186 | struct perf_event_attr pea; 187 | memset(&pea, 0, sizeof(pea)); 188 | 189 | pea.size = sizeof(pea); 190 | pea.type = PERF_TYPE_HARDWARE; 191 | pea.config = PERF_COUNT_HW_CPU_CYCLES; 192 | pea.disabled = 0; 193 | pea.exclude_kernel = 1; 194 | pea.exclude_hv = 1; 195 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0) 196 | pea.exclude_callchain_kernel = 1; 197 | pea.exclude_callchain_user = 1; 198 | #endif 199 | 200 | const int fd = perf_event_open(&pea, 0, -1, -1, 0); 201 | if (fd == -1) { 202 | return false; 203 | } 204 | 205 | ctx->read = perf_read; 206 | ctx->close = perf_close; 207 | ctx->data.fd = fd; 208 | return true; 209 | } 210 | #endif 211 | 212 | static void clock_close(timing_context_t *ctx) { (void)ctx; } 213 | 214 | static uint64_t clock_read(timing_context_t *ctx) { 215 | (void)ctx; 216 | return clock() * (1000000 / CLOCKS_PER_SEC); 217 | } 218 | 219 | static bool clock_init(timing_context_t *ctx) { 220 | ctx->read = clock_read; 221 | ctx->close = clock_close; 222 | return true; 223 | } 224 | 225 | bool timing_init(timing_context_t *ctx) { 226 | #if defined(__linux__) && defined(__aarch64__) 227 | if (armv8_init(ctx)) { 228 | return true; 229 | } 230 | #endif 231 | #if defined(__linux__) 232 | if (perf_init(ctx)) { 233 | return true; 234 | } 235 | #endif 236 | return clock_init(ctx); 237 | } 238 | -------------------------------------------------------------------------------- /tools/bench_timing.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the optimized implementation of the Picnic 3 | * signature scheme. 4 | * See the accompanying documentation for complete details. 5 | * The code is provided under the MIT license: 6 | * 7 | * Copyright (c) 2019-2020 Sebastian Ramacher, AIT 8 | * Copyright (c) 2016-2020 Graz University of Technology 9 | * Copyright (c) 2017 Angela Promitzer 10 | 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the ""Software""), to 13 | * deal in the Software without restriction, including without limitation the 14 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 15 | * sell copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in 19 | * all copies or substantial portions of the Software. 20 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | */ 28 | 29 | #ifndef BENCH_TIMING_H 30 | #define BENCH_TIMING_H 31 | 32 | #include 33 | #include 34 | 35 | typedef struct timing_context_s timing_context_t; 36 | 37 | typedef uint64_t (*timing_read_f)(timing_context_t *ctx); 38 | typedef void (*timing_close_f)(timing_context_t *ctx); 39 | 40 | struct timing_context_s { 41 | timing_read_f read; 42 | timing_close_f close; 43 | 44 | union { 45 | int fd; 46 | } data; 47 | }; 48 | 49 | bool timing_init(timing_context_t *ctx); 50 | 51 | static inline uint64_t timing_read(timing_context_t *ctx) { 52 | return ctx->read(ctx); 53 | } 54 | 55 | static inline void timing_close(timing_context_t *ctx) { ctx->close(ctx); } 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /tools/bench_utils.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Part of this file is is based on the optimized implementation of the Picnic 3 | * signature scheme. 4 | * See the accompanying documentation for complete details. 5 | * The code is provided under the MIT license: 6 | * 7 | * Copyright (c) 2019-2020 Sebastian Ramacher, AIT 8 | * Copyright (c) 2016-2020 Graz University of Technology 9 | * Copyright (c) 2017 Angela Promitzer 10 | 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the ""Software""), to 13 | * deal in the Software without restriction, including without limitation the 14 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 15 | * sell copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in 19 | * all copies or substantial portions of the Software. 20 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | */ 28 | 29 | #include "bench_utils.h" 30 | 31 | #include 32 | #include 33 | #if !defined(_MSC_VER) 34 | #include 35 | #endif 36 | #include 37 | #include 38 | 39 | static bool parse_long(long *value, const char *arg) { 40 | errno = 0; 41 | const long v = strtol(arg, NULL, 10); 42 | 43 | if ((errno == ERANGE && (v == LONG_MAX || v == LONG_MIN)) || 44 | (errno != 0 && v == 0)) { 45 | return false; 46 | } 47 | *value = v; 48 | 49 | return true; 50 | } 51 | 52 | static bool parse_uint32_t(uint32_t *value, const char *arg) { 53 | long tmp = 0; 54 | if (!parse_long(&tmp, arg)) { 55 | return false; 56 | } 57 | 58 | if (tmp < 0 || (unsigned long)tmp > UINT32_MAX) { 59 | return false; 60 | } 61 | 62 | *value = tmp; 63 | return true; 64 | } 65 | 66 | static void print_usage(const char *arg0) { 67 | #if defined(_MSC_VER) 68 | printf("usage: %s iterations instance\n", arg0); 69 | #else 70 | printf("usage: %s [-i iterations] instance\n", arg0); 71 | #endif 72 | } 73 | 74 | static void print_usage_free(const char *arg0) { 75 | #if defined(_MSC_VER) 76 | printf("usage: %s iterations instance\n", arg0); 77 | #else 78 | printf("usage: %s [-i iterations] kappa N tau m1 m2 lambda\n", arg0); 79 | #endif 80 | } 81 | 82 | bool parse_args(bench_options_t *options, int argc, char **argv) { 83 | if (argc <= 1) { 84 | print_usage(argv[0]); 85 | return false; 86 | } 87 | 88 | options->params = PARAMETER_SET_INVALID; 89 | options->iter = 10; 90 | 91 | #if !defined(_MSC_VER) 92 | static const struct option long_options[] = { 93 | {"iter", required_argument, NULL, 'i'}, {0, 0, 0, 0}}; 94 | 95 | int c = -1; 96 | int option_index = 0; 97 | 98 | while ((c = getopt_long(argc, argv, "i:l:", long_options, &option_index)) != 99 | -1) { 100 | switch (c) { 101 | case 'i': 102 | if (!parse_uint32_t(&options->iter, optarg)) { 103 | printf("Failed to parse argument as positive base-10 number!\n"); 104 | return false; 105 | } 106 | break; 107 | 108 | case '?': 109 | default: 110 | printf("usage: %s [-i iter] param\n", argv[0]); 111 | return false; 112 | } 113 | } 114 | 115 | if (optind == argc - 1) { 116 | uint32_t p = PARAMETER_SET_INVALID; 117 | if (!parse_uint32_t(&p, argv[optind])) { 118 | printf("Failed to parse argument as positive base-10 number!\n"); 119 | return false; 120 | } 121 | 122 | if (p <= PARAMETER_SET_INVALID || p >= PARAMETER_SET_MAX_INDEX) { 123 | printf("Invalid parameter set selected!\n"); 124 | return false; 125 | } 126 | options->params = static_cast(p); 127 | } else { 128 | print_usage(argv[0]); 129 | return false; 130 | } 131 | #else 132 | if (argc != 3) { 133 | print_usage(argv[0]); 134 | return false; 135 | } 136 | 137 | uint32_t p = PARAMETER_SET_INVALID; 138 | if (!parse_uint32_t(&options->iter, argv[1]) || 139 | !parse_uint32_t(&p, argv[2])) { 140 | printf("Failed to parse argument as positive base-10 number!\n"); 141 | return false; 142 | } 143 | 144 | if (p <= PARAMETER_SET_INVALID || p >= PARAMETER_SET_MAX_INDEX) { 145 | printf("Invalid parameter set selected!\n"); 146 | return false; 147 | } 148 | options->params = p; 149 | #endif 150 | 151 | return true; 152 | } 153 | 154 | bool parse_args_free(bench_options_free_t *options, int argc, char **argv) { 155 | if (argc <= 6) { 156 | print_usage_free(argv[0]); 157 | return false; 158 | } 159 | 160 | options->kappa = 0; 161 | options->tau = 0; 162 | options->N = 0; 163 | options->m1 = 0; 164 | options->m2 = 0; 165 | options->lambda = 0; 166 | options->iter = 10; 167 | 168 | static const struct option long_options[] = { 169 | {"iter", required_argument, NULL, 'i'}, {0, 0, 0, 0}}; 170 | 171 | int c = -1; 172 | int option_index = 0; 173 | 174 | while ((c = getopt_long(argc, argv, "i:l:", long_options, &option_index)) != 175 | -1) { 176 | switch (c) { 177 | case 'i': 178 | if (!parse_uint32_t(&options->iter, optarg)) { 179 | printf("Failed to parse argument as positive base-10 number!\n"); 180 | return false; 181 | } 182 | break; 183 | 184 | case '?': 185 | default: 186 | print_usage_free(argv[0]); 187 | return false; 188 | } 189 | } 190 | 191 | uint32_t p = 0; 192 | if (!parse_uint32_t(&p, argv[optind++])) { 193 | printf("Failed to parse argument as positive base-10 number!\n"); 194 | return false; 195 | } 196 | options->kappa = p; 197 | 198 | if (!parse_uint32_t(&p, argv[optind++])) { 199 | printf("Failed to parse argument as positive base-10 number!\n"); 200 | return false; 201 | } 202 | options->N = p; 203 | 204 | if (!parse_uint32_t(&p, argv[optind++])) { 205 | printf("Failed to parse argument as positive base-10 number!\n"); 206 | return false; 207 | } 208 | options->tau = p; 209 | 210 | if (!parse_uint32_t(&p, argv[optind++])) { 211 | printf("Failed to parse argument as positive base-10 number!\n"); 212 | return false; 213 | } 214 | options->m1 = p; 215 | 216 | if (!parse_uint32_t(&p, argv[optind++])) { 217 | printf("Failed to parse argument as positive base-10 number!\n"); 218 | return false; 219 | } 220 | options->m2 = p; 221 | 222 | if (!parse_uint32_t(&p, argv[optind++])) { 223 | printf("Failed to parse argument as positive base-10 number!\n"); 224 | return false; 225 | } 226 | options->lambda = p; 227 | return true; 228 | } 229 | -------------------------------------------------------------------------------- /tools/bench_utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Part of this file is is based on the optimized implementation of the Picnic 3 | * signature scheme. 4 | * See the accompanying documentation for complete details. 5 | * The code is provided under the MIT license: 6 | * 7 | * Copyright (c) 2019-2020 Sebastian Ramacher, AIT 8 | * Copyright (c) 2016-2020 Graz University of Technology 9 | * Copyright (c) 2017 Angela Promitzer 10 | 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the ""Software""), to 13 | * deal in the Software without restriction, including without limitation the 14 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 15 | * sell copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in 19 | * all copies or substantial portions of the Software. 20 | * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | * SOFTWARE. 27 | */ 28 | 29 | #ifndef BENCH_UTILS_H 30 | #define BENCH_UTILS_H 31 | 32 | #include 33 | #include 34 | 35 | #include "../banquet_instances.h" 36 | 37 | typedef struct { 38 | banquet_params_t params; 39 | uint32_t iter; 40 | } bench_options_t; 41 | 42 | typedef struct { 43 | uint32_t iter; 44 | uint32_t kappa; 45 | uint32_t m1; 46 | uint32_t m2; 47 | uint32_t tau; 48 | uint32_t N; 49 | uint32_t lambda; 50 | } bench_options_free_t; 51 | 52 | bool parse_args(bench_options_t *options, int argc, char **argv); 53 | 54 | bool parse_args_free(bench_options_free_t *options, int argc, char **argv); 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /tools/morphism.sage: -------------------------------------------------------------------------------- 1 | 2 | R. = GF(2)[] 3 | K. = GF(2^8, modulus= X^8 +X^4+X^3+X+1) 4 | 5 | 6 | F = GF(2^16, 'y', modulus = X^16 + X^5 + X^3 + X + 1) 7 | #F = GF(2^32, 'y', modulus = X^32 + X^7 + X^3 + X^2 + 1) 8 | #F = GF(2^40, 'y', modulus = X^40 + X^5 + X^4 + X^3 + 1) 9 | #F = GF(2^48, 'y', modulus = X^48 + X^5 + X^3 + X^2 + 1) 10 | 11 | print(F, F.modulus()) 12 | print(F.gens()) 13 | H = Hom(K, F) 14 | morph = H.list()[0] 15 | g = morph.im_gens()[0] 16 | print(morph) 17 | -------------------------------------------------------------------------------- /tools/parse_bench.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import sys 3 | 4 | SCALING_FACTOR = 3600.0 * 1000 5 | SCALING_FACTOR = 1000 6 | 7 | with open(sys.argv[1], "r") as f: 8 | content = f.read() 9 | 10 | testruns = content.split("Instance: ") 11 | if len(testruns) > 1: 12 | testruns.pop(0) 13 | 14 | for test in testruns: 15 | lines = test.splitlines() 16 | # first line is instance: 17 | print(lines[0]) 18 | lines.pop(0) 19 | # second line is header: 20 | print(lines[0]) 21 | lines.pop(0) 22 | 23 | count = 0 24 | keygen, sign, ver, size, ser, deser = 0, 0, 0, 0, 0, 0 25 | 26 | for line in lines: 27 | if len(line.strip()) == 0: 28 | continue 29 | vals = line.strip().split(",") 30 | keygen += int(vals[0]) 31 | sign += int(vals[1]) 32 | ver += int(vals[2]) 33 | size += int(vals[3]) 34 | ser += int(vals[4]) 35 | deser += int(vals[5]) 36 | count += 1 37 | 38 | keygen = (keygen / SCALING_FACTOR) / count 39 | sign = (sign / SCALING_FACTOR) / count 40 | ver = (ver / SCALING_FACTOR) / count 41 | size = float(size) / 1024 / count 42 | ser = (ser / SCALING_FACTOR) / count 43 | deser = (deser / SCALING_FACTOR) / count 44 | print("{:.2f},{:.2f},{:.2f},{:.3f},{:.2f},{:.2f}".format( 45 | keygen, sign, ver, size, ser, deser)) 46 | print("-"*80) 47 | -------------------------------------------------------------------------------- /tree.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "gsl-lite.hpp" 10 | #include "types.h" 11 | 12 | class SeedTree { 13 | public: 14 | private: 15 | // data, layed out continously in memory in blocks of digest_size size, root 16 | // at [0], its two children at [1], [2], in general node at [n], children at 17 | // [2*n + 1], [2*n + 2] 18 | std::vector _data; 19 | std::vector _node_exists; 20 | std::vector _node_has_value; 21 | size_t _seed_size; 22 | size_t _num_leaves; 23 | size_t _num_total_nodes; 24 | 25 | inline bool node_exists(size_t idx) { 26 | if (idx >= _num_total_nodes) 27 | return false; 28 | 29 | return _node_exists[idx]; 30 | }; 31 | inline bool node_has_value(size_t idx) { 32 | if (idx >= _num_total_nodes) 33 | return false; 34 | 35 | return _node_has_value[idx]; 36 | }; 37 | 38 | public: 39 | // construct from given seed, expand into num_leaves small seeds 40 | SeedTree(const std::vector &seed, const size_t num_leaves, 41 | const banquet_salt_t &salt, const size_t rep_idx); 42 | // re-construct from reveallist, expand all known values 43 | SeedTree(const reveal_list_t &reveallist, const size_t num_leaves, 44 | const banquet_salt_t &salt, const size_t rep_idx); 45 | ~SeedTree() = default; 46 | 47 | reveal_list_t reveal_all_but(size_t leaf_idx); 48 | std::optional> get_leaf(size_t leaf_idx); 49 | }; 50 | -------------------------------------------------------------------------------- /types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "gsl-lite.hpp" 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "field.h" 10 | 11 | /* Prefix values for domain separation */ 12 | constexpr uint8_t HASH_PREFIX_0 = 0; 13 | constexpr uint8_t HASH_PREFIX_1 = 1; 14 | constexpr uint8_t HASH_PREFIX_2 = 2; 15 | constexpr uint8_t HASH_PREFIX_3 = 3; 16 | constexpr uint8_t HASH_PREFIX_4 = 4; 17 | constexpr uint8_t HASH_PREFIX_5 = 5; 18 | 19 | constexpr size_t SALT_SIZE = 32; 20 | typedef std::array banquet_salt_t; 21 | 22 | typedef std::pair>, size_t> reveal_list_t; 23 | 24 | typedef std::array aes_block_t; 25 | 26 | typedef std::pair, std::vector> banquet_keypair_t; 27 | 28 | struct banquet_repetition_proof_t { 29 | reveal_list_t reveallist; 30 | std::vector C_e; 31 | std::vector sk_delta; 32 | std::vector t_delta; 33 | std::vector P_delta; 34 | field::GF2E P_at_R; 35 | std::vector S_j_at_R; 36 | std::vector T_j_at_R; 37 | }; 38 | 39 | struct banquet_signature_t { 40 | banquet_salt_t salt; 41 | std::vector h_1; 42 | std::vector h_3; 43 | std::vector proofs; 44 | }; 45 | 46 | template class RepContainer { 47 | std::vector _data; 48 | size_t _num_repetitions; 49 | size_t _num_parties; 50 | size_t _object_size; 51 | 52 | public: 53 | RepContainer(size_t num_repetitions, size_t num_parties, size_t object_size) 54 | : _data(num_repetitions * num_parties * object_size), 55 | _num_repetitions(num_repetitions), _num_parties(num_parties), 56 | _object_size(object_size) {} 57 | 58 | inline gsl::span get(size_t repetition, size_t party) { 59 | size_t offset = 60 | (repetition * _num_parties * _object_size) + (party * _object_size); 61 | return gsl::span(_data.data() + offset, _object_size); 62 | } 63 | inline gsl::span get(size_t repetition, size_t party) const { 64 | size_t offset = 65 | (repetition * _num_parties * _object_size) + (party * _object_size); 66 | return gsl::span(_data.data() + offset, _object_size); 67 | } 68 | 69 | std::vector> get_repetition(size_t repetition) { 70 | std::vector> ret; 71 | ret.reserve(_num_parties); 72 | size_t offset = (repetition * _num_parties * _object_size); 73 | for (size_t i = 0; i < _num_parties; i++) 74 | ret.emplace_back(_data.data() + offset + i * _object_size, _object_size); 75 | return ret; 76 | } 77 | }; 78 | 79 | typedef RepContainer RepByteContainer; --------------------------------------------------------------------------------