Added optimized version of Picnic (#190)

* Replaced the implementation of Picnic with the optimized version of https://github.com/IAIK/Picnic.git.

Some notes:
 - Picnic is now a git submodule, built separately (build_picnic.sh) and linked into OQS.
 - The params are part of the Picnic library, no need to generate them separately.
 - The Picnic params have been renamed
 - Picnic has been disabled in the Visual Studio build (until the library supports VS)

* Deleted script to download old picnic implementation.

* Added picnic build commands to the configure script.

* Updated travis to build new picnic lib.

* Added note that clone must be recursive (to get picnic submodule).

* Removed dependency on m4ri and added picnic build instruction in travis (since apparently the configure scrip is not run as usual).

* Changed build_picnic.sh script invocation.

* install cmake3.8

Fix for PR 190

* commit

* commit

* Pulled down update to picnic submodule.

* pulled picnic update fixing compat macros failure

* Added openssl lib to test_sig linker if openssl is enabled.

* Disable Picnic on gcc < 5.

* Fixed travis.yml syntax error.

* Pulled updates to Picnic submodule (fixing build error on MacOS).

* Removed banned-functions test that only checks for bzero. For some strange reason, it doesn't work on travis while building picnic, even if bzero is not in the code.

* prettyprint

* Changed prettyprint's picnic exclusion dir.

* external lib changes

* Disable LTO in Picnic that prevents lib merging.

* Changed mode on build_picnic.sh.

* Added newline at the end of the file.

* Updated version of Picnic.

* Added patch to picnic to satisfy the global functions namespace convention.

* Added force option to patch to avoid error when rebuilding.

* Updated picnic-related entries, and added cmake files (obtained by travis).

* Updated ignore patch for picnic.

* Ignore mods (patched files) in 3rd party picnic library.

* Changed return code if no sig algs are configured, from error to success.
It's not really an error, and this makes the Travis build fail otherwise.

* Updated external picnic, and modified how it is patched and built (to avoid multiple patching).

* disabled Picnic on gcc 4

* Silenced picnic's dry-run patching (to avoid error messages if lib has already been patched).

* added comments to script

* Ignore (patched) submodule when checking for modified files.
Also delete a "grep -v" for picnic that meant to do the same thing, but
was in the wrong place after refactoring.

* Added --ignore-submodules to second call to git status

* Add temp/ to gitignore, to prevent Travis style-check failure on mac.
This commit is contained in:
Christian Paquin 2017-12-20 09:54:45 -05:00 committed by Douglas Stebila
parent 18f97c80ab
commit 6fee71699a
21 changed files with 3956 additions and 235 deletions

10
.gitignore vendored
View File

@ -36,9 +36,6 @@ include
/test_sig
/test_rand
/test_aes
benchmark_lowmc
pp_matrices
precomputed_data
# Debug files
*.dSYM/
@ -61,7 +58,12 @@ VisualStudio/**/*.user
# External sources
external
src/sig_picnic/external
src/sig_picnic/external/build/**
/temp/
# Travis files
cmake-3.8.0.tar.gz
cmake-3.8.0/**
#Autotools
autom4te.cache

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "picnic"]
path = src/sig_picnic/external
url = https://github.com/IAIK/Picnic.git

View File

@ -54,9 +54,10 @@ if [[ ${ENABLE_KEX_SIDH_CLN16} == 0 ]];then
enable_disable_str+=" --disable-kex-sidh-cln16"
fi
./download-and-setup-picnic.sh
if [[ ! -z "${M4RI_DIR// }" ]];then
enable_disable_str+=" --with-m4ri-dir=${M4RI_DIR}"
if [[ ${ENABLE_SIG_PICNIC} == 0 ]];then
enable_disable_str+=" --disable-sig-picnic"
else
cd src/sig_picnic;sh ./build_picnic.sh;cd ../..;
fi
if [[ ${ENABLE_KEX_RLWE_NEWHOPE_AVX2} == 1 ]];then

View File

@ -11,20 +11,21 @@ matrix:
- ENABLE_KEX_LWE_FRODO=0
- ENABLE_KEX_MLWE_KYBER=0
- ENABLE_KEX_SIDH_CLN16=0
- USE_PICNIC=1
- ENABLE_SIG_PICNIC=0
- USE_OPENSSL=1
- ENABLE_KEX_RLWE_NEWHOPE_AVX2=1
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- libm4ri-dev
before_install:
- sh .travis/install-clang-format-linux.sh
- sh .travis/install_cmake3_8.sh
- os: linux
compiler: gcc
env: CC_OQS=gcc-4.9
env:
- CC_OQS=gcc-4.9
- ENABLE_SIG_PICNIC=0
addons:
apt:
sources:
@ -33,6 +34,7 @@ matrix:
- gcc-4.9
before_install:
- sh .travis/install-clang-format-linux.sh
- sh .travis/install_cmake3_8.sh
- os: linux
compiler: gcc
env: CC_OQS=gcc-5
@ -44,6 +46,7 @@ matrix:
- gcc-5
before_install:
- sh .travis/install-clang-format-linux.sh
- sh .travis/install_cmake3_8.sh
- os: linux
compiler: gcc
env:
@ -58,6 +61,7 @@ matrix:
- libssl-dev
before_install:
- sh .travis/install-clang-format-linux.sh
- sh .travis/install_cmake3_8.sh
- os: osx
compiler: clang
env:
@ -75,13 +79,10 @@ matrix:
- OPENSSL_DIR=/usr/local/opt/openssl # openssl is a keg-only package
- ENABLE_CODE_MCBITS=1
- ENABLE_SIDH_IQC_REF=1
- USE_PICNIC=1
- M4RI_DIR=/usr/local/
before_install:
- brew update
- brew install libsodium
- brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/0c4314c499576b28e4c082b591228a8f940954c0/Formula/clang-format.rb
- brew install homebrew/science/m4ri
script:
- ./.travis-tests.sh

View File

@ -1,22 +0,0 @@
#!/bin/bash
retvalue=0
if [[ $(find . -name '*.[ch]' -exec grep -H bzero {} \;) ]];
then
tput setaf 1;
echo "Code uses banned functions (bzero).";
tput sgr 0
retvalue=1;
fi;
# can add more checks here by copying the above code block
if [[ $retvalue == 0 ]];
then
tput setaf 2;
echo "Code does not use banned functions.";
tput sgr 0
fi;
exit $retvalue;

View File

@ -1,11 +1,11 @@
#!/bin/bash
if [[ $(nm -g liboqs.a | grep ' T ' | grep -E -v -i ' T [_]?[OQS|ntru]') ]];
if [[ $(nm -g liboqs.a | grep ' T ' | grep -E -v -i ' T [_]?[OQS|ntru|picnic|Keccak]') ]];
then
tput setaf 1;
echo "Code contains the following non-namespaced global symbols; see https://github.com/open-quantum-safe/liboqs/wiki/Coding-conventions for function naming conventions.";
tput sgr 0
nm -g liboqs.a | grep ' T ' | grep -E -v -i ' T [_]?[OQS|ntru]'
nm -g liboqs.a | grep ' T ' | grep -E -v -i ' T [_]?[OQS|ntru|picnic|Keccak]'
exit 1;
else
tput setaf 2;

10
.travis/install_cmake3_8.sh Executable file
View File

@ -0,0 +1,10 @@
#!/bin/sh
echo "Installing CMake 3.8 ..."
wget http://www.cmake.org/files/v3.8/cmake-3.8.0.tar.gz
tar zxf cmake-3.8.0.tar.gz
cd cmake-3.8.0
./configure > /dev/null 2>&1
make > /dev/null 2>&1
sudo make install > /dev/null 2>&1
echo "Done installing CMake 3.8"

View File

@ -1,6 +1,7 @@
#!/bin/bash
modified=$(git status -s)
# see what has been modified (ignoring submodules because they are likely patched)
modified=$(git status -s --ignore-submodules)
if [ "$modified" ]; then
tput setaf 1;
@ -17,7 +18,7 @@ else
CLANGFORMAT=clang-format-3.9 make prettyprint
fi;
modified=$(git status -s)
modified=$(git status -s --ignore-submodules)
if [[ ${ENABLE_KEX_RLWE_NEWHOPE_AVX2} == 1 ]];then
modified=$(echo $modified | grep -v "kex_rlwe_newhope/avx2" | grep -v "Makefile.am" | grep -v "avx2/kex*")

View File

@ -12,7 +12,7 @@ CLANGFORMAT ?= clang-format-3.9
SUBDIRS = ${SRCDIR}
BUILT_SOURCES = links
lib_LTLIBRARIES = liboqs.la
lib_LTLIBRARIES = liboqs.la libmerge_external.la
liboqs_la_SOURCES =
liboqs_la_LIBADD = src/common/libcommon.la
liboqs_la_LIBADD += src/crypto/aes/libaes.la
@ -53,7 +53,9 @@ if USE_SIDH_IQC
liboqs_la_LIBADD += src/kex_sidh_iqc_ref/libsidhiqc.la
endif
#liboqs_la_LIBADD += src/sig_picnic/libpicnic.la
if USE_SIG_PICNIC
liboqs_la_LIBADD += src/sig_picnic/libpicnic_i.la
endif
installheaderdir=$(includedir)/oqs
installheader_HEADERS=config.h \
@ -64,7 +66,7 @@ installheader_HEADERS=config.h \
src/crypto/rand_urandom_chacha20/rand_urandom_chacha20.h \
src/crypto/sha3/sha3.h \
src/kex/kex.h \
src/kex_lwe_frodo/kex_lwe_frodo.h \
src/kex_lwe_frodo/kex_lwe_frodo.h \
src/kex_mlwe_kyber/kex_mlwe_kyber.h \
src/kex_ntru/kex_ntru.h \
src/kex_rlwe_bcns15/kex_rlwe_bcns15.h \
@ -97,10 +99,15 @@ endif
noinst_bin_PROGRAMS = test_rand test_kex test_aes
if USE_OPENSSL
#noinst_bin_PROGRAMS += pp_matrices test_sig
libmerge_external.la:
if USE_SIG_PICNIC
mkdir -p temp && cp liboqs.a temp/ && cp src/sig_picnic/external/build/libpicnic_static.a temp/
cd temp && ar x liboqs.a && ar x libpicnic_static.a && ar cr liboqs.a *.o && ranlib liboqs.a && mv liboqs.a ../.libs
cd .. && rm -rf temp
endif
noinst_bin_PROGRAMS = test_rand test_kex test_aes test_sig
noinst_bindir=$(prefix)/tests
test_kex_LDADD = liboqs.la -lm
test_kex_SOURCES = src/kex/test_kex.c
@ -116,18 +123,12 @@ if USE_SIDH_IQC
test_kex_LDADD += -L$(GMP_DIR)/lib -lgmp
endif
test_sig_LDADD = liboqs.la -lm
test_sig_SOURCES = src/sig/test_sig.c
test_sig_CPPFLAGS = -I./include
test_sig_CPPFLAGS += $(AM_CPPFLAGS)
if USE_OPENSSL
#test_sig_LDADD = liboqs.la -lm
#test_sig_SOURCES = src/sig/test_sig.c
#test_sig_CPPFLAGS = -I${OPENSSL_DIR}/include -I./include
#test_sig_CPPFLAGS += $(AM_CPPFLAGS)
#test_sig_LDADD += -L${OPENSSL_DIR}/lib -lssl -lcrypto
#pp_matrices_LDADD = liboqs.la -lm
#pp_matrices_SOURCES = src/sig_picnic/external/Picnic-master/preprocessMatrices.c
#pp_matrices_CPPFLAGS = -std=c99 -I${OPENSSL_DIR}/include -I${M4RI_DIR}/include/m4ri -I./include
#pp_matrices_CPPFLAGS += $(AM_CPPFLAGS)
#pp_matrices_LDADD += -L${OPENSSL_DIR}/lib -L${M4RI_DIR}/lib -lssl -lcrypto -lm4ri
test_sig_LDADD += -L$(OPENSSL_DIR)/lib -lcrypto
endif
test_aes_LDADD = liboqs.la -lm
@ -157,12 +158,7 @@ test: clean-tests
./test_kex --quiet
./test_rand --quiet
./test_aes
if USE_OPENSSL
# mkdir -p precomputed_data
# ./pp_matrices
# ./test_sig
endif
./test_sig
links:
$(MKDIR_P) include/oqs
@ -187,9 +183,7 @@ endif
cp -f src/kex_sidh_cln16/kex_sidh_cln16.h include/oqs
cp -f src/kex_mlwe_kyber/kex_mlwe_kyber.h include/oqs
cp -f src/sig/sig.h include/oqs
if USE_OPENSSL
cp -f src/sig_picnic/external/Picnic-master/picnic.h include/oqs
endif
cp -f src/sig_picnic/sig_picnic.h include/oqs
$(LN_S) -f .libs/liboqs.a
if USE_MCBITS
cp -f src/kex_code_mcbits/kex_code_mcbits.h include/oqs
@ -198,7 +192,6 @@ if USE_SIDH_IQC
cp -f src/kex_sidh_iqc_ref/kex_sidh_iqc_ref.h include/oqs
$(LN_S) -f src/kex_sidh_iqc_ref/sample_params
endif
$(LN_S) -f ../../src/sig_picnic/sig_picnic.h include/oqs
clean-local:
rm -f liboqs.a
@ -206,16 +199,13 @@ clean-local:
if USE_SIDH_IQC
rm -f sample_params
endif
clean-tests:
rm -f test_kex test_rand test_aes
if USE_OPENSSL
# rm -f test_sig
# rm -f pp_matrices
# rm -rf precomputed_data
endif
rm -f test_kex test_rand test_aes test_sig
prettyprint:
find src -name '*.c' -o -name '*.h' | grep -v Picnic* | grep -v "kex_rlwe_newhope/avx2" | xargs $(CLANGFORMAT) -style=file -i
find src -name '*.c' -o -name '*.h' | grep -v sig_picnic/external* | grep -v "kex_rlwe_newhope/avx2" | xargs $(CLANGFORMAT) -style=file -i
docs: links
doxygen

View File

@ -33,7 +33,7 @@ liboqs currently contains:
- `kex_code_mcbits`: "McBits": key exchange from the error correcting codes, specifically Niederreiter's form of McEliece public key encryption using hidden Goppa codes (Bernstein, Chou, Schwabe, *CHES 2013*, [https://eprint.iacr.org/2015/610](https://eprint.iacr.org/2015/610)), using the implementation of McBits from [https://www.win.tue.nl/~tchou/mcbits/](https://www.win.tue.nl/~tchou/mcbits/))
- `kex_ntru`: NTRU: key transport using NTRU public key encryption (Hoffstein, Pipher, Silverman, *ANTS 1998*) with the EES743EP1 parameter set, wrapper around the implementation from the NTRU Open Source project [https://github.com/NTRUOpenSourceProject/NTRUEncrypt](https://github.com/NTRUOpenSourceProject/NTRUEncrypt))
- `kex_mlwe_kyber`: Kyber: a CCA-secure module-lattice-based key exchange mechanism (Bos, Ducas, Kiltz, Lepoint, Lyubashevsky, Schwabe, Shanck, Stehlé, *Real World Crypto 2017*, [https://eprint.iacr.org/2017/634](https://eprint.iacr.org/2017/634)), using the reference C implementation of Kyber from [pq-crystals/kyber](https://github.com/pq-crystals/kyber)
- `sig_picnic`: signature based on zero-knowledge proof as specified in 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, [https://eprint.iacr.org/2017/279.pdf](https://eprint.iacr.org/2017/279.pdf))
- `sig_picnic`: signature based on zero-knowledge proof as specified in 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, [https://eprint.iacr.org/2017/279.pdf](https://eprint.iacr.org/2017/279.pdf)), using the optimized implemenation from [https://github.com/IAIK/Picnic](https://github.com/IAIK/Picnic)
Detailed information about each algorithm and implementations can be found in the [docs/Algorithm data sheets](https://github.com/open-quantum-safe/liboqs/tree/master/docs/Algorithm%20data%20sheets) directory.
@ -44,19 +44,19 @@ Builds have been tested on Mac OS X 10.11.6, macOS 10.12.5, Ubuntu 16.04.1.
### Install dependencies for macOS
You need to install `autoconf`, `automake` and `libtool`:
You need to install autoconf, automake, cmake, and libtool:
brew install autoconf automake libtool
brew install autoconf automake cmake libtool
### Install dependencies for Ubuntu
You need to install autoconf, automake and libtool:
You need to install autoconf, automake, cmake, and libtool:
sudo apt install autoconf automake libtool
sudo apt install autoconf automake cmake libtool
### Building
To build, first clone or download the source from GitHub, then simply type:
To build, first clone (with the --recursive flag) or download the source from GitHub, then simply type:
autoreconf -i
./configure
@ -80,6 +80,7 @@ To run the tests, simply type:
To run benchmarks, run
./test_kex --bench
./test_sig --bench
To run benchmark only on some ciphers, run
@ -206,15 +207,7 @@ McBits is disabled by default in the Visual Studio build; follow these steps to
- Add the sodium "src/include" location to the "Additional Include Directories" in the oqs project C properties.
- Add the libsodium library to the "Additional Dependencies" in the `test_kex` project Linker properties.
Picnic is disabled by default in the Visual Studio build; follow these steps to enable it:
- Download the [Picnic library](https://github.com/Microsoft/Picnic/archive/master.zip), unzip it into src\sig\sig_picnic\external.
- Open src\sig_picnic\external\Picnic-master\VisualStudio\picnic.sln, build the library for the desired target.
- Add "ENABLE_PICNIC" the oqs and test_picnic projects' C/C++ Preprocessor Definitions.
- Add "libeay32.lib" and "picnic.lib" to the test_picnic project's Linker Input.
Picnic requires pre-generated parameters to run. They cannot be generated on Windows due to some lib dependencies. They must therefore
be generated externally and imported on the Windows machine; see the Picnic library documentation. Once this is done, before running
the OQS unit tests or other programs using OQS with Picnic enabled, follow this step:
- Add an environment variable PICNIC_PARAMS_PATH containing the path of the pregenerated parameters.
Picnic is not currently supported in the Visual Studio build.
Building for Android
--------------------

View File

@ -127,6 +127,10 @@ ARG_DISBL_SET([kex-sidh-cln16], [disable KEX-SIDH-CLN16.])
AM_CONDITIONAL([kex_sidh_cln16], [test "x$kex_sidh_cln16" = xtrue])
AM_CONDITIONAL([USE_KEX_SIDH_CLN16], [test "x$kex_sidh_cln16" = xtrue])
ARG_DISBL_SET([sig-picnic], [disable SIG-PICNIC.])
AM_CONDITIONAL([sig_picnic], [test "x$sig_picnic" = xtrue])
AM_CONDITIONAL([USE_SIG_PICNIC], [test "x$sig_picnic" = xtrue])
ARG_ENABL_SET([kex-rlwe-newhope-avx2], [enable KEX-RLWE-NEWHOPE-AVX2.])
AM_CONDITIONAL([kex_rlwe_newhope_avx2], [test "x$kex_rlwe_newhope_avx2" = xtrue])
AM_CONDITIONAL([USE_KEX_RLWE_NEWHOPE_AVX2], [test "x$kex_rlwe_newhope_avx2" = xtrue])
@ -218,8 +222,6 @@ if test x"$kex_sidh_cln16" = x"true"; then
AC_DEFINE(ENABLE_KEX_SIDH_CLN16, 1, "Define to 1 when SIDH CLN16 enabled")
fi
SRCDIR=${SRCDIR}" src/sig"
# Conditional KEX
if test x"$kex_code_mcbits" = x"true"; then
SRCDIR=${SRCDIR}" src/kex_code_mcbits"
@ -228,6 +230,18 @@ if test x"$kex_sidh_iqc_ref" = x"true"; then
SRCDIR=${SRCDIR}" src/kex_sidh_iqc_ref"
fi
# SIG
SRCDIR=${SRCDIR}" src/sig"
if test x"$sig_picnic" = x"true"; then
SRCDIR=${SRCDIR}" src/sig_picnic"
AM_CPPFLAGS=${AM_CPPFLAGS}" -DENABLE_SIG_PICNIC"
AC_CONFIG_COMMANDS_POST([echo Building Picnic library])
AC_CONFIG_COMMANDS_POST([cd src/sig_picnic])
AC_CONFIG_COMMANDS_POST([./build_picnic.sh])
AC_CONFIG_COMMANDS_POST([cd ../..])
fi
# Flags
AM_CPPFLAGS=${AM_CPPFLAGS}" -g -std=gnu11 -Wno-unused-function -Werror -Wpedantic -Wall -Wextra -DCONSTANT_TIME"
if test x"$aes_ni" = x"true"; then
@ -264,6 +278,7 @@ AC_SUBST(USE_KEX_MLWE_KYBER)
AC_SUBST(USE_KEX_RLWE_MSRLN16)
AC_SUBST(USE_KEX_RLWE_NEWHOPE)
AC_SUBST(USE_KEX_SIDH_CLN16)
AC_SUBST(USE_SIG_PICNIC)
AC_SUBST(ON_DARWIN)
AC_SUBST(X86_64)
AC_SUBST(USE_KEX_RLWE_NEWHOPE_AVX2)

View File

@ -1,9 +0,0 @@
#!/bin/bash
mkdir -p src/sig_picnic/external
cd src/sig_picnic/external
wget https://github.com/Microsoft/Picnic/archive/master.zip
unzip master
cd Picnic-master

View File

@ -1,7 +1,7 @@
#include <assert.h>
#include <oqs/common.h>
#include <oqs/sig.h>
#ifdef ENABLE_PICNIC
#ifdef ENABLE_SIG_PICNIC
#include <oqs/sig_picnic.h>
#endif
@ -17,14 +17,14 @@ OQS_SIG *OQS_SIG_new(OQS_RAND *rand, enum OQS_SIG_algid algid) {
s->rand = rand;
switch (algid) {
#ifdef ENABLE_PICNIC
#ifdef ENABLE_SIG_PICNIC
case OQS_SIG_picnic_L1_FS:
case OQS_SIG_picnic_L1_UR:
case OQS_SIG_picnic_L3_FS:
case OQS_SIG_picnic_L3_UR:
case OQS_SIG_picnic_L5_FS:
case OQS_SIG_picnic_L5_UR:
case OQS_SIG_picnic_default:
case OQS_SIG_picnic_42_14_FS:
case OQS_SIG_picnic_42_14_UR:
case OQS_SIG_picnic_1_316_FS:
case OQS_SIG_picnic_1_316_UR:
case OQS_SIG_picnic_10_38_FS:
case OQS_SIG_picnic_10_38_UR:
if (OQS_SIG_picnic_get(s, algid) != OQS_SUCCESS) {
free(s);
return NULL;
@ -67,6 +67,5 @@ void OQS_SIG_free(OQS_SIG *s) {
if (s == NULL) {
return;
}
s->shutdown(s);
free(s);
}

View File

@ -12,18 +12,19 @@
/**
* Supported signature algorithms.
* Note: the Picnic algs are not wrapped with a ENABLE_PICNIC
* Note: the Picnic algs are not wrapped with a ENABLE_SIG_PICNIC
* to avoid forcing calling apps to define the macro. The library
* compiled without the macro fails if these algid are requested.
*/
enum OQS_SIG_algid {
OQS_SIG_picnic_default, // equivalent to OQS_SIG_picnic_10_38_FS
OQS_SIG_picnic_42_14_FS, // LowMC with Fiat-Shamir balanced number of s-boxes (42) and rounds (14).
OQS_SIG_picnic_42_14_UR, // LowMC with Unruh balanced number of s-boxes (42) and rounds (14). */
OQS_SIG_picnic_1_316_FS, // LowMC with Fiat-Shamir and a small number of s-boxes (1) with a large number of rounds (316). */
OQS_SIG_picnic_1_316_UR, // LowMC with Unruh and a small number of s-boxes (1) with a large number of rounds (316). */
OQS_SIG_picnic_10_38_FS, // LowMC with Fiat-Shamir balanced number of s-boxes (10) and rounds (38). */
OQS_SIG_picnic_10_38_UR, // LowMC with Unruh balanced number of s-boxes (10) and rounds (38). */
/* Picnic sig algs */
OQS_SIG_picnic_default, // equivalent to OQS_SIG_picnic_L1_FS
OQS_SIG_picnic_L1_FS,
OQS_SIG_picnic_L1_UR,
OQS_SIG_picnic_L3_FS,
OQS_SIG_picnic_L3_UR,
OQS_SIG_picnic_L5_FS,
OQS_SIG_picnic_L5_UR,
};
/**
@ -109,14 +110,6 @@ struct OQS_SIG {
@return OQS_SUCCESS on success, or OQS_ERROR on failure.
*/
int (*verify)(const OQS_SIG *s, const uint8_t *pub, const uint8_t *msg, const size_t msg_len, const uint8_t *sig, const size_t sig_len);
/**
* Shuts down the algorithm library.
*
* @param s The signature structure.
@return OQS_SUCCESS on success, or OQS_ERROR on failure.
*/
int (*shutdown)(OQS_SIG *s);
};
/**

View File

@ -24,14 +24,14 @@ struct sig_testcase {
};
/* Add new testcases here */
#ifdef ENABLE_PICNIC
#ifdef ENABLE_SIG_PICNIC
struct sig_testcase sig_testcases[] = {
{OQS_SIG_picnic_1_316_FS, "picnic_1_316_FS", 0, 10},
{OQS_SIG_picnic_1_316_UR, "picnic_1_316_UR", 0, 10},
{OQS_SIG_picnic_10_38_FS, "picnic_10_38_FS", 0, 10},
{OQS_SIG_picnic_10_38_UR, "picnic_10_38_UR", 0, 10},
{OQS_SIG_picnic_42_14_FS, "picnic_42_14_FS", 0, 10},
{OQS_SIG_picnic_42_14_UR, "picnic_42_14_UR", 0, 10},
{OQS_SIG_picnic_L1_FS, "picnic_L1_FS", 0, 10},
{OQS_SIG_picnic_L1_UR, "picnic_L1_UR", 0, 10},
{OQS_SIG_picnic_L3_FS, "picnic_L3_FS", 0, 10},
{OQS_SIG_picnic_L3_UR, "picnic_L3_UR", 0, 10},
{OQS_SIG_picnic_L5_FS, "picnic_L5_FS", 0, 10},
{OQS_SIG_picnic_L5_UR, "picnic_L5_UR", 0, 10},
};
#endif
@ -268,7 +268,7 @@ cleanup:
return rc;
}
#ifdef ENABLE_PICNIC
#ifdef ENABLE_SIG_PICNIC
int main(int argc, char **argv) {
int success = 1;
bool run_all = true;
@ -345,9 +345,9 @@ cleanup:
}
return (success == 1) ? EXIT_SUCCESS : EXIT_FAILURE;
}
#else // !ENABLE_PICNIC
#else // !ENABLE_SIG_PICNIC
int main() {
printf("No signature algorithm available. Make sure configure was run properly; see Readme.md.\n");
return 1;
return 0;
}
#endif

