mirror of
https://github.com/open-quantum-safe/liboqs.git
synced 2025-10-07 00:10:54 -04:00
Remove picnic (#134)
* Remove picnic * Fix the compilation on macOS * Remove libm4ri-dev * make prettyprint inconsistency, travis typo, travis add OPENSSL_DIR * Missed one comment, should work everywhere now
This commit is contained in:
parent
2fecc3ba37
commit
d08b510b8f
@ -26,7 +26,7 @@ fi
|
||||
|
||||
if [[ ${ENABLE_SIDH_IQC_REF} == 1 ]];then
|
||||
enable_disable_str+=" --enable-kex-sidh-iqc-ref"
|
||||
if [[ ! -z "${GNP_DIR// }" ]];then
|
||||
if [[ ! -z "${GMP_DIR// }" ]];then
|
||||
enable_disable_str+=" --with-gmp-dir=${GMP_DIR}"
|
||||
fi
|
||||
fi
|
||||
|
15
.travis.yml
15
.travis.yml
@ -14,7 +14,6 @@ matrix:
|
||||
packages:
|
||||
- gcc-4.8
|
||||
- libgmp-dev
|
||||
- libm4ri-dev
|
||||
before_install:
|
||||
- sh .travis/install-clang-format-linux.sh
|
||||
- os: linux
|
||||
@ -26,7 +25,6 @@ matrix:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- gcc-4.9
|
||||
- libm4ri-dev
|
||||
before_install:
|
||||
- sh .travis/install-clang-format-linux.sh
|
||||
- os: linux
|
||||
@ -38,7 +36,6 @@ matrix:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- gcc-5
|
||||
- libm4ri-dev
|
||||
before_install:
|
||||
- sh .travis/install-clang-format-linux.sh
|
||||
- os: linux
|
||||
@ -51,14 +48,20 @@ matrix:
|
||||
packages:
|
||||
- gcc-6
|
||||
- libssl-dev
|
||||
- libm4ri-dev
|
||||
before_install:
|
||||
- sh .travis/install-clang-format-linux.sh
|
||||
- os: osx
|
||||
compiler: clang
|
||||
env: CC_OQS=clang AES_NI=0 USE_OPENSSL=1 ENABLE_CODE_MCBITS=1 ENABLE_NTRU=1 ENABLE_SIDH_IQC_REF=1
|
||||
env:
|
||||
- CC_OQS=clang
|
||||
- AES_NI=0
|
||||
- USE_OPENSSL=1
|
||||
- OPENSSL_DIR=/usr/local/opt/openssl
|
||||
- ENABLE_CODE_MCBITS=1
|
||||
- ENABLE_NTRU=1
|
||||
- ENABLE_SIDH_IQC_REF=1
|
||||
before_install:
|
||||
- brew install clang-format openssl libsodium libm4ri-dev
|
||||
- brew install clang-format libsodium
|
||||
|
||||
script:
|
||||
- CC=$CC_OQS ./.travis-tests.sh
|
||||
|
19
Makefile.am
19
Makefile.am
@ -20,7 +20,6 @@ liboqs_la_LIBADD += src/crypto/rand_urandom_chacha20/librandchacha20.la
|
||||
liboqs_la_LIBADD += src/kex_rlwe_bcns15/libbcns15.la src/kex_rlwe_newhope/libnewhope.la
|
||||
liboqs_la_LIBADD += src/kex_lwe_frodo/libfrodo.la src/kex_rlwe_msrln16/libmsrln16.la
|
||||
liboqs_la_LIBADD += src/kex_sidh_cln16/libcln16.la
|
||||
liboqs_la_LIBADD += src/sig_picnic_msr/libpicnicmsr.la
|
||||
|
||||
if USE_MCBITS
|
||||
liboqs_la_LIBADD += src/kex_code_mcbits/libmcbits.la
|
||||
@ -34,7 +33,7 @@ if USE_SIDH_IQC
|
||||
liboqs_la_LIBADD += src/kex_sidh_iqc_ref/libsidhiqc.la
|
||||
endif
|
||||
|
||||
noinst_bin_PROGRAMS = test_rand test_kex test_aes pp_Matrices benchmark_lowmc
|
||||
noinst_bin_PROGRAMS = test_rand test_kex test_aes
|
||||
noinst_bindir=$(prefix)/tests
|
||||
test_kex_LDADD = liboqs.la -lm
|
||||
test_kex_SOURCES = src/kex/test_kex.c
|
||||
@ -73,24 +72,12 @@ test_rand_CPPFLAGS += -maes -msse2
|
||||
endif
|
||||
endif
|
||||
|
||||
pp_Matrices_LDADD = liboqs.la -lm4ri -lcrypto
|
||||
pp_Matrices_SOURCES = src/sig_picnic_msr/preprocessMatrices.c
|
||||
pp_Matrices_CPPFLAGS = -Isrc/sig_picnic_msr/ -I/usr/include/m4ri/
|
||||
pp_Matrices_CPPFLAGS += $(AM_CPPFLAGS)
|
||||
|
||||
benchmark_lowmc_LDADD = liboqs.la -lcrypto -lm4ri
|
||||
benchmark_lowmc_SOURCES = src/sig_picnic_msr/benchmark_lowmc.c src/sig_picnic_msr/test_util.c
|
||||
benchmark_lowmc_CPPFLAGS = -Isrc/sig_picnic_msr/
|
||||
benchmark_lowmc_CPPFLAGS += $(AM_CPPFLAGS)
|
||||
|
||||
|
||||
test: clean-tests
|
||||
make
|
||||
./test_kex
|
||||
./test_rand
|
||||
./test_aes
|
||||
mkdir ./precomputed_data;./pp_Matrices
|
||||
./benchmark_lowmc
|
||||
|
||||
ntru:
|
||||
|
||||
@ -123,14 +110,12 @@ endif
|
||||
clean-local:
|
||||
rm -f liboqs.a
|
||||
rm -rf include
|
||||
rm -rf precomputed_data
|
||||
if USE_SIDH_IQC
|
||||
rm -f sample_params
|
||||
endif
|
||||
|
||||
clean-tests:
|
||||
rm -f test_kex test_rand test_aes pp_Matrices benchmark_lowmc
|
||||
rm -rf precomputed_data
|
||||
rm -f test_kex test_rand test_aes
|
||||
|
||||
prettyprint:
|
||||
find src -name '*.c' -o -name '*.h' | xargs $(CLANGFORMAT) -style=file -i
|
||||
|
13
configure.ac
13
configure.ac
@ -77,11 +77,6 @@ ARG_ENABL_SET([kex-sidh-iqc-ref], [enable KEX-SIDH-IQC-REF.])
|
||||
AM_CONDITIONAL([kex_sidh_iqc_ref], [test "x$kex_sidh_iqc_ref" = xtrue])
|
||||
AM_CONDITIONAL([USE_SIDH_IQC], [test "x$kex_sidh_iqc_ref" = xtrue])
|
||||
|
||||
ARG_ENABL_SET([avx-sig-picnic-msr], [enable AVX-SIG-PICNIC-MSR])
|
||||
AM_CONDITIONAL([avx_sig_picnic_msr], [test "x$avx_sig_picnic_msr" = xtrue])
|
||||
AM_CONDITIONAL([USE_AVX_PICNIC_MSR], [test "x$avx_sig_picnic_msr" = xtrue])
|
||||
|
||||
|
||||
AM_CPPFLAGS="-g -std=gnu11 -Wno-unused-function -Werror -Wpedantic -Wall -Wextra -DCONSTANT_TIME"
|
||||
AC_CANONICAL_HOST
|
||||
# Check for which host we are on and setup a few things
|
||||
@ -131,7 +126,6 @@ SRCDIR=${SRCDIR}" src/kex_rlwe_newhope"
|
||||
SRCDIR=${SRCDIR}" src/kex_lwe_frodo"
|
||||
SRCDIR=${SRCDIR}" src/kex_rlwe_msrln16"
|
||||
SRCDIR=${SRCDIR}" src/kex_sidh_cln16"
|
||||
SRCDIR=${SRCDIR}" src/sig_picnic_msr"
|
||||
|
||||
if test x"$kex_ntru" = x"true"; then
|
||||
AM_CPPFLAGS=${AM_CPPFLAGS}" -DENABLE_NTRU"
|
||||
@ -156,10 +150,6 @@ if test x"$kex_sidh_iqc_ref" = x"true"; then
|
||||
SRCDIR=${SRCDIR}" src/kex_sidh_iqc_ref"
|
||||
fi
|
||||
|
||||
if test x"avx_sig_picnic_msr" = x"true"; then
|
||||
AM_CPPFLAGS=${AM_CPPFLAGS}" -DWITH_AVX -mavx2"
|
||||
fi
|
||||
|
||||
|
||||
AC_SUBST(AM_CPPFLAGS)
|
||||
AC_SUBST(SRCDIR)
|
||||
@ -186,7 +176,6 @@ AC_CONFIG_FILES([Makefile
|
||||
src/kex_code_mcbits/Makefile
|
||||
src/kex_ntru/Makefile
|
||||
src/kex_sidh_iqc_ref/Makefile
|
||||
src/kex_lwe_frodo/Makefile
|
||||
src/sig_picnic_msr/Makefile])
|
||||
src/kex_lwe_frodo/Makefile])
|
||||
|
||||
AC_OUTPUT
|
||||
|
@ -16,9 +16,10 @@ extern const uint64_t p751[NWORDS_FIELD];
|
||||
extern const uint64_t p751p1[NWORDS_FIELD];
|
||||
extern const uint64_t p751x2[NWORDS_FIELD];
|
||||
|
||||
__inline void oqs_sidh_cln16_fpadd751(const digit_t *a, const digit_t *b, digit_t *c) { // Modular addition, c = a+b mod p751.
|
||||
// Inputs: a, b in [0, 2*p751-1]
|
||||
// Output: c in [0, 2*p751-1]
|
||||
// Modular addition, c = a+b mod p751.
|
||||
// Inputs: a, b in [0, 2*p751-1]
|
||||
// Output: c in [0, 2*p751-1]
|
||||
__inline void oqs_sidh_cln16_fpadd751(const digit_t *a, const digit_t *b, digit_t *c) {
|
||||
|
||||
#if (OS_TARGET == OS_WIN)
|
||||
unsigned int i, carry = 0;
|
||||
@ -46,9 +47,10 @@ __inline void oqs_sidh_cln16_fpadd751(const digit_t *a, const digit_t *b, digit_
|
||||
#endif
|
||||
}
|
||||
|
||||
__inline void oqs_sidh_cln16_fpsub751(const digit_t *a, const digit_t *b, digit_t *c) { // Modular subtraction, c = a-b mod p751.
|
||||
// Inputs: a, b in [0, 2*p751-1]
|
||||
// Output: c in [0, 2*p751-1]
|
||||
// Modular subtraction, c = a-b mod p751.
|
||||
// Inputs: a, b in [0, 2*p751-1]
|
||||
// Output: c in [0, 2*p751-1]
|
||||
__inline void oqs_sidh_cln16_fpsub751(const digit_t *a, const digit_t *b, digit_t *c) {
|
||||
|
||||
#if (OS_TARGET == OS_WIN)
|
||||
unsigned int i, borrow = 0;
|
||||
@ -71,8 +73,9 @@ __inline void oqs_sidh_cln16_fpsub751(const digit_t *a, const digit_t *b, digit_
|
||||
#endif
|
||||
}
|
||||
|
||||
__inline void oqs_sidh_cln16_fpneg751(digit_t *a) { // Modular negation, a = -a mod p751.
|
||||
// Input/output: a in [0, 2*p751-1]
|
||||
// Modular negation, a = -a mod p751.
|
||||
// Input/output: a in [0, 2*p751-1]
|
||||
__inline void oqs_sidh_cln16_fpneg751(digit_t *a) {
|
||||
unsigned int i, borrow = 0;
|
||||
|
||||
for (i = 0; i < NWORDS_FIELD; i++) {
|
||||
@ -80,9 +83,10 @@ __inline void oqs_sidh_cln16_fpneg751(digit_t *a) { // Modular negation, a = -a
|
||||
}
|
||||
}
|
||||
|
||||
void oqs_sidh_cln16_fpdiv2_751(const digit_t *a, digit_t *c) { // Modular division by two, c = a/2 mod p751.
|
||||
// Input : a in [0, 2*p751-1]
|
||||
// Output: c in [0, 2*p751-1]
|
||||
// Modular division by two, c = a/2 mod p751.
|
||||
// Input : a in [0, 2*p751-1]
|
||||
// Output: c in [0, 2*p751-1]
|
||||
void oqs_sidh_cln16_fpdiv2_751(const digit_t *a, digit_t *c) {
|
||||
unsigned int i, carry = 0;
|
||||
digit_t mask;
|
||||
|
||||
@ -94,7 +98,8 @@ void oqs_sidh_cln16_fpdiv2_751(const digit_t *a, digit_t *c) { // Modular divisi
|
||||
oqs_sidh_cln16_mp_shiftr1(c, NWORDS_FIELD);
|
||||
}
|
||||
|
||||
void oqs_sidh_cln16_fpcorrection751(digit_t *a) { // Modular correction to reduce field element a in [0, 2*p751-1] to [0, p751-1].
|
||||
// Modular correction to reduce field element a in [0, 2*p751-1] to [0, p751-1].
|
||||
void oqs_sidh_cln16_fpcorrection751(digit_t *a) {
|
||||
unsigned int i, borrow = 0;
|
||||
digit_t mask;
|
||||
|
||||
@ -109,7 +114,8 @@ void oqs_sidh_cln16_fpcorrection751(digit_t *a) { // Modular correction to reduc
|
||||
}
|
||||
}
|
||||
|
||||
void oqs_sidh_cln16_mp_mul(const digit_t *a, const digit_t *b, digit_t *c, const unsigned int nwords) { // Multiprecision multiply, c = a*b, where lng(a) = lng(b) = nwords.
|
||||
// Multiprecision multiply, c = a*b, where lng(a) = lng(b) = nwords.
|
||||
void oqs_sidh_cln16_mp_mul(const digit_t *a, const digit_t *b, digit_t *c, const unsigned int nwords) {
|
||||
|
||||
UNREFERENCED_PARAMETER(nwords);
|
||||
|
||||
@ -524,11 +530,11 @@ void oqs_sidh_cln16_mp_mul(const digit_t *a, const digit_t *b, digit_t *c, const
|
||||
#endif
|
||||
}
|
||||
|
||||
void oqs_sidh_cln16_rdc_mont(const oqs_sidh_cln16_dfelm_t ma, oqs_sidh_cln16_felm_t mc) { // Efficient Montgomery reduction using comba and exploiting the special form of the prime p751.
|
||||
// mc = ma*R^-1 mod p751x2, where R = 2^768.
|
||||
// If ma < 2^768*p751, the output mc is in the range [0, 2*p751-1].
|
||||
// ma is assumed to be in Montgomery representation.
|
||||
|
||||
// Efficient Montgomery reduction using comba and exploiting the special form of the prime p751.
|
||||
// mc = ma*R^-1 mod p751x2, where R = 2^768.
|
||||
// If ma < 2^768*p751, the output mc is in the range [0, 2*p751-1].
|
||||
// ma is assumed to be in Montgomery representation.
|
||||
void oqs_sidh_cln16_rdc_mont(const oqs_sidh_cln16_dfelm_t ma, oqs_sidh_cln16_felm_t mc) {
|
||||
#if (OS_TARGET == OS_WIN)
|
||||
unsigned int carry;
|
||||
digit_t t = 0;
|
||||
|
@ -2,7 +2,7 @@ AUTOMAKE_OPTIONS = foreign
|
||||
noinst_LTLIBRARIES = libcln16.la
|
||||
|
||||
|
||||
libcln16_la_SOURCES = ec_isogeny.c fpx.c kex_sidh_cln16.c SIDH.c sidh_kex.c SIDH_setup.c AMD64/fp_x64.c AMD64/fp_x64_asm.S
|
||||
libcln16_la_SOURCES = ec_isogeny.c fpx.c kex_sidh_cln16.c SIDH.c sidh_kex.c SIDH_setup.c AMD64/fp_x64.c AMD64/fp_x64_asm.S generic/fp_generic.c
|
||||
libcln16_la_CPPFLAGS = -I../../include -I.-fPIC -w
|
||||
libcln16_la_CPPFLAGS += $(AM_CPPFLAGS)
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
*********************************************************************************************/
|
||||
|
||||
#include "SIDH_internal.h"
|
||||
#include <malloc.h>
|
||||
// #include <malloc.h>
|
||||
|
||||
SIDH_CRYPTO_STATUS oqs_sidh_cln16_curve_initialize(PCurveIsogenyStruct pCurveIsogeny, PCurveIsogenyStaticData pCurveIsogenyData) { // Initialize curve isogeny structure pCurveIsogeny with static data extracted from pCurveIsogenyData.
|
||||
// This needs to be called after allocating memory for "pCurveIsogeny" using SIDH_curve_allocate().
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,81 +0,0 @@
|
||||
/*! @file LowMC.h
|
||||
* @brief Header file for LowMC.c, the file where all the LowMC
|
||||
* proof-of-knowledge operations are done.
|
||||
*
|
||||
* This file is part of the reference implementation of the Picnic and Fish
|
||||
* signature schemes, described in the paper:
|
||||
*
|
||||
* Post-Quantum Zero-Knowledge and Signatures from Symmetric-Key Primitives
|
||||
* Melissa Chase and David Derler and Steven Goldfeder and Claudio Orlandi and
|
||||
* Sebastian Ramacher and Christian Rechberger and Daniel Slamanig and Greg
|
||||
* Zaverucha
|
||||
* Cryptology ePrint Archive: Report 2017/279
|
||||
* http://eprint.iacr.org/2017/279
|
||||
*
|
||||
* The code is provided under the MIT license, see LICENSE for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
#ifndef LOWMC_H
|
||||
#define LOWMC_H
|
||||
|
||||
#include <openssl/sha.h>
|
||||
#include "LowMCConstants.h"
|
||||
|
||||
#define PRG_SEED_LENGTH 32
|
||||
|
||||
#define NUM_ZKB_ROUNDS 438
|
||||
|
||||
typedef struct proof_t {
|
||||
uint8_t seed1[PRG_SEED_LENGTH];
|
||||
uint8_t seed2[PRG_SEED_LENGTH];
|
||||
uint32_t *inputShare; // Input share of the party which does not derive it from the seed (not included if challenge is 0)
|
||||
uint8_t *communicatedBits;
|
||||
uint8_t view3Commitment[SHA256_DIGEST_LENGTH];
|
||||
uint8_t *view3UnruhG; // we include the max length, but we will only serialize the bytes we use
|
||||
} proof_t;
|
||||
|
||||
typedef struct signature_t {
|
||||
proof_t proofs[NUM_ZKB_ROUNDS];
|
||||
uint8_t challengeBits[((2 * NUM_ZKB_ROUNDS) - 1) / 8 + 1]; // there are 2 bits per round for the challenge.
|
||||
} signature_t;
|
||||
|
||||
typedef enum {
|
||||
TRANSFORM_FS = 0,
|
||||
TRANSFORM_UR = 1,
|
||||
TRANSFORM_INVALID = 255
|
||||
} transform_t;
|
||||
|
||||
int sign(uint32_t *privateKey, uint32_t *pubKey, uint32_t *pubInput, const uint8_t *message, size_t messageByteLength, signature_t *sig, transform_t transform, lowmcparams_t *params);
|
||||
int verify(signature_t *sig, const uint32_t *pubKey, const uint32_t *pubInput, const uint8_t *message, size_t messageByteLength, transform_t transform, lowmcparams_t *params);
|
||||
|
||||
void allocateSignature(signature_t *sig, lowmcparams_t *params);
|
||||
void freeSignature(signature_t *sig);
|
||||
|
||||
/* Returns the number of bytes written on success, or -1 on error */
|
||||
int serializeSignature(const signature_t *sig, uint8_t *sigBytes, size_t sigBytesLen, transform_t transform, lowmcparams_t *params);
|
||||
/* Returns EXIT_SUCCESS on success or EXIT_FAILURE on error */
|
||||
int deserializeSignature(signature_t *sig, const uint8_t *sigBytes, size_t sigBytesLen, transform_t transform, lowmcparams_t *params);
|
||||
|
||||
/* Functions to initialize OpenSSL */
|
||||
void init_EVP();
|
||||
void cleanup_EVP();
|
||||
|
||||
/*
|
||||
* Fill buf with len random bytes.
|
||||
* Returns 1 on success, 0 on failure
|
||||
*/
|
||||
int random_bytes_default_openssl(uint8_t *buf, size_t len);
|
||||
|
||||
/* Return the number of bytes required to represent the given number of bits */
|
||||
uint32_t numBytes(uint32_t numBits);
|
||||
|
||||
/* Get a bit from a byte array */
|
||||
uint8_t getBit(const uint8_t *array, uint32_t bitNumber);
|
||||
uint8_t getBitFromWordArray(const uint32_t *array, uint32_t bitNumber);
|
||||
|
||||
/* Set a bit in a byte/word array */
|
||||
void setBit(uint8_t *bytes, uint32_t bitNumber, uint8_t val);
|
||||
void setBitInWordArray(uint32_t *bytes, uint32_t bitNumber, uint8_t val);
|
||||
|
||||
#endif /* LOWMC_H */
|
@ -1,51 +0,0 @@
|
||||
/*! @file LowMCConstants.h
|
||||
* @brief Constant parameters for the LowMC instantiations used in the
|
||||
* signature scheme.
|
||||
*
|
||||
* This file is part of the reference implementation of the Picnic and Fish
|
||||
* signature schemes, described in the paper:
|
||||
*
|
||||
* Post-Quantum Zero-Knowledge and Signatures from Symmetric-Key Primitives
|
||||
* Melissa Chase and David Derler and Steven Goldfeder and Claudio Orlandi and
|
||||
* Sebastian Ramacher and Christian Rechberger and Daniel Slamanig and Greg
|
||||
* Zaverucha
|
||||
* Cryptology ePrint Archive: Report 2017/279
|
||||
* http://eprint.iacr.org/2017/279
|
||||
*
|
||||
* The code is provided under the MIT license, see LICENSE for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#ifndef LOWMCCONSTANTS_H
|
||||
#define LOWMCCONSTANTS_H
|
||||
|
||||
#define WORD_SIZE_BITS 32 // the word size for the implementation. Not a LowMC parameter
|
||||
|
||||
#define STATE_SIZE_BITS 256
|
||||
#define STATE_SIZE_WORDS STATE_SIZE_BITS / WORD_SIZE_BITS
|
||||
|
||||
#define LOWMC_MAX_STATE_SIZE 32
|
||||
|
||||
#if (STATE_SIZE_WORDS & 1) == 1
|
||||
#error The implementation of LowMC assumes STATE_SIZE_WORDS is even
|
||||
#endif
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
#define DEFAULT_DATA_PATH "precomputed_data\\"
|
||||
#else
|
||||
#define DEFAULT_DATA_PATH "precomputed_data/"
|
||||
#endif
|
||||
|
||||
typedef struct lowmcparams_t {
|
||||
uint32_t numRounds;
|
||||
uint32_t numSboxes;
|
||||
uint32_t stateSizeBits;
|
||||
uint32_t stateSizeBytes;
|
||||
uint32_t stateSizeWords;
|
||||
uint32_t numAndBytes;
|
||||
uint32_t UnruhGWithoutInputBytes;
|
||||
uint32_t UnruhGWithInputBytes;
|
||||
} lowmcparams_t;
|
||||
|
||||
#endif /* LOWMCCONSTANTS_H */
|
@ -1,282 +0,0 @@
|
||||
/*! @file LowMCEnc.c
|
||||
* @brief C implementation of LowMC encrypt. This is used to generate keys
|
||||
* for the Picnic signature scheme.
|
||||
*
|
||||
* This file is part of the reference implementation of the Picnic and Fish
|
||||
* signature schemes, described in the paper:
|
||||
*
|
||||
* Post-Quantum Zero-Knowledge and Signatures from Symmetric-Key Primitives
|
||||
* Melissa Chase and David Derler and Steven Goldfeder and Claudio Orlandi and
|
||||
* Sebastian Ramacher and Christian Rechberger and Daniel Slamanig and Greg
|
||||
* Zaverucha
|
||||
* Cryptology ePrint Archive: Report 2017/279
|
||||
* http://eprint.iacr.org/2017/279
|
||||
*
|
||||
* The code is provided under the MIT license, see LICENSE for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <immintrin.h>
|
||||
|
||||
#include "LowMCConstants.h"
|
||||
#include "platform.h"
|
||||
|
||||
#define t 8
|
||||
|
||||
uint32_t (*linearMatricesLookupTable)[STATE_SIZE_BITS / t][1 << t][STATE_SIZE_WORDS];
|
||||
uint32_t (*keyMatricesLookupTable)[STATE_SIZE_BITS / t][1 << t][STATE_SIZE_WORDS];
|
||||
uint32_t (*roundConstants)[STATE_SIZE_WORDS];
|
||||
|
||||
__m256i (*linearMatricesLookupTableVec)[STATE_SIZE_BITS / t][1 << t][1];
|
||||
__m256i (*keyMatricesLookupTableVec)[STATE_SIZE_BITS / t][1 << t][1];
|
||||
__m256i (*roundConstantsVec)[1];
|
||||
|
||||
/* Helper functions */
|
||||
|
||||
/* Get one bit from a byte array */
|
||||
static uint8_t getBit(const uint32_t *array, uint32_t bitNumber) {
|
||||
return (array[bitNumber / WORD_SIZE_BITS] >> (WORD_SIZE_BITS - 1 - (bitNumber % WORD_SIZE_BITS))) & 0x01;
|
||||
}
|
||||
|
||||
/* Set a specific bit in a byte array to a given value */
|
||||
static void setBit(uint32_t *bytes, uint32_t bitNumber, uint8_t val) {
|
||||
bytes[bitNumber / WORD_SIZE_BITS] = (bytes[bitNumber / WORD_SIZE_BITS] & ~(1 << (WORD_SIZE_BITS - 1 - (bitNumber % WORD_SIZE_BITS)))) | (val << (WORD_SIZE_BITS - 1 - (bitNumber % WORD_SIZE_BITS)));
|
||||
}
|
||||
|
||||
static void xor_bytes(uint32_t *in1, uint32_t *in2, uint32_t *out, uint32_t numBytes) {
|
||||
for (uint32_t i = 0; i < numBytes; i++) {
|
||||
out[i] = in1[i] ^ in2[i];
|
||||
}
|
||||
}
|
||||
|
||||
static void multiplyWithMatrix(uint32_t *state,
|
||||
uint32_t matrix[STATE_SIZE_BITS / t][1 << t][STATE_SIZE_WORDS],
|
||||
uint32_t *output, lowmcparams_t *params) {
|
||||
uint32_t temp[STATE_SIZE_WORDS] = {0};
|
||||
|
||||
for (uint32_t i = 0; i < params->stateSizeWords; i++) {
|
||||
xor_bytes(temp, matrix[i * (sizeof(uint32_t))][(state[i] >> 24) & 0xFF], temp,
|
||||
params->stateSizeWords);
|
||||
xor_bytes(temp, matrix[i * (sizeof(uint32_t)) + 1][(state[i] >> 16) & 0xFF],
|
||||
temp, params->stateSizeWords);
|
||||
xor_bytes(temp, matrix[i * (sizeof(uint32_t)) + 2][(state[i] >> 8) & 0xFF],
|
||||
temp, params->stateSizeWords);
|
||||
xor_bytes(temp, matrix[i * (sizeof(uint32_t)) + 3][(state[i]) & 0xFF], temp,
|
||||
params->stateSizeWords);
|
||||
}
|
||||
memcpy(output, &temp, params->stateSizeBytes);
|
||||
}
|
||||
|
||||
// starts from the left, and interprets the first bit t encounters as the highest order bit (compared to the lookup table
|
||||
// in lowmc reference code. may need to change this
|
||||
static void substitution(uint32_t *state, lowmcparams_t *params) {
|
||||
for (uint32_t i = 0; i < params->numSboxes * 3; i += 3) {
|
||||
uint8_t a = getBit(state, params->stateSizeBits - 1 - i - 2);
|
||||
uint8_t b = getBit(state, params->stateSizeBits - 1 - i - 1);
|
||||
uint8_t c = getBit(state, params->stateSizeBits - 1 - i);
|
||||
setBit(state, params->stateSizeBits - 1 - i - 2, a ^ (b & c));
|
||||
setBit(state, params->stateSizeBits - 1 - i - 1, a ^ b ^ (a & c));
|
||||
setBit(state, params->stateSizeBits - 1 - i, a ^ b ^ c ^ (a & b));
|
||||
}
|
||||
}
|
||||
|
||||
static void computeRoundKey(uint32_t *key, uint32_t *output, uint32_t round, lowmcparams_t *params) {
|
||||
multiplyWithMatrix(key, keyMatricesLookupTable[round], output, params);
|
||||
}
|
||||
|
||||
int readRoundConstants(lowmcparams_t *params, FILE *fp) {
|
||||
size_t ret;
|
||||
uint32_t numRounds = params->numRounds;
|
||||
uint32_t stateWords = params->stateSizeWords;
|
||||
|
||||
roundConstants = malloc(
|
||||
numRounds * sizeof(*roundConstants));
|
||||
if (roundConstants == NULL) {
|
||||
fprintf(stderr, "%s: Failed to allocate roundConstants.\n", __func__);
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef WITH_AVX
|
||||
roundConstantsVec = _mm_malloc(
|
||||
numRounds * sizeof(*roundConstantsVec), 32);
|
||||
if (roundConstantsVec == NULL) {
|
||||
fprintf(stderr, "%s: Failed to allocate roundConstantsVec.\n", __func__);
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (uint32_t i = 0; i < numRounds; i++) {
|
||||
ret = fread(&roundConstants[i],
|
||||
sizeof(uint32_t), stateWords, fp);
|
||||
#ifdef WITH_AVX
|
||||
*roundConstantsVec[i] = _mm256_loadu_si256(
|
||||
(__m256i *) roundConstants[i]);
|
||||
#endif
|
||||
if (ret != stateWords) {
|
||||
fprintf(stderr, "%s: Failed to read round constants, aborting.\n", __func__);
|
||||
fclose(fp);
|
||||
free(roundConstants);
|
||||
#ifdef WITH_AVX
|
||||
_mm_free(roundConstantsVec);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int readLookupTables(lowmcparams_t *params, const char *path) {
|
||||
FILE *fp;
|
||||
size_t ret;
|
||||
char filename[256];
|
||||
|
||||
if (path == NULL) {
|
||||
path = DEFAULT_DATA_PATH;
|
||||
} else if (strlen(path) > 220) {
|
||||
fprintf(stderr, "%s: Faield to read lookup tables. Provided path is too long\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sprintf(filename, "%slookupTables_%d_%d_%d.bin", path, params->stateSizeBits, params->numSboxes, params->numRounds);
|
||||
fp = fopen(filename, "rb");
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr, "%s: Failed to open '%s'.\n", __func__, filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t numRounds = params->numRounds;
|
||||
uint32_t stateBits = params->stateSizeBits;
|
||||
uint32_t stateWords = params->stateSizeWords;
|
||||
linearMatricesLookupTable = malloc(
|
||||
numRounds * sizeof(*linearMatricesLookupTable));
|
||||
if (linearMatricesLookupTable == NULL) {
|
||||
fprintf(stderr, "%s: Failed to allocate linearMatricesLookupTable.\n", __func__);
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef WITH_AVX
|
||||
linearMatricesLookupTableVec = _mm_malloc(
|
||||
numRounds * sizeof(*linearMatricesLookupTableVec), 32);
|
||||
if (linearMatricesLookupTableVec == NULL) {
|
||||
fprintf(stderr, "%s: Failed to allocate keyMatricesLookupTableVec.\n", __func__);
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (uint32_t i = 0; i < numRounds; i++) {
|
||||
for (uint32_t j = 0; j < stateBits / t; j++) {
|
||||
for (uint32_t k = 0; k < (1 << t); k++) {
|
||||
ret = fread(linearMatricesLookupTable[i][j][k], sizeof(uint32_t), stateWords, fp);
|
||||
#ifdef WITH_AVX
|
||||
*linearMatricesLookupTableVec[i][j][k] = _mm256_loadu_si256(
|
||||
(__m256i *) linearMatricesLookupTable[i][j][k]);
|
||||
#endif
|
||||
if (ret != stateWords) {
|
||||
fprintf(stderr, "%s: Failed to read look up table, aborting.\n", __func__);
|
||||
fclose(fp);
|
||||
free(linearMatricesLookupTable);
|
||||
#ifdef WITH_AVX
|
||||
_mm_free(linearMatricesLookupTableVec);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
numRounds++;
|
||||
|
||||
keyMatricesLookupTable = malloc(numRounds * sizeof(*keyMatricesLookupTable));
|
||||
|
||||
if (keyMatricesLookupTable == NULL) {
|
||||
fprintf(stderr, "%s: Failed to allocate keyMatricesLookupTable.\n", __func__);
|
||||
fclose(fp);
|
||||
free(linearMatricesLookupTable);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef WITH_AVX
|
||||
keyMatricesLookupTableVec = _mm_malloc(numRounds * sizeof(*keyMatricesLookupTableVec), 32);
|
||||
|
||||
if (keyMatricesLookupTableVec == NULL) {
|
||||
fprintf(stderr, "%s: Failed to allocate keyMatricesLookupTableVec.\n", __func__);
|
||||
fclose(fp);
|
||||
_mm_free(linearMatricesLookupTableVec);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (uint32_t i = 0; i < numRounds; i++) {
|
||||
for (uint32_t j = 0; j < stateBits / t; j++) {
|
||||
for (uint32_t k = 0; k < (1 << t); k++) {
|
||||
ret = fread(keyMatricesLookupTable[i][j][k], sizeof(uint32_t),
|
||||
stateWords, fp);
|
||||
#ifdef WITH_AVX
|
||||
*keyMatricesLookupTableVec[i][j][k] = _mm256_loadu_si256(
|
||||
(__m256i *) keyMatricesLookupTable[i][j][k]);
|
||||
#endif
|
||||
|
||||
if (ret != stateWords) {
|
||||
fprintf(stderr, "%s: Failed to read look up table, aborting. \n", __func__);
|
||||
fclose(fp);
|
||||
free(linearMatricesLookupTable);
|
||||
free(keyMatricesLookupTable);
|
||||
#ifdef WITH_AVX
|
||||
_mm_free(linearMatricesLookupTableVec);
|
||||
_mm_free(keyMatricesLookupTable);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return readRoundConstants(params, fp);
|
||||
}
|
||||
void freeRoundConstants() {
|
||||
free(roundConstants);
|
||||
#ifdef WITH_AVX
|
||||
_mm_free(roundConstantsVec);
|
||||
#endif
|
||||
}
|
||||
|
||||
void freeLookupTables() {
|
||||
free(linearMatricesLookupTable);
|
||||
free(keyMatricesLookupTable);
|
||||
#ifdef WITH_AVX
|
||||
_mm_free(linearMatricesLookupTableVec);
|
||||
_mm_free(keyMatricesLookupTableVec);
|
||||
#endif
|
||||
freeRoundConstants();
|
||||
}
|
||||
|
||||
void LowMCEnc(const uint32_t *plaintext, uint32_t *output, uint32_t *key, lowmcparams_t *params) {
|
||||
uint32_t roundKey[LOWMC_MAX_STATE_SIZE / sizeof(uint32_t)];
|
||||
|
||||
if (plaintext != output) {
|
||||
/* output will hold the intermediate state */
|
||||
memcpy(output, plaintext, params->stateSizeBytes);
|
||||
}
|
||||
|
||||
computeRoundKey(key, roundKey, 0, params);
|
||||
xor_bytes(output, roundKey, output, params->stateSizeWords);
|
||||
|
||||
for (uint32_t r = 1; r <= params->numRounds; r++) {
|
||||
computeRoundKey(key, roundKey, r, params);
|
||||
substitution(output, params);
|
||||
multiplyWithMatrix(output, linearMatricesLookupTable[r - 1], output, params);
|
||||
xor_bytes(output, roundConstants[r - 1], output, params->stateSizeWords);
|
||||
xor_bytes(output, roundKey, output, params->stateSizeWords);
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
/*! @file LowMCEnc.h
|
||||
* @brief Header file for LowMcEnc.c, the C implementation of LowMC.
|
||||
*
|
||||
* This file is part of the reference implementation of the Picnic and Fish
|
||||
* signature schemes, described in the paper:
|
||||
*
|
||||
* Post-Quantum Zero-Knowledge and Signatures from Symmetric-Key Primitives
|
||||
* Melissa Chase and David Derler and Steven Goldfeder and Claudio Orlandi and
|
||||
* Sebastian Ramacher and Christian Rechberger and Daniel Slamanig and Greg
|
||||
* Zaverucha
|
||||
* Cryptology ePrint Archive: Report 2017/279
|
||||
* http://eprint.iacr.org/2017/279
|
||||
*
|
||||
* The code is provided under the MIT license, see LICENSE for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LowMCEnc_h
|
||||
#define LowMCEnc_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include "LowMCConstants.h"
|
||||
|
||||
/** Encrypt one block of data with the specified LowMC parameter set
|
||||
*
|
||||
* @param plaintext[in] The plaintext to encrypt, must have length STATE_SIZE_BYTES
|
||||
* @param ciphertext[in,out] The output ciphertext, must have length STATE_SIZE_BYTES
|
||||
* @param key[in] The key to use for encryption. Must have length STATE_SIZE_BYTES
|
||||
* @param parameters[in] The LowMC parameter set to be used
|
||||
*
|
||||
* @remark Before encryption, readLookupTables must be called, and afterwards
|
||||
* freeLookupTables should be called to free memory.
|
||||
*/
|
||||
void LowMCEnc(const uint32_t *plaintext, uint32_t *ciphertext,
|
||||
const uint32_t *key, lowmcparams_t *parameters);
|
||||
|
||||
/** Read precomputed data required by LowMCEnc().
|
||||
* If the path parameter is NULL, data is read from DEFAULT_DATA_PATH. If the path
|
||||
* parameter is provided, it must contain the trailing slash, i.e., "mypath/", not "mypath"
|
||||
*/
|
||||
int readLookupTables(lowmcparams_t *params, const char *path);
|
||||
|
||||
/** Free memory allocated by readLookupTables */
|
||||
void freeLookupTables();
|
||||
|
||||
#endif /* LowMcEnc_h */
|
@ -1,8 +0,0 @@
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
noinst_LTLIBRARIES = libpicnicmsr.la
|
||||
|
||||
|
||||
libpicnicmsr_la_SOURCES = LowMCEnc.c LowMC.c picnic.c
|
||||
|
||||
libpicnicmsr_la_CPPFLAGS = -O3 -march=native -Wall -Wextra -Wpedantic -Werror -std=gnu99 -D__LINUX__ -D__X64__
|
||||
|
@ -1,322 +0,0 @@
|
||||
/*! @file benchmark_lowmc.c
|
||||
* @brief Benchmarking code for the Picnic and Fish signature schemes. KeyGen,
|
||||
* sign, and verify are benchmarked both directly as well as using the
|
||||
* signature API.
|
||||
*
|
||||
* This file is part of the reference implementation of the Picnic and Fish
|
||||
* signature schemes, described in the paper:
|
||||
*
|
||||
* Post-Quantum Zero-Knowledge and Signatures from Symmetric-Key Primitives
|
||||
* Melissa Chase and David Derler and Steven Goldfeder and Claudio Orlandi and
|
||||
* Sebastian Ramacher and Christian Rechberger and Daniel Slamanig and Greg
|
||||
* Zaverucha
|
||||
* Cryptology ePrint Archive: Report 2017/279
|
||||
* http://eprint.iacr.org/2017/279
|
||||
*
|
||||
* The code is provided under the MIT license, see LICENSE for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#include "LowMCEnc.h"
|
||||
#include "LowMC.h"
|
||||
#include "test_util.h"
|
||||
#include <immintrin.h>
|
||||
|
||||
#include "picnic.h"
|
||||
|
||||
#define NUM_ITER 1
|
||||
#define t 8
|
||||
|
||||
#define MESSAGE_LEN 50
|
||||
|
||||
#define TRANSFORM_STRING(tr) ((tr == TRANSFORM_UR) ? "UR" : "FS")
|
||||
|
||||
/* function defined in picnic.c, used here for testing, but not part of the Picnic API */
|
||||
int picnicParamsToLowMCParams(picnic_params_t picnicParams, lowmcparams_t *lowmcParams);
|
||||
|
||||
/* nameOfConfig is just used to print the results nicely and can be anything, but
|
||||
* should be a recognizable name of the circuit used */
|
||||
void benchmarkPicnicDirect(const char *nameOfConfig, transform_t transform, picnic_params_t params) {
|
||||
lowmcparams_t lowmcparams;
|
||||
|
||||
if (picnicParamsToLowMCParams(params, &lowmcparams) != EXIT_SUCCESS) {
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
uint32_t *privateKey = calloc(lowmcparams.stateSizeWords, sizeof(uint32_t));
|
||||
privateKey[lowmcparams.stateSizeWords - 1] = 1;
|
||||
uint32_t *pubInput = calloc(lowmcparams.stateSizeWords, sizeof(uint32_t));
|
||||
pubInput[lowmcparams.stateSizeWords - 1] = 1;
|
||||
|
||||
uint8_t message[MESSAGE_LEN];
|
||||
memset(&message, 0, sizeof(message));
|
||||
|
||||
if (readLookupTables(&lowmcparams, NULL) != 0) {
|
||||
fprintf(stdout, "Initialization failed (reading look-up tables).\n");
|
||||
fflush(stdout);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
uint64_t cycles_begin, cycles_end;
|
||||
|
||||
/* Generate key pair */
|
||||
uint32_t *publicKey = (uint32_t *) malloc(lowmcparams.stateSizeWords * sizeof(uint32_t));
|
||||
signature_t *signature = malloc(sizeof(signature_t));
|
||||
allocateSignature(signature, &lowmcparams);
|
||||
|
||||
printf("\nPicnic direct benchmark: running keyGen, sign & verify for %d iterations of %d rounds each \n",
|
||||
NUM_ITER, NUM_ZKB_ROUNDS);
|
||||
|
||||
cycles_begin = cpucycles();
|
||||
for (int i = 0; i < NUM_ITER; i++) {
|
||||
LowMCEnc(pubInput, publicKey, privateKey, &lowmcparams);
|
||||
}
|
||||
cycles_end = cpucycles();
|
||||
|
||||
char label[100];
|
||||
sprintf(label, "Time for [%s-%s] keyGeneration (LowMCEnc())", nameOfConfig, TRANSFORM_STRING(transform));
|
||||
bench_print(label, (cycles_end - cycles_begin), NUM_ITER); /* The 3rd param is the number of runs*/
|
||||
|
||||
cycles_begin = cpucycles();
|
||||
for (int i = 0; i < NUM_ITER; i++) {
|
||||
sign(privateKey, publicKey, pubInput, message, sizeof(message), signature, transform, &lowmcparams);
|
||||
}
|
||||
cycles_end = cpucycles();
|
||||
|
||||
sprintf(label, "Time for [%s-%s] sign()", nameOfConfig, TRANSFORM_STRING(transform));
|
||||
bench_print(label, (cycles_end - cycles_begin), NUM_ITER); /* The 3rd param is the number of runs*/
|
||||
|
||||
cycles_begin = cpucycles();
|
||||
for (int i = 0; i < NUM_ITER; i++) {
|
||||
verify(signature, publicKey, pubInput, message,
|
||||
sizeof(message), transform, &lowmcparams);
|
||||
}
|
||||
cycles_end = cpucycles();
|
||||
|
||||
sprintf(label, "Time for [%s-%s] verify()", nameOfConfig, TRANSFORM_STRING(transform));
|
||||
bench_print(label, (cycles_end - cycles_begin), NUM_ITER);
|
||||
|
||||
freeSignature(signature);
|
||||
free(signature);
|
||||
free(publicKey);
|
||||
free(privateKey);
|
||||
free(pubInput);
|
||||
freeLookupTables();
|
||||
}
|
||||
|
||||
void benchmarkPicnicAPI(char *nameOfConfig, transform_t transform, picnic_params_t params) {
|
||||
picnic_publickey_t pk;
|
||||
picnic_privatekey_t sk;
|
||||
uint64_t cycles_begin, cycles_end;
|
||||
char label[100];
|
||||
|
||||
printf("\n Picnic API benchmark: running keyGen, sign & verify for %d iterations of %d rounds each \n",
|
||||
NUM_ITER, NUM_ZKB_ROUNDS);
|
||||
|
||||
if (picnic_init(params, NULL, 0) != 0) {
|
||||
fprintf(stdout, "Initialization failed.\n");
|
||||
fflush(stdout);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Key generation */
|
||||
cycles_begin = cpucycles();
|
||||
for (int i = 0; i < NUM_ITER; i++) {
|
||||
(void) picnic_keygen(params, &pk, &sk);
|
||||
}
|
||||
cycles_end = cpucycles();
|
||||
|
||||
sprintf(label, "Time for [%s-%s] picnic_keygen", nameOfConfig, TRANSFORM_STRING(transform));
|
||||
bench_print(label, (cycles_end - cycles_begin), NUM_ITER);
|
||||
|
||||
/* Sign */
|
||||
uint8_t message[MESSAGE_LEN];
|
||||
memset(&message, 0, sizeof(message));
|
||||
uint8_t *signature = NULL;
|
||||
|
||||
size_t signature_len = picnic_signature_size(params);
|
||||
signature = (uint8_t *) malloc(signature_len);
|
||||
if (signature == NULL) {
|
||||
printf("failed to allocate signature\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
size_t av_sig_len = 0;
|
||||
cycles_begin = cpucycles();
|
||||
for (int i = 0; i < NUM_ITER; i++) {
|
||||
/* Since the sign API outputs the number of signature bytes, re-set it
|
||||
* to the size of the buffer every iteration */
|
||||
size_t siglen = signature_len;
|
||||
|
||||
(void) picnic_sign(&sk, message, sizeof(message), signature, &siglen);
|
||||
av_sig_len += siglen;
|
||||
}
|
||||
cycles_end = cpucycles();
|
||||
|
||||
sprintf(label, "Time for [%s-%s] picnic_sign", nameOfConfig, TRANSFORM_STRING(transform));
|
||||
bench_print(label, (cycles_end - cycles_begin), NUM_ITER);
|
||||
|
||||
/* Verify */
|
||||
cycles_begin = cpucycles();
|
||||
for (int i = 0; i < NUM_ITER; i++) {
|
||||
(void) picnic_verify(&pk, message, sizeof(message), signature,
|
||||
signature_len);
|
||||
}
|
||||
cycles_end = cpucycles();
|
||||
|
||||
sprintf(label, "Time for [%s-%s] picnic_verify", nameOfConfig, TRANSFORM_STRING(transform));
|
||||
bench_print(label, (cycles_end - cycles_begin), NUM_ITER);
|
||||
|
||||
if (transform == TRANSFORM_UR) {
|
||||
printf(" Signature size (exact): %u bytes\n", (unsigned int) (av_sig_len / NUM_ITER));
|
||||
} else if (transform == TRANSFORM_FS) {
|
||||
unsigned int av = ((unsigned int) (av_sig_len / NUM_ITER)) + ((av_sig_len % NUM_ITER) != 0);
|
||||
printf(" Signature size (average): %u bytes\n", av);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
free(signature);
|
||||
picnic_shutdown(0);
|
||||
}
|
||||
|
||||
void parseOptions(int argc, char **argv, transform_t *transform) {
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (strcmp("-u", argv[i]) == 0) {
|
||||
*transform = TRANSFORM_UR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int serializationTest(transform_t transform, picnic_params_t params) {
|
||||
int ret = -1;
|
||||
lowmcparams_t lowmcparams = {0};
|
||||
signature_t signature;
|
||||
signature_t signature2;
|
||||
uint32_t *privateKey = NULL;
|
||||
uint32_t *pubInput = NULL;
|
||||
|
||||
if (picnicParamsToLowMCParams(params, &lowmcparams) != EXIT_SUCCESS) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t *publicKey = (uint32_t *) malloc(lowmcparams.stateSizeWords * sizeof(uint32_t));
|
||||
uint8_t message[MESSAGE_LEN];
|
||||
memset(&message, 0, sizeof(message));
|
||||
|
||||
if (readLookupTables(&lowmcparams, NULL) != 0) {
|
||||
fprintf(stdout, "Initialization failed (reading look-up tables).\n");
|
||||
ret = -1;
|
||||
goto Exit;
|
||||
}
|
||||
/* Generate key pair */
|
||||
privateKey = calloc(lowmcparams.stateSizeWords, sizeof(uint32_t));
|
||||
pubInput = calloc(lowmcparams.stateSizeWords, sizeof(uint32_t));
|
||||
|
||||
LowMCEnc(pubInput, publicKey, privateKey, &lowmcparams);
|
||||
|
||||
/* Create a signature to serialize */
|
||||
allocateSignature(&signature, &lowmcparams);
|
||||
allocateSignature(&signature2, &lowmcparams);
|
||||
sign(privateKey, publicKey, pubInput, message, sizeof(message), &signature, transform, &lowmcparams);
|
||||
|
||||
uint8_t sigBytes[PICNIC_MAX_SIGNATURE_SIZE];
|
||||
memset(sigBytes, 0, sizeof(sigBytes));
|
||||
ret = serializeSignature(&signature, sigBytes, sizeof(sigBytes), transform, &lowmcparams);
|
||||
if (ret == -1) {
|
||||
fprintf(stderr, "Failed to serialize signature\n");
|
||||
ret = -1;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
ret = deserializeSignature(&signature2, sigBytes, sizeof(sigBytes), transform, &lowmcparams);
|
||||
if (ret != EXIT_SUCCESS) {
|
||||
fprintf(stderr, "Failed to deserialize signature\n");
|
||||
ret = -1;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
uint8_t sigBytes2[sizeof(sigBytes)];
|
||||
memset(sigBytes2, 0, sizeof(sigBytes2));
|
||||
ret = serializeSignature(&signature2, sigBytes2, sizeof(sigBytes2), transform, &lowmcparams);
|
||||
if (ret == -1) {
|
||||
fprintf(stderr, "Failed to serialize signature 2\n");
|
||||
ret = -1;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (memcmp(sigBytes, sigBytes2, sizeof(sigBytes2)) != 0) {
|
||||
fprintf(stderr, "Serialization roundtrip failed\n");
|
||||
ret = -1;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
ret = verify(&signature2, publicKey, pubInput, message, sizeof(message), transform, &lowmcparams);
|
||||
if (ret != EXIT_SUCCESS) {
|
||||
fprintf(stderr, "Failed to verify deserialized signature\n");
|
||||
ret = -1;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
ret = 0; /* Success */
|
||||
|
||||
Exit:
|
||||
freeSignature(&signature);
|
||||
freeSignature(&signature2);
|
||||
free(publicKey);
|
||||
free(privateKey);
|
||||
free(pubInput);
|
||||
freeLookupTables();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void runBenchmarks(picnic_params_t params, transform_t transform) {
|
||||
|
||||
printf("\nBenchmarking Picnic with %s\n", picnic_get_param_name(params));
|
||||
|
||||
if (serializationTest(transform, params) != 0) {
|
||||
printf("Failed serialization test\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* Benchmark Picnic by calling the sign/verify functions directly (as
|
||||
* opposed to using the public API) */
|
||||
benchmarkPicnicDirect("LowMC", transform, params);
|
||||
|
||||
/* Benchmark functions in the public API */
|
||||
benchmarkPicnicAPI("LowMC", transform, params);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
transform_t transform = TRANSFORM_FS;
|
||||
|
||||
parseOptions(argc, argv, &transform);
|
||||
|
||||
printf("Running benchmarks\n");
|
||||
|
||||
// benchmark the given transform with each of the 3 supported LowMC parameter sets
|
||||
picnic_params_t params;
|
||||
params = (transform == TRANSFORM_UR) ? LowMC_256_256_42_14_UR : LowMC_256_256_42_14_FS;
|
||||
runBenchmarks(params, transform);
|
||||
|
||||
params = (transform == TRANSFORM_UR) ? LowMC_256_256_1_316_UR : LowMC_256_256_1_316_FS;
|
||||
runBenchmarks(params, transform);
|
||||
|
||||
params = (transform == TRANSFORM_UR) ? LowMC_256_256_10_38_UR : LowMC_256_256_10_38_FS;
|
||||
runBenchmarks(params, transform);
|
||||
}
|
@ -1,152 +0,0 @@
|
||||
/*! @file example.c
|
||||
* @brief This is an example program to demonstrate how to use the
|
||||
* signature API.
|
||||
*
|
||||
* This file is part of the reference implementation of the Picnic and Fish
|
||||
* signature schemes, described in the paper:
|
||||
*
|
||||
* Post-Quantum Zero-Knowledge and Signatures from Symmetric-Key Primitives
|
||||
* Melissa Chase and David Derler and Steven Goldfeder and Claudio Orlandi and
|
||||
* Sebastian Ramacher and Christian Rechberger and Daniel Slamanig and Greg
|
||||
* Zaverucha
|
||||
* Cryptology ePrint Archive: Report 2017/279
|
||||
* http://eprint.iacr.org/2017/279
|
||||
*
|
||||
* The code is provided under the MIT license, see LICENSE for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
#include "LowMC.h"
|
||||
#include "picnic.h"
|
||||
#include <stdio.h>
|
||||
#include <memory.h>
|
||||
|
||||
#define MSG_LEN 500
|
||||
|
||||
int picnicExample(picnic_params_t parameters) {
|
||||
picnic_publickey_t pk;
|
||||
picnic_privatekey_t sk;
|
||||
|
||||
printf("Picnic example with parameter set: %s\n", picnic_get_param_name(parameters));
|
||||
|
||||
fprintf(stdout, "Initializing library... ");
|
||||
fflush(stdout);
|
||||
if (picnic_init(parameters, NULL, 0) != 0) {
|
||||
fprintf(stdout, "Initialization failed.\n");
|
||||
fflush(stdout);
|
||||
exit(-1);
|
||||
}
|
||||
printf("done\n");
|
||||
|
||||
fprintf(stdout, "Generating key... ");
|
||||
fflush(stdout);
|
||||
int ret = picnic_keygen(parameters, &pk, &sk);
|
||||
|
||||
if (ret != 0) {
|
||||
printf("picnic_keygen failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
printf(" success\n");
|
||||
|
||||
uint8_t message[MSG_LEN];
|
||||
memset(message, 0x01, sizeof(message));
|
||||
uint8_t *signature = NULL;
|
||||
|
||||
size_t signature_len = picnic_signature_size(parameters);
|
||||
signature = (uint8_t *) malloc(signature_len);
|
||||
if (signature == NULL) {
|
||||
printf("failed to allocate signature\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
fprintf(stdout, "Signing a %d byte message... ", MSG_LEN);
|
||||
fflush(stdout);
|
||||
|
||||
ret = picnic_sign(&sk, message, sizeof(message), signature, &signature_len);
|
||||
if (ret != 0) {
|
||||
printf("picnic_sign failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
printf(" success\n");
|
||||
|
||||
/* signature_len has the exact number of bytes used */
|
||||
if (signature_len < picnic_signature_size(parameters)) {
|
||||
uint8_t *newsig = realloc(signature, signature_len);
|
||||
if (newsig == NULL) {
|
||||
printf("failed to re-size signature\n");
|
||||
/* Not an error, we can continue with signature */
|
||||
} else {
|
||||
signature = newsig;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stdout, "Verifying signature... ");
|
||||
fflush(stdout);
|
||||
|
||||
ret = picnic_verify(&pk, message, sizeof(message), signature, signature_len);
|
||||
if (ret != 0) {
|
||||
printf("picnic_verify failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
printf(" success\n");
|
||||
|
||||
printf("Testing public key serialization... ");
|
||||
uint8_t pk_buf[PICNIC_MAX_PUBLICKEY_SIZE + 1];
|
||||
ret = picnic_write_public_key(&pk, pk_buf, sizeof(pk_buf));
|
||||
if (ret <= 0) {
|
||||
printf("Failed to serialize public key\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
memset(&pk, 0x00, sizeof(picnic_publickey_t));
|
||||
|
||||
ret = picnic_read_public_key(&pk, pk_buf, sizeof(pk_buf));
|
||||
if (ret != 0) {
|
||||
printf("Failed to read public key\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
ret = picnic_verify(&pk, message, sizeof(message), signature, signature_len);
|
||||
if (ret != 0) {
|
||||
printf("picnic_verify failedi after de-serializing public key\n");
|
||||
exit(-1);
|
||||
}
|
||||
printf(" success\n");
|
||||
|
||||
printf("Testing private key serialization... ");
|
||||
uint8_t sk_buf[PICNIC_MAX_PRIVATEKEY_SIZE + 1];
|
||||
ret = picnic_write_private_key(&sk, sk_buf, sizeof(sk_buf));
|
||||
if (ret <= 0) {
|
||||
printf("Failed to write private key\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
memset(&sk, 0x00, sizeof(picnic_privatekey_t));
|
||||
ret = picnic_read_private_key(&sk, sk_buf, sizeof(sk_buf), &pk);
|
||||
if (ret != 0) {
|
||||
printf("Failed to read private key\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
ret = picnic_validate_keypair(&sk, &pk);
|
||||
if (ret != 0) {
|
||||
printf("Keypair invalid after deserializing private key\n");
|
||||
exit(-1);
|
||||
}
|
||||
printf(" success\n");
|
||||
|
||||
fprintf(stdout, "Shutting down library... ");
|
||||
fflush(stdout);
|
||||
picnic_shutdown(0);
|
||||
printf("done\n\n");
|
||||
|
||||
free(signature);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
for (picnic_params_t params = 1; params < PARAMETER_SET_MAX_INDEX; params++) {
|
||||
picnicExample(params);
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,467 +0,0 @@
|
||||
/*! @file picnic.c
|
||||
* @brief Implementation of the Picnic signature API
|
||||
*
|
||||
* This file is part of the reference implementation of the Picnic and Fish
|
||||
* signature schemes, described in the paper:
|
||||
*
|
||||
* Post-Quantum Zero-Knowledge and Signatures from Symmetric-Key Primitives
|
||||
* Melissa Chase and David Derler and Steven Goldfeder and Claudio Orlandi and
|
||||
* Sebastian Ramacher and Christian Rechberger and Daniel Slamanig and Greg
|
||||
* Zaverucha
|
||||
* Cryptology ePrint Archive: Report 2017/279
|
||||
* http://eprint.iacr.org/2017/279
|
||||
*
|
||||
* The code is provided under the MIT license, see LICENSE for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <memory.h>
|
||||
#include <limits.h>
|
||||
#include "LowMCEnc.h"
|
||||
#include "LowMC.h"
|
||||
#include "picnic.h"
|
||||
#include "platform.h"
|
||||
|
||||
static int g_initialized = 0;
|
||||
|
||||
#define ENSURE_LIBRARY_INITIALIZED() \
|
||||
if (!g_initialized) { \
|
||||
printf("Library not initialized\n"); \
|
||||
return -1; \
|
||||
}
|
||||
|
||||
static int is_valid_params(picnic_params_t params) {
|
||||
if (params > 0 && params < PARAMETER_SET_MAX_INDEX) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
transform_t get_transform(picnic_params_t parameters) {
|
||||
switch (parameters) {
|
||||
case LowMC_256_256_42_14_FS:
|
||||
case LowMC_256_256_1_316_FS:
|
||||
case LowMC_256_256_10_38_FS:
|
||||
return TRANSFORM_FS;
|
||||
case LowMC_256_256_42_14_UR:
|
||||
case LowMC_256_256_1_316_UR:
|
||||
case LowMC_256_256_10_38_UR:
|
||||
return TRANSFORM_UR;
|
||||
|
||||
default:
|
||||
return TRANSFORM_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
const char *picnic_get_param_name(picnic_params_t parameters) {
|
||||
switch (parameters) {
|
||||
case LowMC_256_256_42_14_FS:
|
||||
return "LowMC_256_256_42_14_FS";
|
||||
case LowMC_256_256_1_316_FS:
|
||||
return "LowMC_256_256_1_316_FS";
|
||||
case LowMC_256_256_10_38_FS:
|
||||
return "LowMC_256_256_10_38_FS";
|
||||
case LowMC_256_256_42_14_UR:
|
||||
return "LowMC_256_256_42_14_UR";
|
||||
case LowMC_256_256_1_316_UR:
|
||||
return "LowMC_256_256_1_316_UR";
|
||||
case LowMC_256_256_10_38_UR:
|
||||
return "LowMC_256_256_10_38_UR";
|
||||
|
||||
default:
|
||||
return "Unknown parameter set";
|
||||
}
|
||||
}
|
||||
|
||||
int picnicParamsToLowMCParams(picnic_params_t picnicParams, lowmcparams_t *lowmcParams) {
|
||||
memset(lowmcParams, 0, sizeof(lowmcparams_t));
|
||||
|
||||
switch (picnicParams) {
|
||||
case LowMC_256_256_42_14_FS:
|
||||
lowmcParams->stateSizeBytes = 32;
|
||||
lowmcParams->numSboxes = 42;
|
||||
lowmcParams->numRounds = 14;
|
||||
lowmcParams->numAndBytes = numBytes(lowmcParams->numSboxes * 3 * lowmcParams->numRounds);
|
||||
break;
|
||||
case LowMC_256_256_42_14_UR:
|
||||
lowmcParams->stateSizeBytes = 32;
|
||||
lowmcParams->numSboxes = 42;
|
||||
lowmcParams->numRounds = 14;
|
||||
lowmcParams->numAndBytes = numBytes(lowmcParams->numSboxes * 3 * lowmcParams->numRounds);
|
||||
lowmcParams->UnruhGWithoutInputBytes = PRG_SEED_LENGTH + lowmcParams->numAndBytes;
|
||||
lowmcParams->UnruhGWithInputBytes = lowmcParams->UnruhGWithoutInputBytes + lowmcParams->stateSizeBytes;
|
||||
break;
|
||||
case LowMC_256_256_1_316_FS:
|
||||
lowmcParams->stateSizeBytes = 32;
|
||||
lowmcParams->numSboxes = 1;
|
||||
lowmcParams->numRounds = 316;
|
||||
lowmcParams->numAndBytes = numBytes(lowmcParams->numSboxes * 3 * lowmcParams->numRounds);
|
||||
break;
|
||||
case LowMC_256_256_1_316_UR:
|
||||
lowmcParams->stateSizeBytes = 32;
|
||||
lowmcParams->numSboxes = 1;
|
||||
lowmcParams->numRounds = 316;
|
||||
lowmcParams->numAndBytes = numBytes(lowmcParams->numSboxes * 3 * lowmcParams->numRounds);
|
||||
lowmcParams->UnruhGWithoutInputBytes = PRG_SEED_LENGTH + lowmcParams->numAndBytes;
|
||||
lowmcParams->UnruhGWithInputBytes = lowmcParams->UnruhGWithoutInputBytes + lowmcParams->stateSizeBytes;
|
||||
break;
|
||||
case LowMC_256_256_10_38_FS:
|
||||
lowmcParams->stateSizeBytes = 32;
|
||||
lowmcParams->numSboxes = 10;
|
||||
lowmcParams->numRounds = 38;
|
||||
lowmcParams->numAndBytes = numBytes(lowmcParams->numSboxes * 3 * lowmcParams->numRounds);
|
||||
break;
|
||||
case LowMC_256_256_10_38_UR:
|
||||
lowmcParams->stateSizeBytes = 32;
|
||||
lowmcParams->numSboxes = 10;
|
||||
lowmcParams->numRounds = 38;
|
||||
lowmcParams->numAndBytes = numBytes(lowmcParams->numSboxes * 3 * lowmcParams->numRounds);
|
||||
lowmcParams->UnruhGWithoutInputBytes = PRG_SEED_LENGTH + lowmcParams->numAndBytes;
|
||||
lowmcParams->UnruhGWithInputBytes = lowmcParams->UnruhGWithoutInputBytes + lowmcParams->stateSizeBytes;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "%s: Unsupported LowMC parameter set (%d). \n", __func__, picnicParams);
|
||||
return -1;
|
||||
}
|
||||
|
||||
lowmcParams->stateSizeBits = lowmcParams->stateSizeBytes * 8;
|
||||
lowmcParams->stateSizeWords = lowmcParams->stateSizeBits / WORD_SIZE_BITS;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int picnic_init(picnic_params_t params, const char *path, unsigned int flags) {
|
||||
/* NOTE: Not threadsafe, init_EVP may end up being called multiple times.
|
||||
* and readLookupTables will leak if called multiple times. */
|
||||
if (!g_initialized) {
|
||||
|
||||
/* Do not initialize OpenSSL when flags == 1 */
|
||||
if (flags == 0) {
|
||||
init_EVP();
|
||||
}
|
||||
|
||||
lowmcparams_t lowmcparams;
|
||||
|
||||
int ret = picnicParamsToLowMCParams(params, &lowmcparams);
|
||||
if (ret != EXIT_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = readLookupTables(&lowmcparams, path);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
g_initialized = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void picnic_shutdown(unsigned int flags) {
|
||||
if (g_initialized) {
|
||||
|
||||
/* Do not shutdown OpenSSL when flags == 1 */
|
||||
if (flags == 0) {
|
||||
cleanup_EVP();
|
||||
}
|
||||
freeLookupTables();
|
||||
g_initialized = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int picnic_keygen(picnic_params_t parameters, picnic_publickey_t *pk,
|
||||
picnic_privatekey_t *sk) {
|
||||
ENSURE_LIBRARY_INITIALIZED();
|
||||
|
||||
if (!is_valid_params(parameters)) {
|
||||
printf("Invalid parameter set\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pk == NULL) {
|
||||
printf("public key is NULL\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sk == NULL) {
|
||||
printf("private key is NULL\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(pk, 0x00, sizeof(picnic_publickey_t));
|
||||
memset(sk, 0x00, sizeof(picnic_privatekey_t));
|
||||
|
||||
lowmcparams_t lowmcparams;
|
||||
int ret = picnicParamsToLowMCParams(parameters, &lowmcparams);
|
||||
if (ret != EXIT_SUCCESS) {
|
||||
fprintf(stderr, "Failed to initialize LowMC parameters\n");
|
||||
fflush(stderr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Generate a private key */
|
||||
sk->params = parameters;
|
||||
if (!picnic_random_bytes(sk->data, lowmcparams.stateSizeBytes)) {
|
||||
printf("Failed to generate private key\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Generate a random plaintext block */
|
||||
pk->params = parameters;
|
||||
if (!picnic_random_bytes(pk->pubInput, lowmcparams.stateSizeBytes)) {
|
||||
printf("Failed to generate private key\n");
|
||||
return -1;
|
||||
}
|
||||
sk->pk = pk;
|
||||
|
||||
/* Compute the ciphertext */
|
||||
LowMCEnc((uint32_t *) pk->pubInput, (uint32_t *) pk->ciphertext,
|
||||
(uint32_t *) sk->data, &lowmcparams);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int picnic_sign(picnic_privatekey_t *sk, const uint8_t *message, size_t message_len,
|
||||
uint8_t *signature, size_t *signature_len) {
|
||||
ENSURE_LIBRARY_INITIALIZED();
|
||||
|
||||
int ret;
|
||||
transform_t transform = get_transform(sk->params);
|
||||
signature_t *sig = (signature_t *) malloc(sizeof(signature_t));
|
||||
lowmcparams_t lowmcparams;
|
||||
|
||||
ret = picnicParamsToLowMCParams(sk->params, &lowmcparams);
|
||||
if (ret != EXIT_SUCCESS) {
|
||||
fprintf(stderr, "Failed to initialize LowMC parameters\n");
|
||||
fflush(stderr);
|
||||
freeSignature(sig);
|
||||
free(sig);
|
||||
return ret;
|
||||
}
|
||||
|
||||
allocateSignature(sig, &lowmcparams);
|
||||
if (sig == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = sign((uint32_t *) sk->data, (uint32_t *) sk->pk->ciphertext, (uint32_t *) sk->pk->pubInput, message,
|
||||
message_len, sig, transform, &lowmcparams);
|
||||
if (ret != EXIT_SUCCESS) {
|
||||
fprintf(stderr, "Failed to create signature\n");
|
||||
fflush(stderr);
|
||||
freeSignature(sig);
|
||||
free(sig);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// self-check for debugging, try to verify the sig we just created
|
||||
ret = verify(sig, (uint32_t*)sk->pk->ciphertext, (uint32_t*)sk->pk->pubInput, message, message_len, transform, lowmcparams);
|
||||
if (ret != EXIT_SUCCESS) {
|
||||
fprintf(stderr, "Failed self-test, signature didn't verify.\n");
|
||||
fflush(stderr);
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = serializeSignature(sig, signature, *signature_len, transform, &lowmcparams);
|
||||
if (ret == -1) {
|
||||
fprintf(stderr, "Failed to serialize signature\n");
|
||||
fflush(stderr);
|
||||
freeSignature(sig);
|
||||
free(sig);
|
||||
return -1;
|
||||
}
|
||||
*signature_len = ret;
|
||||
freeSignature(sig);
|
||||
free(sig);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t picnic_signature_size(picnic_params_t parameters) {
|
||||
|
||||
lowmcparams_t lowmcparams;
|
||||
transform_t transform = get_transform(parameters);
|
||||
|
||||
int ret = picnicParamsToLowMCParams(parameters, &lowmcparams);
|
||||
|
||||
if (ret != EXIT_SUCCESS) {
|
||||
return PICNIC_MAX_SIGNATURE_SIZE;
|
||||
}
|
||||
|
||||
switch (transform) {
|
||||
case TRANSFORM_FS:
|
||||
// This is the largest possible FS signature size and would result when no challenges are 0 -- which would require us to include stateSizeBytes for every ZKB round.
|
||||
return NUM_ZKB_ROUNDS * (SHA256_DIGEST_LENGTH + lowmcparams.stateSizeBytes + numBytes(3 * lowmcparams.numSboxes * lowmcparams.numRounds) + 2 * PRG_SEED_LENGTH) + numBytes(2 * NUM_ZKB_ROUNDS);
|
||||
case TRANSFORM_UR:
|
||||
return NUM_ZKB_ROUNDS * (SHA256_DIGEST_LENGTH + lowmcparams.stateSizeBytes + 2 * numBytes(3 * lowmcparams.numSboxes * lowmcparams.numRounds) + 3 * PRG_SEED_LENGTH) + numBytes(2 * NUM_ZKB_ROUNDS);
|
||||
default:
|
||||
return PICNIC_MAX_SIGNATURE_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
int picnic_verify(picnic_publickey_t *pk, const uint8_t *message, size_t message_len,
|
||||
const uint8_t *signature, size_t signature_len) {
|
||||
ENSURE_LIBRARY_INITIALIZED();
|
||||
int ret;
|
||||
|
||||
lowmcparams_t lowmcparams;
|
||||
ret = picnicParamsToLowMCParams(pk->params, &lowmcparams);
|
||||
if (ret != EXIT_SUCCESS) {
|
||||
fprintf(stderr, "Failed to initialize LowMC parameters\n");
|
||||
fflush(stderr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
transform_t transform = get_transform(pk->params);
|
||||
signature_t *sig = (signature_t *) malloc(sizeof(signature_t));
|
||||
allocateSignature(sig, &lowmcparams);
|
||||
if (sig == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = deserializeSignature(sig, signature, signature_len, transform, &lowmcparams);
|
||||
if (ret != EXIT_SUCCESS) {
|
||||
fprintf(stderr, "Failed to deserialize signature\n");
|
||||
fflush(stderr);
|
||||
freeSignature(sig);
|
||||
free(sig);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = verify(sig, (uint32_t *) pk->ciphertext,
|
||||
(uint32_t *) pk->pubInput, message, message_len, transform, &lowmcparams);
|
||||
if (ret != EXIT_SUCCESS) {
|
||||
/* Signature is invalid, or verify function failed */
|
||||
freeSignature(sig);
|
||||
free(sig);
|
||||
return -1;
|
||||
}
|
||||
|
||||
freeSignature(sig);
|
||||
free(sig);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Serialize public key */
|
||||
int picnic_write_public_key(const picnic_publickey_t *key, uint8_t *buf, size_t buflen) {
|
||||
if (key == NULL || buf == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t bytesRequired = 1 + sizeof(key->pubInput) + sizeof(key->ciphertext);
|
||||
if (buflen < bytesRequired || bytesRequired > INT_MAX) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf[0] = (uint8_t) key->params;
|
||||
|
||||
memcpy(buf + 1, key->pubInput, sizeof(key->pubInput));
|
||||
memcpy(buf + 1 + sizeof(key->pubInput), key->ciphertext, sizeof(key->ciphertext));
|
||||
|
||||
return (int) bytesRequired;
|
||||
}
|
||||
|
||||
int picnic_read_public_key(picnic_publickey_t *key, const uint8_t *buf, size_t buflen) {
|
||||
if (key == NULL || buf == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t bytesExpected = 1 + sizeof(key->pubInput) + sizeof(key->ciphertext);
|
||||
if (buflen < bytesExpected) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (is_valid_params(buf[0])) {
|
||||
key->params = buf[0];
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(key->pubInput, buf + 1, sizeof(key->pubInput));
|
||||
memcpy(key->ciphertext, buf + 1 + sizeof(key->pubInput), sizeof(key->ciphertext));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Serialize a private key. */
|
||||
int picnic_write_private_key(const picnic_privatekey_t *key, uint8_t *buf, size_t buflen) {
|
||||
if (key == NULL || buf == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t bytesRequired = 1 + sizeof(key->data);
|
||||
if (buflen < bytesRequired || bytesRequired > INT_MAX) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf[0] = (uint8_t) key->params;
|
||||
|
||||
memcpy(buf + 1, key->data, sizeof(key->data));
|
||||
|
||||
return (int) bytesRequired;
|
||||
}
|
||||
|
||||
/* De-serialize a private key. */
|
||||
int picnic_read_private_key(picnic_privatekey_t *key, const uint8_t *buf, size_t buflen, picnic_publickey_t *publickey) {
|
||||
if (key == NULL || buf == NULL || publickey == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t bytesExpected = 1 + sizeof(key->data);
|
||||
if (buflen < bytesExpected) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (is_valid_params(buf[0])) {
|
||||
key->params = buf[0];
|
||||
} else {
|
||||
/* Unsupported parameter set */
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (key->params != publickey->params) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(key->data, buf + 1, sizeof(key->data));
|
||||
key->pk = publickey;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check that a key pair is valid. */
|
||||
int picnic_validate_keypair(const picnic_privatekey_t *privatekey, const picnic_publickey_t *publickey) {
|
||||
ENSURE_LIBRARY_INITIALIZED();
|
||||
|
||||
lowmcparams_t lowmcparams;
|
||||
int ret;
|
||||
ret = picnicParamsToLowMCParams(publickey->params, &lowmcparams);
|
||||
if (ret != EXIT_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (privatekey == NULL || publickey == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (privatekey->params != publickey->params) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!is_valid_params(privatekey->params)) {
|
||||
fprintf(stderr, "Unsupported parameter set\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Re-compute the ciphertext and compare to the value in the public key. */
|
||||
uint8_t ciphertext[sizeof(publickey->ciphertext)];
|
||||
LowMCEnc((uint32_t *) publickey->pubInput, (uint32_t *) ciphertext, (uint32_t *) privatekey->data, &lowmcparams);
|
||||
if (memcmp(ciphertext, publickey->ciphertext, sizeof(ciphertext)) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,294 +0,0 @@
|
||||
/*! @file picnic.h
|
||||
* @brief Public API for the Picnic signature scheme.
|
||||
*
|
||||
* This file is part of the reference implementation of the Picnic and Fish
|
||||
* signature schemes, described in the paper:
|
||||
*
|
||||
* Post-Quantum Zero-Knowledge and Signatures from Symmetric-Key Primitives <br/>
|
||||
* Melissa Chase and David Derler and Steven Goldfeder and Claudio Orlandi and
|
||||
* Sebastian Ramacher and Christian Rechberger and Daniel Slamanig and Greg
|
||||
* Zaverucha <br/>
|
||||
* Cryptology ePrint Archive: Report 2017/279 <br/>
|
||||
* http://eprint.iacr.org/2017/279 <br/>
|
||||
*
|
||||
* The code is provided under the MIT license, see LICENSE for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
// Doxygen mainpage:
|
||||
/** @mainpage
|
||||
*
|
||||
* This is a reference implementation of the Picnic and Fish signature
|
||||
* schemes, described in the paper:
|
||||
*
|
||||
* Post-Quantum Zero-Knowledge and Signatures from Symmetric-Key Primitives <br/>
|
||||
* Melissa Chase and David Derler and Steven Goldfeder and Claudio Orlandi and
|
||||
* Sebastian Ramacher and Christian Rechberger and Daniel Slamanig and Greg
|
||||
* Zaverucha <br/>
|
||||
* Cryptology ePrint Archive: Report 2017/279 <br/>
|
||||
* http://eprint.iacr.org/2017/279 <br/>
|
||||
*
|
||||
* The library API is documented in \ref picnic.h.
|
||||
*
|
||||
* Authors: Steven Goldfeder and Greg Zaverucha <br/>
|
||||
* May 2017
|
||||
*/
|
||||
|
||||
#ifndef PICNIC_H
|
||||
#define PICNIC_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Maximum lengths in bytes */
|
||||
#define PICNIC_MAX_PUBLICKEY_SIZE 64 /**< Largest public key size, in bytes */
|
||||
#define PICNIC_MAX_PRIVATEKEY_SIZE 64 /**< Largest private key size, in bytes */
|
||||
#define PICNIC_MAX_SIGNATURE_SIZE 263786 /**< Largest signature size, in bytes */
|
||||
|
||||
/** Parameter sets */
|
||||
typedef enum picnic_params_t {
|
||||
PARAMETER_SET_INVALID = 0,
|
||||
LowMC_256_256_42_14_FS = 1, /**< LowMC with Fiat-Shamir balanced number of s-boxes (42) and rounds (14). */
|
||||
LowMC_256_256_42_14_UR = 2, /**< LowMC with Unruh balanced number of s-boxes (42) and rounds (14). */
|
||||
LowMC_256_256_1_316_FS = 3, /**< LowMC with Fiat-Shamir and a small number of s-boxes (1) with a large number of rounds (316). */
|
||||
LowMC_256_256_1_316_UR = 4, /**< LowMC with Unruh and a small number of s-boxes (1) with a large number of rounds (316). */
|
||||
LowMC_256_256_10_38_FS = 5, /**< LowMC with Fiat-Shamir balanced number of s-boxes (10) and rounds (38). */
|
||||
LowMC_256_256_10_38_UR = 6, /**< LowMC with Unruh balanced number of s-boxes (10) and rounds (38). */
|
||||
PARAMETER_SET_MAX_INDEX = 7
|
||||
} picnic_params_t;
|
||||
|
||||
/** Public key */
|
||||
typedef struct {
|
||||
picnic_params_t params; /**< The parameter set used with this public key. */
|
||||
uint8_t pubInput[PICNIC_MAX_PUBLICKEY_SIZE / 2]; /**< The input plaintext block to LowMC. */
|
||||
uint8_t ciphertext[PICNIC_MAX_PUBLICKEY_SIZE / 2]; /**< The encryption of pubInput under the private key. */
|
||||
} picnic_publickey_t;
|
||||
|
||||
/** Private key */
|
||||
typedef struct {
|
||||
picnic_params_t params; /**< The parameter set used with this private key. */
|
||||
uint8_t data[PICNIC_MAX_PRIVATEKEY_SIZE]; /**< The private key data. */
|
||||
picnic_publickey_t *pk; /**< The corresponding public key. */
|
||||
} picnic_privatekey_t;
|
||||
|
||||
/**
|
||||
* Library initialization.
|
||||
* Must be called before calling any of the other functions.
|
||||
*
|
||||
* Used to initialize OpenSSL and load LowMC constants and precomputed tables.
|
||||
* Initialization is specific to a parameter set.
|
||||
*
|
||||
* @param[in] params The parameter set that will be used.
|
||||
* @param[in] path (optional) a path where pre-computed data is stored. If
|
||||
* provided, must contain the trailing slash character(s) ('/' or '\\').
|
||||
* @param[in] flags (optional) If flags is 1, OpenSSL is not initialized. This
|
||||
* is useful if the application using picnic.h also uses OpenSSL, and does not
|
||||
* want the picnic_init to perform OpenSSL initialization. If flags is 1,
|
||||
* fucntions in picnic.h assume that OpenSSL has been initialized, and that the
|
||||
* SHA-256, and AES algorithms are available.
|
||||
*
|
||||
* @return 0 on success, nonzero for error
|
||||
*
|
||||
* @see picnic_shutdown()
|
||||
*/
|
||||
int picnic_init(picnic_params_t params, const char *path, unsigned int flags);
|
||||
|
||||
/**
|
||||
* Free resources allocated by picnic_init().
|
||||
*
|
||||
* @param[in] flags If flags is 1, the OpenSSL shutdown steps are not
|
||||
* performed. This is useful if the application using picnic.h also uses
|
||||
* OpenSSL, and does not want picnic_shutdown to shutdown OpenSSL.
|
||||
*
|
||||
* @see picnic_init()
|
||||
*/
|
||||
void picnic_shutdown(unsigned int flags);
|
||||
|
||||
/**
|
||||
* Get a string representation of the parameter set.
|
||||
*
|
||||
* @param parameters A parameter set
|
||||
*
|
||||
* @return A null-terminated string describing the parameter set.
|
||||
*/
|
||||
const char *picnic_get_param_name(picnic_params_t parameters);
|
||||
|
||||
/* Signature API */
|
||||
|
||||
/**
|
||||
* Key generation function.
|
||||
* Generates a public and private key pair, for the specified parameter set.
|
||||
*
|
||||
* @param[in] parameters The parameter set to use when generating a key.
|
||||
* @param[out] pk The new public key.
|
||||
* @param[out] sk The new private key.
|
||||
*
|
||||
* @return Returns 0 for success, or a nonzero value indicating an error.
|
||||
*
|
||||
* @see picnic_verify(), picnic_sign()
|
||||
*/
|
||||
int picnic_keygen(picnic_params_t parameters, picnic_publickey_t *pk,
|
||||
picnic_privatekey_t *sk);
|
||||
|
||||
/**
|
||||
* Signature function.
|
||||
* Signs a message with the given keypair.
|
||||
*
|
||||
* @param[in] sk The signer's private key.
|
||||
* @param[in] message The message to be signed.
|
||||
* @param[in] message_len The length of the message, in bytes.
|
||||
* @param[out] signature A buffer to hold the signature. The required size does
|
||||
* not exceed PICNIC_MAX_SIGNATURE_SIZE bytes. The specific max number of
|
||||
* bytes required for a parameter set is given by picnic_signature_size(). Note
|
||||
* that the length of each signature varies slightly, for the parameter sets
|
||||
* using the FS transform. The parameter sets using the Unruh transform have a
|
||||
* fixed length.
|
||||
* @param[in,out] signature_len The length of the provided signature buffer.
|
||||
* On success, this is set to the number of bytes written to the signature buffer.
|
||||
*
|
||||
* @return Returns 0 for success, or a nonzero value indicating an error.
|
||||
*
|
||||
* @see picnic_verify(), picnic_keygen(), picnic_signature_size()
|
||||
*/
|
||||
int picnic_sign(picnic_privatekey_t *sk, const uint8_t *message, size_t message_len,
|
||||
uint8_t *signature, size_t *signature_len);
|
||||
|
||||
/**
|
||||
* Get the number of bytes required to hold a signature.
|
||||
*
|
||||
* @param[in] parameters The parameter set of the signature.
|
||||
*
|
||||
* @return The number of bytes required to hold the signature created by
|
||||
* picnic_sign
|
||||
*
|
||||
* @note The size of signatures with parameter sets using the FS transform vary
|
||||
* slightly based on the random choices made during signing. This function
|
||||
* will return a suffcient number of bytes to hold a signature, and the
|
||||
* picnic_sign() function returns the exact number used for a given signature.
|
||||
*
|
||||
* @see picnic_sign()
|
||||
*/
|
||||
size_t picnic_signature_size(picnic_params_t parameters);
|
||||
|
||||
/**
|
||||
* Verification function.
|
||||
* Verifies a signature is valid with respect to a public key and message.
|
||||
*
|
||||
* @param[in] pk The signer's public key.
|
||||
* @param[in] message The message the signature purpotedly signs.
|
||||
* @param[in] message_len The length of the message, in bytes.
|
||||
* @param[in] signature The signature to verify.
|
||||
* @param[in] signature_len The length of the signature.
|
||||
*
|
||||
* @return Returns 0 for success, indicating a valid signature, or a nonzero
|
||||
* value indicating an error or an invalid signature.
|
||||
*
|
||||
* @see picnic_sign(), picnic_keygen()
|
||||
*/
|
||||
int picnic_verify(picnic_publickey_t *pk, const uint8_t *message, size_t message_len,
|
||||
const uint8_t *signature, size_t signature_len);
|
||||
|
||||
/**
|
||||
* Serialize a public key.
|
||||
*
|
||||
* @param[in] key The public key to serialize
|
||||
* @param[out] buf The buffer to write the key to.
|
||||
* Must have size at least PICNIC_MAX_PUBLICKEY_SIZE + 1 bytes.
|
||||
* @param[in] buflen The length of buf, in bytes
|
||||
*
|
||||
* @return Returns the number of bytes written.
|
||||
*/
|
||||
int picnic_write_public_key(const picnic_publickey_t *key, uint8_t *buf, size_t buflen);
|
||||
|
||||
/**
|
||||
* De-serialize a public key.
|
||||
*
|
||||
* @param[out] key The public key object to be populated.
|
||||
* @param[in] buf The buffer to read the public key from.
|
||||
* Must be at least PICNIC_MAX_PUBLICKEY_SIZE + 1 bytes.
|
||||
* @param[in] buflen The length of buf, in bytes
|
||||
*
|
||||
* @return Returns the number of bytes written.
|
||||
*/
|
||||
int picnic_read_public_key(picnic_publickey_t *key, const uint8_t *buf, size_t buflen);
|
||||
|
||||
/**
|
||||
* Serialize a private key.
|
||||
*
|
||||
* @param[in] key The private key to serialize
|
||||
* @param[out] buf The buffer to write the key to.
|
||||
* Must have size at least PICNIC_MAX_PRIVATEKEY_SIZE + 1 bytes.
|
||||
* @param[in] buflen The length of buf, in bytes
|
||||
*
|
||||
* @return Returns the number of bytes written.
|
||||
*/
|
||||
int picnic_write_private_key(const picnic_privatekey_t *key, uint8_t *buf, size_t buflen);
|
||||
|
||||
/**
|
||||
* De-serialize a private key.
|
||||
*
|
||||
* @param[out] key The private key object to be populated
|
||||
* @param[in] buf The buffer to read the key from.
|
||||
* Must have size at least PICNIC_MAX_PRIVATEKEY_SIZE + 1 bytes.
|
||||
* @param[in] buflen The length of buf, in bytes
|
||||
* @param[in] publickey The corresponding public key
|
||||
*
|
||||
* @return Returns 0 on success, or a nonzero value indicating an error.
|
||||
*/
|
||||
int picnic_read_private_key(picnic_privatekey_t *key, const uint8_t *buf, size_t buflen, picnic_publickey_t *publickey);
|
||||
|
||||
/**
|
||||
* Check that a key pair is valid.
|
||||
*
|
||||
* @param[in] privatekey The private key to check
|
||||
* @param[in] publickey The public key to check
|
||||
*
|
||||
* @return Returns 0 if the key pair is valid, or a nonzero value indicating an error
|
||||
*/
|
||||
int picnic_validate_keypair(const picnic_privatekey_t *privatekey, const picnic_publickey_t *publickey);
|
||||
|
||||
/**
|
||||
* picnic_random_bytes is used to generate random bytes in key generation and
|
||||
* signing. See the provided implementation "random_bytes_default_openssl"
|
||||
* based on OpenSSL's RAND_bytes.
|
||||
*
|
||||
* To use another RNG, make sure it has the same behavior as
|
||||
* random_bytes_default_openssl, and change the definition of
|
||||
* picnic_random_bytes.
|
||||
*/
|
||||
#define picnic_random_bytes random_bytes_default_openssl
|
||||
|
||||
/*
|
||||
* Note signing digests and streaming APIs
|
||||
*
|
||||
* Sometimes signaure APIs include "sign_digest" and "verify_digest" functions,
|
||||
* that allow the caller to hash the message themselves and provide the digest
|
||||
* to the sign/verify functions. Example use cases for these APIs are
|
||||
* applications that must sign very large messages, which don't fit in memory,
|
||||
* or that must signa long stream data. Applications that really need this
|
||||
* behavior could provide a digest to the sign/verify APIs provided here.
|
||||
* This is discouraged however, because the message will then be hashed twice,
|
||||
* the challenge used in the proof will be:
|
||||
* c = H(random, per-signature values || H(M))
|
||||
* instead of
|
||||
* c = H(random, per-signature values || M).
|
||||
* In the former case, a collision for H immediately gives a forgery (in the
|
||||
* GMR security game, but not necessarily in all applications). For this reason
|
||||
* the latter case arguably provides better security.
|
||||
*
|
||||
* A better way to implement a streaming API (not provided by this library)
|
||||
* would be to hash the first part of the challenge, then continue hashing the
|
||||
* message as a stream, then finish computing the signature.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*PICNIC_H*/
|
@ -1,25 +0,0 @@
|
||||
/*! @file platform.h
|
||||
* @brief Platform-specific defines.
|
||||
*
|
||||
* This file is part of the reference implementation of the Picnic and Fish
|
||||
* signature schemes, described in the paper:
|
||||
*
|
||||
* Post-Quantum Zero-Knowledge and Signatures from Symmetric-Key Primitives
|
||||
* Melissa Chase and David Derler and Steven Goldfeder and Claudio Orlandi and
|
||||
* Sebastian Ramacher and Christian Rechberger and Daniel Slamanig and Greg
|
||||
* Zaverucha
|
||||
* Cryptology ePrint Archive: Report 2017/279
|
||||
* http://eprint.iacr.org/2017/279
|
||||
*
|
||||
* The code is provided under the MIT license, see LICENSE for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
/* __FUNCTION__ generates a warning on Linux with -Wpedantic and newer versions
|
||||
* of GCC (tested with 5.4). So we use __func__ in all source and define it on
|
||||
* Windows.
|
||||
*/
|
||||
#if defined(__WINDOWS__)
|
||||
#define __func__ __FUNCTION__
|
||||
#endif
|
@ -1,212 +0,0 @@
|
||||
/*! @file preprocessMatrices.c
|
||||
* @brief Utility program to generate lookup tables used for fast
|
||||
* matrix multiplication. It outputs precomputed data to the data
|
||||
* directory.
|
||||
*
|
||||
* This file is part of the reference implementation of the Picnic and Fish
|
||||
* signature schemes, described in the paper:
|
||||
*
|
||||
* Post-Quantum Zero-Knowledge and Signatures from Symmetric-Key Primitives
|
||||
* Melissa Chase and David Derler and Steven Goldfeder and Claudio Orlandi and
|
||||
* Sebastian Ramacher and Christian Rechberger and Daniel Slamanig and Greg
|
||||
* Zaverucha
|
||||
* Cryptology ePrint Archive: Report 2017/279
|
||||
* http://eprint.iacr.org/2017/279
|
||||
*
|
||||
* The code is provided under the MIT license, see LICENSE for
|
||||
* more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "matrices_256_10_38.h"
|
||||
#include "matrices_256_42_14.h"
|
||||
#include "matrices_256_1_316.h"
|
||||
|
||||
#include "LowMCConstants.h"
|
||||
#include "LowMC.h"
|
||||
#include "picnic.h"
|
||||
#include <graycode.h>
|
||||
|
||||
#define t 8
|
||||
|
||||
/* Function in picnic.c not exposed in picnic.h */
|
||||
int picnicParamsToLowMCParams(picnic_params_t picnicParams, lowmcparams_t *lowmcParams);
|
||||
|
||||
//static code* grayCode;
|
||||
|
||||
void xor (uint32_t * in1, uint32_t *in2, uint32_t *out, uint32_t numWords) {
|
||||
for (uint32_t i = 0; i < numWords; i++) {
|
||||
out[i] = in1[i] ^ in2[i];
|
||||
}
|
||||
}
|
||||
|
||||
void rotate(uint32_t input[STATE_SIZE_BITS][STATE_SIZE_WORDS], uint32_t output[STATE_SIZE_BITS][STATE_SIZE_WORDS]) {
|
||||
for (int i = 0; i < STATE_SIZE_BITS; i++) {
|
||||
for (int j = 0; j < STATE_SIZE_BITS; j++) {
|
||||
setBitInWordArray(output[STATE_SIZE_BITS - 1 - i], STATE_SIZE_BITS - 1 - j,
|
||||
getBitFromWordArray(input[j], i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void generateTable(size_t numRounds, size_t stateBits, size_t stateWords,
|
||||
uint32_t matrices[numRounds][stateBits][stateWords],
|
||||
const char *matrixName, FILE *fp, FILE *fp2) {
|
||||
int *ord = malloc((1 << t) * sizeof(int));
|
||||
int *inc = malloc((1 << t) * sizeof(int));
|
||||
|
||||
m4ri_build_code(ord, inc, t);
|
||||
uint32_t rotatedMat[stateBits][stateWords];
|
||||
|
||||
uint32_t ****lookupTable = malloc(numRounds * sizeof(uint32_t ***));
|
||||
for (size_t i = 0; i < numRounds; i++) {
|
||||
lookupTable[i] = malloc(stateBits / t * sizeof(uint32_t **));
|
||||
for (size_t j = 0; j < stateBits / t; j++) {
|
||||
lookupTable[i][j] = malloc((1 << t) * sizeof(uint32_t *));
|
||||
for (int k = 0; k < (1 << t); k++) {
|
||||
lookupTable[i][j][k] = calloc(stateWords, sizeof(uint32_t));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < numRounds; i++) {
|
||||
rotate(matrices[i], rotatedMat);
|
||||
for (size_t j = 0; j < stateBits / t; j++) {
|
||||
memset(lookupTable[i][j][0], 0, stateWords * sizeof(uint32_t));
|
||||
for (int k = 1; k < 1 << t; k++) {
|
||||
xor(lookupTable[i][(stateBits / t) - 1 - j][ord[k - 1]],
|
||||
rotatedMat[(j * t) + (inc[k - 1])],
|
||||
lookupTable[i][(stateBits / t) - 1 - j][ord[k]],
|
||||
stateWords);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < numRounds; i++) {
|
||||
for (size_t j = 0; j < stateBits / t; j++) {
|
||||
for (size_t k = 0; k < (1 << t); k++) {
|
||||
fwrite(lookupTable[i][j][k], sizeof(uint32_t), stateWords, fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t i, j, k, l;
|
||||
|
||||
fprintf(fp2, "uint32_t %sLookupTable2 [%zd][%zd][%d][%zd] = {", matrixName,
|
||||
numRounds, stateBits / t, 1 << t, stateWords);
|
||||
for (i = 0; i < numRounds; i++) {
|
||||
fprintf(fp2, "{");
|
||||
for (j = 0; j < stateBits / t; j++) {
|
||||
fprintf(fp2, "{");
|
||||
for (k = 0; k < (1 << t); k++) {
|
||||
fprintf(fp2, "{");
|
||||
for (l = 0; l < stateWords; l++) {
|
||||
fprintf(fp2, "0x%x", lookupTable[i][j][k][l]);
|
||||
if (l != stateWords - 1) {
|
||||
fprintf(fp2, ",");
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(fp2, "}");
|
||||
if (k != (1 << t) - 1) {
|
||||
fprintf(fp2, ", \n");
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(fp2, "}");
|
||||
if (j != (stateBits / t) - 1) {
|
||||
fprintf(fp2, ", \n");
|
||||
}
|
||||
}
|
||||
fprintf(fp2, "}");
|
||||
if (i != numRounds - 1) {
|
||||
fprintf(fp2, ", \n");
|
||||
}
|
||||
}
|
||||
fprintf(fp2, "};\n");
|
||||
for (size_t i = 0; i < numRounds; i++) {
|
||||
for (size_t j = 0; j < stateBits / t; j++) {
|
||||
for (int k = 0; k < (1 << t); k++) {
|
||||
free(lookupTable[i][j][k]);
|
||||
}
|
||||
free(lookupTable[i][j]);
|
||||
}
|
||||
free(lookupTable[i]);
|
||||
}
|
||||
free(lookupTable);
|
||||
}
|
||||
|
||||
void writeRoundConstants(size_t numRounds, size_t stateWords, uint32_t roundConstants[numRounds][stateWords], FILE *fp) {
|
||||
for (size_t i = 0; i < numRounds; i++) {
|
||||
//for(int j = 0; j < stateWords;j++) {
|
||||
fwrite(&roundConstants[i], sizeof(uint32_t), stateWords, fp);
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
void generatelookupTables(picnic_params_t picnic_params) {
|
||||
lowmcparams_t params = {0};
|
||||
|
||||
picnicParamsToLowMCParams(picnic_params, ¶ms);
|
||||
|
||||
FILE *fp;
|
||||
char filename[100];
|
||||
sprintf(filename, DEFAULT_DATA_PATH "lookupTables_%d_%d_%d.bin", params.stateSizeBits, params.numSboxes, params.numRounds);
|
||||
char filename2[100];
|
||||
sprintf(filename2, DEFAULT_DATA_PATH "lookupTables_%d_%d_%d.h", params.stateSizeBits, params.numSboxes, params.numRounds);
|
||||
fp = fopen(filename, "wb");
|
||||
FILE *fp2;
|
||||
fp2 = fopen(filename2, "w+");
|
||||
|
||||
if (fp == NULL || fp2 == NULL) {
|
||||
printf("Failed to open '%s' or '%s' for writing\n", filename, filename2);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
switch (picnic_params) {
|
||||
case LowMC_256_256_42_14_FS:
|
||||
// fall through
|
||||
case LowMC_256_256_42_14_UR:
|
||||
generateTable(params.numRounds, params.stateSizeBits, params.stateSizeWords,
|
||||
linearMatrices_256_42_14, "linearMatrices", fp, fp2);
|
||||
generateTable(params.numRounds + 1, params.stateSizeBits, params.stateSizeWords,
|
||||
keyMatrices_256_42_14, "keyMatrices", fp, fp2);
|
||||
writeRoundConstants(params.numRounds, params.stateSizeWords, roundConstants256_42_14, fp);
|
||||
break;
|
||||
case LowMC_256_256_1_316_FS:
|
||||
// fall through
|
||||
case LowMC_256_256_1_316_UR:
|
||||
generateTable(params.numRounds, params.stateSizeBits, params.stateSizeWords,
|
||||
linearMatrices_256_1_316, "linearMatrices", fp, fp2);
|
||||
generateTable(params.numRounds + 1, params.stateSizeBits, params.stateSizeWords,
|
||||
keyMatrices_256_1_316, "keyMatrices", fp, fp2);
|
||||
writeRoundConstants(params.numRounds, params.stateSizeWords, roundConstants256_1_316, fp);
|
||||
|
||||
break;
|
||||
case LowMC_256_256_10_38_FS:
|
||||
// fall through
|
||||
case LowMC_256_256_10_38_UR:
|
||||
generateTable(params.numRounds, params.stateSizeBits, params.stateSizeWords,
|
||||
linearMatrices_256_10_38, "linearMatrices", fp, fp2);
|
||||
generateTable(params.numRounds + 1, params.stateSizeBits, params.stateSizeWords,
|
||||
keyMatrices_256_10_38, "keyMatrices", fp, fp2);
|
||||
writeRoundConstants(params.numRounds, params.stateSizeWords, roundConstants256_10_38, fp);
|
||||
|
||||
break;
|
||||
case PARAMETER_SET_INVALID:
|
||||
case PARAMETER_SET_MAX_INDEX:
|
||||
break;
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
int main() {
|
||||
for (picnic_params_t params = 1; params < PARAMETER_SET_MAX_INDEX; params++) {
|
||||
generatelookupTables(params);
|
||||
}
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Microsoft Corporation.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "test_util.h"
|
||||
|
||||
/* Platform-specific includes for timing code */
|
||||
#if OS_TARGET == OS_WIN
|
||||
#include <windows.h>
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
#if (OS_TARGET == OS_LINUX) && (TARGET == TARGET_ARM)
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
int64_t cpucycles(void) // Access system counter for benchmarking
|
||||
{
|
||||
#if (OS_TARGET == OS_WIN) && (TARGET == TARGET_AMD64 || TARGET == TARGET_x86)
|
||||
return __rdtsc();
|
||||
#elif (OS_TARGET == OS_WIN) && (TARGET == TARGET_ARM)
|
||||
return __rdpmccntr64();
|
||||
#elif (OS_TARGET == OS_LINUX) && (TARGET == TARGET_AMD64 || TARGET == TARGET_x86)
|
||||
unsigned int hi, lo;
|
||||
|
||||
asm volatile("rdtsc\n\t"
|
||||
: "=a"(lo), "=d"(hi));
|
||||
return ((int64_t) lo) | (((int64_t) hi) << 32);
|
||||
#elif (OS_TARGET == OS_LINUX) && (TARGET == TARGET_ARM)
|
||||
struct timespec time;
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &time);
|
||||
return (int64_t)(time.tv_sec * 1e9 + time.tv_nsec);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void bench_print(char *label, unsigned long long count,
|
||||
unsigned long long num_runs) // Print benchmarking result with the corresponding unit
|
||||
{
|
||||
char *unit;
|
||||
unsigned long long result = count / num_runs;
|
||||
|
||||
#if (OS_TARGET == OS_LINUX) && (TARGET == TARGET_ARM)
|
||||
if (result >= 1e7) {
|
||||
unit = "msec";
|
||||
result = result / 1e6;
|
||||
} else if (result >= 1e4) {
|
||||
unit = "usec";
|
||||
result = result / 1e3;
|
||||
} else {
|
||||
unit = "nsec";
|
||||
}
|
||||
#else
|
||||
unit = "cycles";
|
||||
#endif
|
||||
|
||||
printf(" %s runs in %*s %10lld %s\n", label, (int) (50 - strlen(label)),
|
||||
" ", result, unit);
|
||||
|
||||
return;
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Microsoft Corporation.
|
||||
*/
|
||||
|
||||
#define OS_WIN 1
|
||||
#define OS_LINUX 2
|
||||
|
||||
#define TARGET_AMD64 1
|
||||
|
||||
#if defined(__WINDOWS__)
|
||||
#define OS_TARGET OS_WIN
|
||||
#elif defined(__LINUX__)
|
||||
#define OS_TARGET OS_LINUX
|
||||
#else
|
||||
#error-- "Unknown OS"
|
||||
#endif
|
||||
|
||||
#ifdef __X64__
|
||||
#define TARGET TARGET_AMD64
|
||||
#else
|
||||
// Default to x64
|
||||
#define TARGET TARGET_AMD64
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Print benchmarking result with the corresponding unit
|
||||
void bench_print(char *label, unsigned long long count,
|
||||
unsigned long long num_runs);
|
||||
|
||||
// Access system counter for benchmarking
|
||||
int64_t cpucycles(void);
|
Loading…
x
Reference in New Issue
Block a user