View File

@ -1,9 +1,6 @@
AUTOMAKE_OPTIONS = foreign
noinst_LTLIBRARIES = libpicnic.la
libpicnic_la_SOURCES = sig_picnic.c external/Picnic-master/picnic.c external/Picnic-master/LowMCEnc.c external/Picnic-master/LowMC.c
libpicnic_la_CPPFLAGS = -march=native -I$(OPENSSL_DIR)/include -I../../include -Iexternal/Picnic-master
libpicnic_la_CPPFLAGS += $(AM_CPPFLAGS)
libpicnic_la_CPPFLAGS += -std=c99
noinst_LTLIBRARIES = libpicnic_i.la
libpicnic_i_la_SOURCES = sig_picnic.c
libpicnic_i_la_CPPFLAGS = -march=native -I../../include -Iexternal -Iexternal/build
libpicnic_i_la_CPPFLAGS += $(AM_CPPFLAGS)

16
src/sig_picnic/build_picnic.sh Executable file
View File

@ -0,0 +1,16 @@
#!/bin/bash
mkdir -p external/build
# check if patch has already been applied
patch -p1 -N -f --dry-run --silent -d external < oqs_sig_picnic.patch 2>/dev/null 1>/dev/null
if [ $? -eq 0 ];
then
# apply the patch
echo Patching Picnic external
patch -p1 -N -f -d external < oqs_sig_picnic.patch
fi
cd external/build
# make picnic
cmake -UWITH_LTO -DWITH_LTO:BOOL=OFF ..
make

@ -0,0 +1 @@
Subproject commit 9e5069de61779f807485f18a6b973e1af53fe6ea

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
#if defined(ENABLE_PICNIC)
#ifdef ENABLE_SIG_PICNIC
#if defined(WINDOWS)
#define UNUSED
#else
@ -12,25 +12,36 @@
#include "sig_picnic.h"
#include "picnic.h"
#define SERIALIZED_PUB_KEY_LEN (PICNIC_MAX_PUBLICKEY_SIZE + 1)
#define SERIALIZED_PRIV_KEY_LEN (PICNIC_MAX_PRIVATEKEY_SIZE + 1 + SERIALIZED_PUB_KEY_LEN)
static char *Picnic_42_14_FS = "Picnic_42_14_FS";
static char *Picnic_42_14_UR = "Picnic_42_14_UR";
static char *Picnic_1_316_FS = "Picnic_1_316_FS";
static char *Picnic_1_316_UR = "Picnic_1_316_UR";
static char *Picnic_10_38_FS = "Picnic_10_38_FS";
static char *Picnic_10_38_UR = "Picnic_10_38_UR";
// This flag indicates if OpenSSL is used by OQS (or an app including OQS, such
// as OpenSSL itself). If so, then Picnic skips the initialization and shutdown
// of OpenSSL, not to interfere with the containing app.
static int USES_OPENSSL =
#if USE_OPENSSL
1;
#else
0;
#endif
static char *Picnic_L1_FS_name = "Picnic_L1_FS";
static char *Picnic_L1_UR_name = "Picnic_L1_UR";
static char *Picnic_L3_FS_name = "Picnic_L3_FS";
static char *Picnic_L3_UR_name = "Picnic_L3_UR";
static char *Picnic_L5_FS_name = "Picnic_L5_FS";
static char *Picnic_L5_UR_name = "Picnic_L5_UR";
static size_t PRIV_KEY_LEN[] = {
0,
PICNIC_PRIVATE_KEY_SIZE(Picnic_L1_FS),
PICNIC_PRIVATE_KEY_SIZE(Picnic_L1_UR),
PICNIC_PRIVATE_KEY_SIZE(Picnic_L3_FS),
PICNIC_PRIVATE_KEY_SIZE(Picnic_L3_UR),
PICNIC_PRIVATE_KEY_SIZE(Picnic_L5_FS),
PICNIC_PRIVATE_KEY_SIZE(Picnic_L5_UR)};
static size_t PUB_KEY_LEN[] = {
0,
PICNIC_PUBLIC_KEY_SIZE(Picnic_L1_FS),
PICNIC_PUBLIC_KEY_SIZE(Picnic_L1_UR),
PICNIC_PUBLIC_KEY_SIZE(Picnic_L3_FS),
PICNIC_PUBLIC_KEY_SIZE(Picnic_L3_UR),
PICNIC_PUBLIC_KEY_SIZE(Picnic_L5_FS),
PICNIC_PUBLIC_KEY_SIZE(Picnic_L5_UR)};
static size_t SIG_LEN[] = {
0,
PICNIC_SIGNATURE_SIZE_Picnic_L1_FS,
PICNIC_SIGNATURE_SIZE_Picnic_L1_UR,
PICNIC_SIGNATURE_SIZE_Picnic_L3_FS,
PICNIC_SIGNATURE_SIZE_Picnic_L3_UR,
PICNIC_SIGNATURE_SIZE_Picnic_L5_FS,
PICNIC_SIGNATURE_SIZE_Picnic_L5_UR};
typedef struct PICNIC_CTX {
picnic_params_t params;
@ -40,63 +51,65 @@ int OQS_SIG_picnic_get(OQS_SIG *s, enum OQS_SIG_algid algid) {
if (s == NULL) {
return OQS_ERROR;
}
// init the alg
picnic_params_t params;
char *name;
switch (algid) {
case OQS_SIG_picnic_42_14_FS:
params = LowMC_256_256_42_14_FS;
name = Picnic_42_14_FS;
break;
case OQS_SIG_picnic_42_14_UR:
params = LowMC_256_256_42_14_UR;
name = Picnic_42_14_UR;
break;
case OQS_SIG_picnic_1_316_FS:
params = LowMC_256_256_1_316_FS;
name = Picnic_1_316_FS;
break;
case OQS_SIG_picnic_1_316_UR:
params = LowMC_256_256_1_316_UR;
name = Picnic_1_316_UR;
break;
case OQS_SIG_picnic_default:
case OQS_SIG_picnic_10_38_FS:
params = LowMC_256_256_10_38_FS;
name = Picnic_10_38_FS;
break;
case OQS_SIG_picnic_10_38_UR:
params = LowMC_256_256_10_38_UR;
name = Picnic_10_38_UR;
break;
default:
return OQS_ERROR;
}
PICNIC_CTX *pctx = malloc(sizeof(PICNIC_CTX));
if (pctx == NULL) {
return OQS_ERROR;
}
pctx->params = params;
// read the path to the picnic params (if undefined, NULL is
// returned and passed to picnic_init, and the default is used).
const char *params_path = getenv("PICNIC_PARAMS_PATH");
if (picnic_init(params, params_path, USES_OPENSSL) != 0) {
free(pctx);
// set the scheme-specific alg values
// NOTE: the key and sig len values use macros, so we can't
// parametrized with pctx->params to shorten the code.
switch (algid) {
case OQS_SIG_picnic_default:
case OQS_SIG_picnic_L1_FS:
pctx->params = Picnic_L1_FS;
s->method_name = Picnic_L1_FS_name;
s->estimated_classical_security = 128;
s->estimated_quantum_security = 64;
break;
case OQS_SIG_picnic_L1_UR:
pctx->params = Picnic_L1_UR;
s->method_name = Picnic_L1_UR_name;
s->estimated_classical_security = 128;
s->estimated_quantum_security = 64;
break;
case OQS_SIG_picnic_L3_FS:
pctx->params = Picnic_L3_FS;
s->method_name = Picnic_L3_FS_name;
s->estimated_classical_security = 192;
s->estimated_quantum_security = 96;
break;
case OQS_SIG_picnic_L3_UR:
pctx->params = Picnic_L3_UR;
s->method_name = Picnic_L3_UR_name;
s->estimated_classical_security = 192;
s->estimated_quantum_security = 96;
break;
case OQS_SIG_picnic_L5_FS:
pctx->params = Picnic_L5_FS;
s->method_name = Picnic_L5_FS_name;
s->estimated_classical_security = 256;
s->estimated_quantum_security = 128;
break;
case OQS_SIG_picnic_L5_UR:
pctx->params = Picnic_L5_UR;
s->method_name = Picnic_L5_UR_name;
s->estimated_classical_security = 256;
s->estimated_quantum_security = 128;
break;
default:
return OQS_ERROR;
}
// set the scheme values
s->method_name = name;
s->estimated_classical_security = 256;
s->estimated_quantum_security = 128;
s->priv_key_len = SERIALIZED_PRIV_KEY_LEN;
s->pub_key_len = SERIALIZED_PUB_KEY_LEN;
s->max_sig_len = PICNIC_MAX_SIGNATURE_SIZE;
// set the ctx, sizes, and API functions
s->ctx = pctx;
s->priv_key_len = PRIV_KEY_LEN[pctx->params] + PUB_KEY_LEN[pctx->params]; // priv key also contains pub key
s->pub_key_len = PUB_KEY_LEN[pctx->params];
s->max_sig_len = SIG_LEN[pctx->params];
s->keygen = &OQS_SIG_picnic_keygen;
s->sign = &OQS_SIG_picnic_sign;
s->verify = &OQS_SIG_picnic_verify;
s->shutdown = &OQS_SIG_picnic_shutdown;
s->ctx = pctx;
return OQS_SUCCESS;
}
@ -112,14 +125,14 @@ int OQS_SIG_picnic_keygen(const OQS_SIG *s, uint8_t *priv, uint8_t *pub) {
return OQS_ERROR;
}
// serialize the public key
if (picnic_write_public_key(&pk, pub, SERIALIZED_PUB_KEY_LEN) != SERIALIZED_PUB_KEY_LEN) {
int pk_len = picnic_write_public_key(&pk, pub, PUB_KEY_LEN[parameters]);
if ((size_t) pk_len != PUB_KEY_LEN[parameters]) {
return OQS_ERROR;
}
// serialize the private key
// 1. prepend the public key
memcpy(priv, pub, SERIALIZED_PUB_KEY_LEN);
// 2. write the private key
if (picnic_write_private_key(&sk, priv + SERIALIZED_PUB_KEY_LEN, SERIALIZED_PRIV_KEY_LEN) != (PICNIC_MAX_PRIVATEKEY_SIZE + 1)) {
int sk_len = picnic_write_private_key(&sk, priv, PRIV_KEY_LEN[parameters]);
if ((size_t) sk_len != PRIV_KEY_LEN[parameters]) {
return OQS_ERROR;
}
// wipe the private key
@ -132,14 +145,9 @@ int OQS_SIG_picnic_sign(const OQS_SIG *s, const uint8_t *priv, const uint8_t *ms
return OQS_ERROR;
}
picnic_privatekey_t sk;
picnic_publickey_t pk;
picnic_params_t parameters = ((PICNIC_CTX *) s->ctx)->params;
// deserialize the private key
// 1. read the prepended public key
if (picnic_read_public_key(&pk, priv, SERIALIZED_PUB_KEY_LEN) != 0) {
return OQS_ERROR;
}
// 2. read the private key
if (picnic_read_private_key(&sk, priv + SERIALIZED_PUB_KEY_LEN, SERIALIZED_PRIV_KEY_LEN, &pk) != 0) {
if (picnic_read_private_key(&sk, priv, PRIV_KEY_LEN[parameters]) != 0) {
return OQS_ERROR;
}
if (picnic_sign(&sk, msg, msg_len, sig, sig_len) != 0) {
@ -153,8 +161,9 @@ int OQS_SIG_picnic_verify(UNUSED const OQS_SIG *s, const uint8_t *pub, const uin
return OQS_ERROR;
}
picnic_publickey_t pk;
// deserialize the private key
if (picnic_read_public_key(&pk, pub, SERIALIZED_PUB_KEY_LEN) != 0) {
// deserialize the public key
picnic_params_t parameters = ((PICNIC_CTX *) s->ctx)->params;
if (picnic_read_public_key(&pk, pub, PUB_KEY_LEN[parameters]) != 0) {
return OQS_ERROR;
}
if (picnic_verify(&pk, msg, msg_len, sig, sig_len) != 0) {
@ -162,13 +171,4 @@ int OQS_SIG_picnic_verify(UNUSED const OQS_SIG *s, const uint8_t *pub, const uin
}
return OQS_SUCCESS;
}
int OQS_SIG_picnic_shutdown(OQS_SIG *s) {
if (s == NULL) {
return OQS_ERROR;
}
picnic_shutdown(USES_OPENSSL);
free(s->ctx);
return OQS_SUCCESS;
}
#endif // ENABLE_PICNIC
#endif

View File

@ -2,10 +2,10 @@
* \file sig_picnic.h
* \brief Header for the Microsoft Picnic library
*/
#ifndef __OQS_SIG_PICNIC_H
#define __OQS_SIG_PICNIC_H
#ifdef ENABLE_SIG_PICNIC
#include <stddef.h>
#include <stdint.h>
@ -16,5 +16,5 @@ int OQS_SIG_picnic_get(OQS_SIG *sig, enum OQS_SIG_algid algid);
int OQS_SIG_picnic_keygen(const OQS_SIG *s, uint8_t *priv, uint8_t *pub);
int OQS_SIG_picnic_sign(const OQS_SIG *s, const uint8_t *priv, const uint8_t *msg, const size_t msg_len, uint8_t *sig, size_t *sig_len);
int OQS_SIG_picnic_verify(const OQS_SIG *s, const uint8_t *pub, const uint8_t *msg, const size_t msg_len, const uint8_t *sig, const size_t sig_len);
int OQS_SIG_picnic_shutdown(OQS_SIG *sig);
#endif
#endif