mirror of
https://github.com/open-quantum-safe/liboqs.git
synced 2025-12-05 00:03:00 -05:00
Remove kex_lwe_frodo and add kem_frodokem to master-new-api (#302)
* Remove kex_lwe_frodo * Add FrodoKEM * Prettyprint * Missing liboqs.a * Fix errors because of disabling frodokem * Fix sike OQS_KEM_ prefix related inconsistencies * Fix naming inconsistensies
This commit is contained in:
parent
7f3d1b9e53
commit
f5df1c159f
1
.gitignore
vendored
1
.gitignore
vendored
@ -32,6 +32,7 @@ include
|
||||
*.i*86
|
||||
*.x86_64
|
||||
*.hex
|
||||
/example_kem
|
||||
/speed_kem
|
||||
/test_kem
|
||||
/test_kex
|
||||
|
||||
@ -8,7 +8,6 @@ matrix:
|
||||
compiler: gcc
|
||||
env:
|
||||
- CC_OVERRIDE=gcc
|
||||
- ENABLE_KEX_LWE_FRODO=0
|
||||
- ENABLE_KEX_SIDH_MSR=0
|
||||
- ENABLE_SIG_PICNIC=0
|
||||
- USE_OPENSSL=1
|
||||
|
||||
@ -53,10 +53,6 @@ if [[ ${ENABLE_CODE_MCBITS} == 1 ]];then
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ ${ENABLE_KEX_LWE_FRODO} == 0 ]];then
|
||||
enable_disable_str+=" --disable-kex-lwe-frodo"
|
||||
fi
|
||||
|
||||
if [[ ${ENABLE_KEX_NTRU} == 0 ]];then
|
||||
enable_disable_str+=" --disable-kex-ntru"
|
||||
fi
|
||||
|
||||
48
Makefile.am
48
Makefile.am
@ -24,9 +24,6 @@ liboqs_la_LIBADD += src/kex/libkex.la
|
||||
if USE_KEX_RLWE_NEWHOPE_AVX2
|
||||
liboqs_la_LIBADD += src/kex_rlwe_newhope/avx2/libnewhope_avx2.la
|
||||
endif
|
||||
if USE_KEX_LWE_FRODO
|
||||
liboqs_la_LIBADD += src/kex_lwe_frodo/libfrodo.la
|
||||
endif
|
||||
if USE_KEX_NTRU
|
||||
liboqs_la_LIBADD += src/kex_ntru/libntru.la
|
||||
endif
|
||||
@ -47,9 +44,12 @@ if USE_SIG_PICNIC
|
||||
liboqs_la_LIBADD += src/sig_picnic/libpicnic_i.la
|
||||
endif
|
||||
|
||||
if USE_KEM_SIKE
|
||||
if ENABLE_KEM_SIKE
|
||||
liboqs_la_LIBADD += src/kem/sike/libkemsike.la
|
||||
endif
|
||||
if ENABLE_KEM_FRODOKEM
|
||||
liboqs_la_LIBADD += src/kem/frodokem/libkemfrodokem.la
|
||||
endif
|
||||
|
||||
installheaderdir=$(includedir)/oqs
|
||||
installheader_HEADERS=config.h \
|
||||
@ -62,11 +62,11 @@ installheader_HEADERS=config.h \
|
||||
src/crypto/sha3/sha3.h \
|
||||
src/kem/kem.h \
|
||||
src/kex/kex.h \
|
||||
src/kex_lwe_frodo/kex_lwe_frodo.h \
|
||||
src/kex_ntru/kex_ntru.h \
|
||||
src/kex_rlwe_newhope/kex_rlwe_newhope.h \
|
||||
src/kex_sidh_msr/kex_sidh_msr.h \
|
||||
src/kem/sike/kem_sike.h \
|
||||
src/kem/frodokem/kem_frodokem.h \
|
||||
src/sig/sig.h
|
||||
|
||||
install-exec-local:
|
||||
@ -87,10 +87,7 @@ if USE_MCBITS
|
||||
cp src/kex_code_mcbits/kex_code_mcbits.h $(includedir)/oqs
|
||||
endif
|
||||
|
||||
noinst_bin_PROGRAMS = speed_kem test_kem test_kex test_aes test_rand test_sha3
|
||||
if USE_KEX_LWE_FRODO
|
||||
noinst_bin_PROGRAMS += minimal_kex_oqs
|
||||
endif
|
||||
noinst_bin_PROGRAMS = example_kem speed_kem test_kem test_kex test_aes test_rand test_sha3
|
||||
if USE_SIG_PICNIC
|
||||
noinst_bin_PROGRAMS += test_sig minimal_sig_oqs
|
||||
endif
|
||||
@ -113,6 +110,14 @@ if USE_OPENSSL
|
||||
test_kem_LDADD += -L$(OPENSSL_DIR)/lib -lcrypto
|
||||
endif
|
||||
|
||||
example_kem_LDADD = liboqs.la -lm
|
||||
example_kem_SOURCES = src/kem/example_kem.c
|
||||
example_kem_CPPFLAGS = -I./include
|
||||
example_kem_CPPFLAGS += $(AM_CPPFLAGS)
|
||||
if USE_OPENSSL
|
||||
example_kem_LDADD += -L$(OPENSSL_DIR)/lib -lcrypto
|
||||
endif
|
||||
|
||||
test_kex_LDADD = liboqs.la -lm
|
||||
test_kex_SOURCES = src/kex/test_kex.c
|
||||
test_kex_CPPFLAGS = -I./include
|
||||
@ -143,20 +148,6 @@ endif
|
||||
|
||||
endif # USE_SIG_PICNIC
|
||||
|
||||
if USE_KEX_LWE_FRODO
|
||||
minimal_kex_oqs_LDADD = liboqs.la -lm
|
||||
minimal_kex_oqs_SOURCES = src/kex/minimal_kex_oqs.c
|
||||
minimal_kex_oqs_CPPFLAGS = -I./include
|
||||
minimal_kex_oqs_CPPFLAGS += $(AM_CPPFLAGS)
|
||||
if USE_MCBITS
|
||||
minimal_kex_oqs_LDADD += -L${SODIUM_DIR}/lib -lsodium
|
||||
endif
|
||||
if USE_OPENSSL
|
||||
minimal_kex_oqs_LDADD += -L$(OPENSSL_DIR)/lib -lcrypto
|
||||
endif
|
||||
|
||||
endif # USE_KEX_LWE_FRODO
|
||||
|
||||
test_aes_LDADD = liboqs.la -lm
|
||||
test_aes_SOURCES = src/crypto/aes/test_aes.c
|
||||
test_aes_CPPFLAGS = -I./include
|
||||
@ -186,6 +177,7 @@ test_sha3_CPPFLAGS += $(AM_CPPFLAGS)
|
||||
|
||||
test: clean-tests
|
||||
make
|
||||
./example_kem
|
||||
./test_kem
|
||||
./test_kex --quiet
|
||||
./test_rand --quiet
|
||||
@ -195,9 +187,6 @@ if USE_SIG_PICNIC
|
||||
./test_sig
|
||||
./minimal_sig_oqs
|
||||
endif
|
||||
if USE_KEX_LWE_FRODO
|
||||
./minimal_kex_oqs
|
||||
endif
|
||||
|
||||
links:
|
||||
$(MKDIR_P) include/oqs
|
||||
@ -211,8 +200,8 @@ links:
|
||||
cp -f src/crypto/sha3/sha3.h include/oqs
|
||||
cp -f src/kem/kem.h include/oqs
|
||||
cp -f src/kem/sike/kem_sike.h include/oqs
|
||||
cp -f src/kem/frodokem/kem_frodokem.h include/oqs
|
||||
cp -f src/kex/kex.h include/oqs
|
||||
cp -f src/kex_lwe_frodo/kex_lwe_frodo.h include/oqs
|
||||
cp -f src/kex_ntru/kex_ntru.h include/oqs
|
||||
cp -f src/kex_rlwe_newhope/kex_rlwe_newhope.h include/oqs
|
||||
if USE_KEX_RLWE_NEWHOPE_AVX2
|
||||
@ -230,16 +219,13 @@ endif
|
||||
clean-local:
|
||||
rm -f liboqs.a
|
||||
rm -rf include
|
||||
if USE_KEX_LWE_FRODO
|
||||
rm -f minimal_kex_oqs
|
||||
endif
|
||||
if USE_SIG_PICNIC
|
||||
rm -f test_sig
|
||||
rm -f minimal_sig_oqs
|
||||
endif
|
||||
|
||||
clean-tests:
|
||||
rm -f speed_kem test_kem test_kex test_rand test_aes test_sha3
|
||||
rm -f example_kem speed_kem test_kem test_kex test_rand test_aes test_sha3
|
||||
|
||||
prettyprint:
|
||||
find src -name '*.c' -o -name '*.h' | grep -v sig_picnic/external* | grep -v "kex_rlwe_newhope/avx2" | grep -v "kex_sidh_msr" | xargs $(CLANGFORMAT) -style=file -i
|
||||
|
||||
@ -4,3 +4,4 @@
|
||||
|
||||
- Create a new `test_common` program that combines `test_rand`, `test_aes`, `test_sha`, etc.
|
||||
- `speed_kem` needs autoconf to generate compilation information variables
|
||||
- Frodo ahsn't been configured to use AVX2 where available
|
||||
|
||||
@ -24,7 +24,6 @@ Contents
|
||||
liboqs currently contains:
|
||||
|
||||
- `kex_rlwe_newhope`: "NewHope": key exchange from the ring learning with errors problem (Alkim, Ducas, Pöppelmann, Schwabe, *USENIX Security 2016*, [https://eprint.iacr.org/2015/1092](https://eprint.iacr.org/2015/1092)) (using the reference C implementation of NewHope from [https://github.com/tpoeppelmann/newhope](https://github.com/tpoeppelmann/newhope))
|
||||
- `kex_lwe_frodo`: "Frodo": key exchange from the learning with errors problem (Bos, Costello, Ducas, Mironov, Naehrig, Nikolaenko, Raghunathan, Stebila, *ACM Conference on Computer and Communications Security 2016*, [https://eprint.iacr.org/2016/659](https://eprint.iacr.org/2016/659))
|
||||
- `kex_sidh_msr`: key exchange from the supersingular isogeny Diffie-Hellman problem (Costello, Naehrig, Longa, *CRYPTO 2016*, [https://eprint.iacr.org/2016/413](https://eprint.iacr.org/2016/413)), using the implementation of Microsoft Research [https://www.microsoft.com/en-us/research/project/sidh-library/](https://www.microsoft.com/en-us/research/project/sidh-library/)
|
||||
- `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))
|
||||
@ -137,7 +136,7 @@ To build with `kex_code_mcbits ` enabled:
|
||||
|
||||
### Building with the following KEX algorithms disabled
|
||||
|
||||
./configure --disable-kex-ntru --disable-kex-lwe-frodo --disable-kex-rlwe-newhope --disable-kex-sidh-msr
|
||||
./configure --disable-kex-ntru --disable-kex-rlwe-newhope --disable-kex-sidh-msr
|
||||
make clean
|
||||
make
|
||||
|
||||
|
||||
@ -46,8 +46,6 @@
|
||||
<ClInclude Include="..\..\src\kex\kex.h" />
|
||||
<ClInclude Include="..\..\src\kex_code_mcbits\kex_code_mcbits.h" />
|
||||
<ClInclude Include="..\..\src\kex_code_mcbits\mcbits.h" />
|
||||
<ClInclude Include="..\..\src\kex_lwe_frodo\kex_lwe_frodo.h" />
|
||||
<ClInclude Include="..\..\src\kex_lwe_frodo\local.h" />
|
||||
<ClInclude Include="..\..\src\kex_ntru\kex_ntru.h" />
|
||||
<ClInclude Include="..\..\src\kex_rlwe_newhope\kex_rlwe_newhope.h" />
|
||||
<ClInclude Include="..\..\src\kex_rlwe_newhope\params.h" />
|
||||
@ -93,9 +91,6 @@
|
||||
<ClCompile Include="..\..\src\kex\kex.c" />
|
||||
<ClCompile Include="..\..\src\kex_code_mcbits\external\operations.c" />
|
||||
<ClCompile Include="..\..\src\kex_code_mcbits\kex_code_mcbits.c" />
|
||||
<ClCompile Include="..\..\src\kex_lwe_frodo\kex_lwe_frodo.c" />
|
||||
<ClCompile Include="..\..\src\kex_lwe_frodo\lwe.c" />
|
||||
<ClCompile Include="..\..\src\kex_lwe_frodo\lwe_noise.c" />
|
||||
<ClCompile Include="..\..\src\kex_ntru\kex_ntru.c" />
|
||||
<ClCompile Include="..\..\src\kex_rlwe_newhope\kex_rlwe_newhope.c" />
|
||||
<ClCompile Include="..\..\src\kex_sidh_msr\kex_sidh_msr.c" />
|
||||
@ -269,7 +264,6 @@ copy "$(SolutionDir)..\src\crypto\rand_urandom_aesctr\rand_urandom_aesctr.h" "$(
|
||||
copy "$(SolutionDir)..\src\crypto\sha3\sha3.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex\kex.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_rlwe_newhope\kex_rlwe_newhope.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_lwe_frodo\kex_lwe_frodo.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_code_mcbits\kex_code_mcbits.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_ntru\kex_ntru.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_sidh_msr\kex_sidh_msr.h" "$(SolutionDir)include\oqs\"
|
||||
@ -306,7 +300,6 @@ copy "$(SolutionDir)..\src\crypto\rand_urandom_aesctr\rand_urandom_aesctr.h" "$(
|
||||
copy "$(SolutionDir)..\src\crypto\sha3\sha3.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex\kex.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_rlwe_newhope\kex_rlwe_newhope.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_lwe_frodo\kex_lwe_frodo.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_code_mcbits\kex_code_mcbits.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_ntru\kex_ntru.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_sidh_msr\kex_sidh_msr.h" "$(SolutionDir)include\oqs\"
|
||||
@ -343,7 +336,6 @@ copy "$(SolutionDir)..\src\crypto\rand_urandom_aesctr\rand_urandom_aesctr.h" "$(
|
||||
copy "$(SolutionDir)..\src\crypto\sha3\sha3.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex\kex.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_rlwe_newhope\kex_rlwe_newhope.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_lwe_frodo\kex_lwe_frodo.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_code_mcbits\kex_code_mcbits.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_ntru\kex_ntru.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_sidh_msr\kex_sidh_msr.h" "$(SolutionDir)include\oqs\"
|
||||
@ -387,7 +379,6 @@ copy "$(SolutionDir)..\src\crypto\rand_urandom_aesctr\rand_urandom_aesctr.h" "$(
|
||||
copy "$(SolutionDir)..\src\crypto\sha3\sha3.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex\kex.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_rlwe_newhope\kex_rlwe_newhope.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_lwe_frodo\kex_lwe_frodo.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_code_mcbits\kex_code_mcbits.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_ntru\kex_ntru.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_sidh_msr\kex_sidh_msr.h" "$(SolutionDir)include\oqs\"
|
||||
@ -430,7 +421,6 @@ copy "$(SolutionDir)..\src\crypto\rand_urandom_aesctr\rand_urandom_aesctr.h" "$(
|
||||
copy "$(SolutionDir)..\src\crypto\sha3\sha3.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex\kex.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_rlwe_newhope\kex_rlwe_newhope.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_lwe_frodo\kex_lwe_frodo.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_code_mcbits\kex_code_mcbits.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_ntru\kex_ntru.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_sidh_msr\kex_sidh_msr.h" "$(SolutionDir)include\oqs\"
|
||||
@ -471,7 +461,6 @@ copy "$(SolutionDir)..\src\crypto\rand_urandom_aesctr\rand_urandom_aesctr.h" "$(
|
||||
copy "$(SolutionDir)..\src\crypto\sha3\sha3.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex\kex.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_rlwe_newhope\kex_rlwe_newhope.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_lwe_frodo\kex_lwe_frodo.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_code_mcbits\kex_code_mcbits.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_ntru\kex_ntru.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_sidh_msr\kex_sidh_msr.h" "$(SolutionDir)include\oqs\"
|
||||
@ -512,7 +501,6 @@ copy "$(SolutionDir)..\src\crypto\rand_urandom_aesctr\rand_urandom_aesctr.h" "$(
|
||||
copy "$(SolutionDir)..\src\crypto\sha3\sha3.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex\kex.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_rlwe_newhope\kex_rlwe_newhope.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_lwe_frodo\kex_lwe_frodo.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_code_mcbits\kex_code_mcbits.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_ntru\kex_ntru.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_sidh_msr\kex_sidh_msr.h" "$(SolutionDir)include\oqs\"
|
||||
@ -560,7 +548,6 @@ copy "$(SolutionDir)..\src\crypto\rand_urandom_aesctr\rand_urandom_aesctr.h" "$(
|
||||
copy "$(SolutionDir)..\src\crypto\sha3\sha3.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex\kex.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_rlwe_newhope\kex_rlwe_newhope.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_lwe_frodo\kex_lwe_frodo.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_code_mcbits\kex_code_mcbits.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_ntru\kex_ntru.h" "$(SolutionDir)include\oqs\"
|
||||
copy "$(SolutionDir)..\src\kex_sidh_msr\kex_sidh_msr.h" "$(SolutionDir)include\oqs\"
|
||||
|
||||
@ -1,18 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\kex_lwe_frodo\kex_lwe_frodo.c">
|
||||
<Filter>KEX_Frodo</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\kex_rlwe_newhope\kex_rlwe_newhope.c">
|
||||
<Filter>KEX_NewHope</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\kex_lwe_frodo\lwe.c">
|
||||
<Filter>KEX_Frodo</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\kex_lwe_frodo\lwe_noise.c">
|
||||
<Filter>KEX_Frodo</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\common\common.c">
|
||||
<Filter>Common</Filter>
|
||||
</ClCompile>
|
||||
@ -123,15 +114,9 @@
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\kex_lwe_frodo\kex_lwe_frodo.h">
|
||||
<Filter>KEX_Frodo</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kex_rlwe_newhope\kex_rlwe_newhope.h">
|
||||
<Filter>KEX_NewHope</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kex_lwe_frodo\local.h">
|
||||
<Filter>KEX_Frodo</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\kex_rlwe_newhope\params.h">
|
||||
<Filter>KEX_NewHope</Filter>
|
||||
</ClInclude>
|
||||
@ -273,9 +258,6 @@
|
||||
<Filter Include="KEX">
|
||||
<UniqueIdentifier>{3bb6aa76-f294-47a9-bf22-76245c9cb1d1}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="KEX_Frodo">
|
||||
<UniqueIdentifier>{6bfff158-3e78-402f-ba16-e8d315089de8}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="KEX_NewHope">
|
||||
<UniqueIdentifier>{d0291785-4232-4264-b1bd-08b7e3f8df5e}</UniqueIdentifier>
|
||||
</Filter>
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
#define __WINCONFIG_H
|
||||
|
||||
/* Enable schemes supported on Windows */
|
||||
#define ENABLE_KEX_LWE_FRODO
|
||||
#define ENABLE_KEX_NTRU
|
||||
#define ENABLE_KEX_RLWE_NEWHOPE
|
||||
#define ENABLE_KEX_SIDH_MSR
|
||||
|
||||
38
configure.ac
38
configure.ac
@ -92,10 +92,6 @@ ARG_ENABL_SET([kex-code-mcbits], [enable KEX-CODE-MCBITS.])
|
||||
AM_CONDITIONAL([kex_code_mcbits], [test "x$kex_code_mcbits" = xtrue])
|
||||
AM_CONDITIONAL([USE_MCBITS], [test "x$kex_code_mcbits" = xtrue])
|
||||
|
||||
ARG_DISBL_SET([kex-lwe-frodo], [disable KEX-LWE-FRODO.])
|
||||
AM_CONDITIONAL([kex_lwe_frodo], [test "x$kex_lwe_frodo" = xtrue])
|
||||
AM_CONDITIONAL([USE_KEX_LWE_FRODO], [test "x$kex_lwe_frodo" = xtrue])
|
||||
|
||||
ARG_DISBL_SET([kex-ntru], [disable KEX-NTRU.])
|
||||
AM_CONDITIONAL([kex_ntru], [test "x$kex_ntru" = xtrue])
|
||||
AM_CONDITIONAL([USE_KEX_NTRU], [test "x$kex_ntru" = xtrue])
|
||||
@ -116,10 +112,6 @@ 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])
|
||||
|
||||
ARG_DISBL_SET([kem-sike], [disable KEM-SIKE.])
|
||||
AM_CONDITIONAL([kem_sike], [test "x$kem_sike" = xtrue])
|
||||
AM_CONDITIONAL([USE_KEM_SIKE], [test "x$kem_sike" = xtrue])
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
# Check for which host we are on and setup a few things
|
||||
@ -177,12 +169,6 @@ SRCDIR=${SRCDIR}" src/crypto/aes src/crypto/sha3 src/crypto/rand_urandom_aesctr
|
||||
# KEX
|
||||
SRCDIR=${SRCDIR}" src/kex"
|
||||
|
||||
if test x"$kex_lwe_frodo" = x"true"; then
|
||||
SRCDIR=${SRCDIR}" src/kex_lwe_frodo"
|
||||
AM_CPPFLAGS=${AM_CPPFLAGS}" -DENABLE_KEX_LWE_FRODO"
|
||||
AC_DEFINE(ENABLE_KEX_LWE_FRODO, 1, "Define to 1 when FRODO enabled")
|
||||
fi
|
||||
|
||||
if test x"$kex_ntru" = x"true"; then
|
||||
SRCDIR=${SRCDIR}" src/kex_ntru"
|
||||
AM_CPPFLAGS=${AM_CPPFLAGS}" -DENABLE_KEX_NTRU"
|
||||
@ -218,12 +204,20 @@ fi
|
||||
# KEM
|
||||
SRCDIR=${SRCDIR}" src/kem"
|
||||
|
||||
if test x"$kem_sike" = x"true"; then
|
||||
SRCDIR=${SRCDIR}" src/kem/sike"
|
||||
AM_CPPFLAGS=${AM_CPPFLAGS}" -DOQS_ENABLE_KEM_sike_p503 -DOQS_ENABLE_KEM_sike_p751"
|
||||
AC_DEFINE(OQS_ENABLE_KEM_sike_p503, 1, "Define to 1 when Sike-p503 enabled")
|
||||
AC_DEFINE(OQS_ENABLE_KEM_sike_p751, 1, "Define to 1 when Sike-p751 enabled")
|
||||
fi
|
||||
ARG_DISBL_SET([kem-sike], [disable KEM-SIKE.])
|
||||
AM_CONDITIONAL([ENABLE_KEM_SIKE], [test "x$kem_sike" = xtrue])
|
||||
AM_COND_IF([ENABLE_KEM_SIKE], [SRCDIR="${SRCDIR} src/kem/sike"])
|
||||
AM_COND_IF([ENABLE_KEM_SIKE], [AC_DEFINE(OQS_ENABLE_KEM_sike_p503, 1, "Define to 1 when Sike-p503 enabled")])
|
||||
AM_COND_IF([ENABLE_KEM_SIKE], [AC_DEFINE(OQS_ENABLE_KEM_sike_p751, 1, "Define to 1 when Sike-p751 enabled")])
|
||||
|
||||
ARG_DISBL_SET([kem-frodokem], [disable KEM-FrodoKEM.])
|
||||
AM_CONDITIONAL([ENABLE_KEM_FRODOKEM], [test "x$kem_frodokem" = xtrue])
|
||||
AM_COND_IF([ENABLE_KEM_FRODOKEM], [SRCDIR="${SRCDIR} src/kem/frodokem"])
|
||||
AM_COND_IF([ENABLE_KEM_FRODOKEM], [AC_DEFINE(OQS_ENABLE_KEM_frodokem_640_aes, 1, "Define to 1 when FrodoKEM-640-AES enabled")])
|
||||
AM_COND_IF([ENABLE_KEM_FRODOKEM], [AC_DEFINE(OQS_ENABLE_KEM_frodokem_640_cshake, 1, "Define to 1 when FrodoKEM-640-cSHAKE enabled")])
|
||||
AM_COND_IF([ENABLE_KEM_FRODOKEM], [AC_DEFINE(OQS_ENABLE_KEM_frodokem_976_aes, 1, "Define to 1 when FrodoKEM-976-AES enabled")])
|
||||
AM_COND_IF([ENABLE_KEM_FRODOKEM], [AC_DEFINE(OQS_ENABLE_KEM_frodokem_976_cshake, 1, "Define to 1 when FrodoKEM-976-cSHAKE enabled")])
|
||||
|
||||
|
||||
|
||||
# Flags
|
||||
@ -252,14 +246,12 @@ AC_SUBST(USE_OPENSSL)
|
||||
AC_SUBST(USE_AES_NI)
|
||||
AC_SUBST(USE_KEX_NTRU)
|
||||
AC_SUBST(USE_MCBITS)
|
||||
AC_SUBST(USE_KEX_LWE_FRODO)
|
||||
AC_SUBST(USE_KEX_RLWE_NEWHOPE)
|
||||
AC_SUBST(USE_KEX_SIDH_MSR)
|
||||
AC_SUBST(USE_SIG_PICNIC)
|
||||
AC_SUBST(ON_DARWIN)
|
||||
AC_SUBST(X86_64)
|
||||
AC_SUBST(USE_KEX_RLWE_NEWHOPE_AVX2)
|
||||
AC_SUBST(USE_KEM_SIKE)
|
||||
|
||||
|
||||
AC_CONFIG_FILES([Makefile
|
||||
@ -274,11 +266,11 @@ AC_CONFIG_FILES([Makefile
|
||||
src/kex_sidh_msr/Makefile
|
||||
src/kex_code_mcbits/Makefile
|
||||
src/kex_ntru/Makefile
|
||||
src/kex_lwe_frodo/Makefile
|
||||
src/sig/Makefile
|
||||
src/sig_picnic/Makefile
|
||||
src/kex_rlwe_newhope/avx2/Makefile
|
||||
src/kem/sike/Makefile
|
||||
src/kem/frodokem/Makefile
|
||||
])
|
||||
|
||||
AC_OUTPUT
|
||||
|
||||
40
docs/algorithms/kem_frodokem.md
Normal file
40
docs/algorithms/kem_frodokem.md
Normal file
@ -0,0 +1,40 @@
|
||||
liboqs master branch algorithm datasheet: `kem_frodokem`
|
||||
========================================================
|
||||
|
||||
Summary
|
||||
-------
|
||||
|
||||
- **Name**: FrodoKEM
|
||||
- **Algorithm type**: key encapsulation mechanism
|
||||
- **Main cryptographic assumption**: learning with errors (LWE)
|
||||
- **Scheme authors**: Michael Naehrig, Erdem Alkim, Joppe Bos, Léo Ducas, Karen Easterbrook, Brian LaMacchia, Patrick Longa, Ilya Mironov, Valeria Nikolaenko, Christopher Peikert, Ananth Raghunathan, Douglas Stebila
|
||||
- **Authors' website**: https://frodokem.org/
|
||||
- **Added to liboqs by**: Douglas Stebila
|
||||
|
||||
Parameter sets
|
||||
--------------
|
||||
|
||||
| Parameter set | Security model | Claimed NIST security level | Public key size (bytes) | Secret key size (bytes) | Ciphertext size (bytes) | Shared secret size (bytes) |
|
||||
|---------------------|:--------------:|:---------------------------:|:-----------------------:|:-----------------------:|:-----------------------:|:--------------------------:|
|
||||
| FrodoKEM-640-AES | IND-CCA | 1 | 9616 | 19872 | 9736 | 16 |
|
||||
| FrodoKEM-640-cSHAKE | IND-CCA | 1 | 9616 | 19872 | 9736 | 16 |
|
||||
| FrodoKEM-976-AES | IND-CCA | 3 | 15632 | 31272 | 15768 | 24 |
|
||||
| FrodoKEM-976-cSHAKE | IND-CCA | 3 | 15632 | 31272 | 15768 | 24 |
|
||||
|
||||
Implementation
|
||||
--------------
|
||||
|
||||
- **Source of implementation:** https://github.com/Microsoft/PQCrypto-LWEKE
|
||||
- **License:** MIT License
|
||||
- **Language:** C
|
||||
- **Constant-time:** Yes
|
||||
- **Architectures supported in liboqs master branch**: x86, x64
|
||||
|
||||
Additional comments
|
||||
-------------------
|
||||
|
||||
The original FrodoKEM implementation includes optimizations that are not currently being built in liboqs:
|
||||
|
||||
- ARM
|
||||
- AVX2
|
||||
- cSHAKE 4-way hashing
|
||||
@ -1,60 +0,0 @@
|
||||
Algorithm data sheet: `kex_lwe_frodo`
|
||||
=======================================
|
||||
|
||||
Algorithm
|
||||
---------
|
||||
|
||||
**Name:** Frodo
|
||||
|
||||
**Description:** Key exchange protocol proposed by Bos et al. [BCDMNNRS16] based on the ring learning with errors problem. Instantiation of the Lindner–Peikert approximate LWE key agreement scheme [LP10], which was an adaptation of the LWE public key encryption scheme of in public key encryption scheme of Regev [Reg05], using reconciliation mechanism of Peikert [Pei14].
|
||||
|
||||
**Supporting research:**
|
||||
|
||||
- [BCDMNNRS16] Joppe Bos, Craig Costello, Léo Ducas, Ilya Mironov, Michael Naehrig, Valeria Nikolaenko, Ananth Raghunathan, Douglas Stebila. Frodo: Take off the ring! Practical, quantum-secure key exchange from LWE. In *Proc. 23rd ACM Conference on Computer and Communications Security (CCS) 2016*, pp. 1006-1018. ACM, October 2016. [https://eprint.iacr.org/2016/659](https://eprint.iacr.org/2016/659)
|
||||
- [Pei14] Chris Peikert. Lattice cryptography for the Internet. In *PQCrypto 2014*, volume 8772 of LNCS, pages 197–219. Springer, 2014. [https://eprint.iacr.org/2014/070](https://eprint.iacr.org/2014/070)
|
||||
- [LP10] Richard Lindner and Chris Peikert. Better key sizes (and attacks) for LWE-based encryption. In *Proc. CT-RSA 2011*, *LNCS*, vol. 6558, pp. 319–339. Springer, February 2011. [https://eprint.iacr.org/2010/613](https://eprint.iacr.org/2010/613)
|
||||
- [Reg05] Oded Regev. On lattices, learning with errors, random linear codes, and cryptography. In *Proc. 37th ACM STOC*, pp. 84–93. ACM Press, May 2005.
|
||||
|
||||
Security
|
||||
--------
|
||||
|
||||
**Security model:** Unauthenticated key exchange / passive (IND-CPA) key encapsulation mechanism
|
||||
|
||||
**Underlying hard problem(s):** Decision learning with errors problem
|
||||
|
||||
Parameter set 1
|
||||
---------------
|
||||
|
||||
"Recommended" parameter set from [BCDMNNRS16]
|
||||
|
||||
**Claimed classical security:**
|
||||
|
||||
- 2^144 (original paper)
|
||||
|
||||
**Claimed quantum security:**
|
||||
|
||||
- 2^130 (original paper)
|
||||
|
||||
**Communication size:**
|
||||
|
||||
- Alice → Bob: 11,377 bytes
|
||||
- Bob → Alice: 11,296 bytes
|
||||
- total: 22,673 bytes
|
||||
|
||||
Implementation
|
||||
--------------
|
||||
|
||||
**Source of implementation:** Original research paper ([https://github.com/lwe-frodo/lwe-frodo](https://github.com/lwe-frodo/lwe-frodo))
|
||||
|
||||
**License:** MIT License
|
||||
|
||||
**Language:** C
|
||||
|
||||
**Constant-time:** Yes
|
||||
|
||||
**Testing:**
|
||||
|
||||
- Correctness: covered by test harness `test_kex`
|
||||
- Statistics of shared secrets: covered by test harness `test_kex`
|
||||
- Static analysis:
|
||||
- `scan_build`
|
||||
183
src/kem/example_kem.c
Normal file
183
src/kem/example_kem.c
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* example_kem.c
|
||||
*
|
||||
* Minimal example of a Diffie-Hellman-style post-quantum key encapsulation
|
||||
* implemented in liboqs.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <oqs/oqs.h>
|
||||
|
||||
/* Cleaning up memory etc */
|
||||
void cleanup_stack(uint8_t *secret_key, size_t secret_key_len,
|
||||
uint8_t *shared_secret_e, uint8_t *shared_secret_d,
|
||||
size_t shared_secret_len);
|
||||
|
||||
void cleanup_heap(uint8_t *secret_key, uint8_t *shared_secret_e,
|
||||
uint8_t *shared_secret_d, uint8_t *public_key,
|
||||
uint8_t *ciphertext, OQS_KEM *kem);
|
||||
|
||||
/* This function gives an example of the operations performed by both
|
||||
* the decapsulator and the encapsulator in a single KEM session,
|
||||
* using only compile-time macros and allocating variables
|
||||
* statically on the stack, calling a specific algorithm's functions
|
||||
* directly.
|
||||
*
|
||||
* The macros OQS_KEM_frodokem_640_aes_length_* and the functions
|
||||
* OQS_KEM_frodokem_640_aes_* are only defined if the algorithm
|
||||
* FrodoKEM-640-AES was enabled at compile-time which must be
|
||||
* checked using the OQS_ENABLE_KEM_frodokem_640_aes macro.
|
||||
*
|
||||
* <oqs/config.h>, which is included in <oqs/oqs.h>, contains macros
|
||||
* indicating which algorithms were enabled when this instance of liboqs
|
||||
* was compiled.
|
||||
*/
|
||||
OQS_STATUS example_stack() {
|
||||
#ifndef OQS_ENABLE_KEM_frodokem_640_aes // if FrodoKEM-640-AES was not enabled at compile-time
|
||||
printf("[example_stack] OQS_KEM_frodokem_640_aes was not enabled at "
|
||||
"compile-time.\n");
|
||||
return OQS_ERROR;
|
||||
#endif
|
||||
#ifdef OQS_ENABLE_KEM_frodokem_640_aes
|
||||
uint8_t public_key[OQS_KEM_frodokem_640_aes_length_public_key];
|
||||
uint8_t secret_key[OQS_KEM_frodokem_640_aes_length_secret_key];
|
||||
uint8_t ciphertext[OQS_KEM_frodokem_640_aes_length_ciphertext];
|
||||
uint8_t shared_secret_e[OQS_KEM_frodokem_640_aes_length_shared_secret];
|
||||
uint8_t shared_secret_d[OQS_KEM_frodokem_640_aes_length_shared_secret];
|
||||
|
||||
OQS_STATUS rc = OQS_KEM_frodokem_640_aes_keypair(public_key, secret_key);
|
||||
if (rc != OQS_SUCCESS) {
|
||||
fprintf(stderr, "ERROR: OQS_KEM_frodokem_640_aes_keypair failed!\n");
|
||||
cleanup_stack(secret_key, OQS_KEM_frodokem_640_aes_length_secret_key,
|
||||
shared_secret_e, shared_secret_d,
|
||||
OQS_KEM_frodokem_640_aes_length_shared_secret);
|
||||
|
||||
return OQS_ERROR;
|
||||
}
|
||||
rc = OQS_KEM_frodokem_640_aes_encaps(ciphertext, shared_secret_e, public_key);
|
||||
if (rc != OQS_SUCCESS) {
|
||||
fprintf(stderr, "ERROR: OQS_KEM_frodokem_640_aes_encaps failed!\n");
|
||||
cleanup_stack(secret_key, OQS_KEM_frodokem_640_aes_length_secret_key,
|
||||
shared_secret_e, shared_secret_d,
|
||||
OQS_KEM_frodokem_640_aes_length_shared_secret);
|
||||
|
||||
return OQS_ERROR;
|
||||
}
|
||||
rc = OQS_KEM_frodokem_640_aes_decaps(shared_secret_d, ciphertext, secret_key);
|
||||
if (rc != OQS_SUCCESS) {
|
||||
fprintf(stderr, "ERROR: OQS_KEM_frodokem_640_aes_decaps failed!\n");
|
||||
cleanup_stack(secret_key, OQS_KEM_frodokem_640_aes_length_secret_key,
|
||||
shared_secret_e, shared_secret_d,
|
||||
OQS_KEM_frodokem_640_aes_length_shared_secret);
|
||||
|
||||
return OQS_ERROR;
|
||||
}
|
||||
printf("[example_stack] OQS_KEM_frodokem_640_aes operations completed.\n");
|
||||
|
||||
return OQS_SUCCESS; // success!
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This function gives an example of the operations performed by both
|
||||
* the decapsulator and the encapsulator in a single KEM session,
|
||||
* allocating variables dynamically on the heap and calling the generic
|
||||
* OQS_KEM object.
|
||||
*
|
||||
* This does not require the use of compile-time macros to check if the
|
||||
* algorithm in question was enabled at compile-time; instead, the caller
|
||||
* must check that the OQS_KEM object returned is not NULL.
|
||||
*/
|
||||
OQS_STATUS example_heap() {
|
||||
OQS_KEM *kem = NULL;
|
||||
uint8_t *public_key = NULL;
|
||||
uint8_t *secret_key = NULL;
|
||||
uint8_t *ciphertext = NULL;
|
||||
uint8_t *shared_secret_e = NULL;
|
||||
uint8_t *shared_secret_d = NULL;
|
||||
|
||||
kem = OQS_KEM_new(OQS_KEM_alg_frodokem_640_aes);
|
||||
if (kem == NULL) {
|
||||
printf("[example_heap] OQS_KEM_frodokem_640_aes was not enabled at "
|
||||
"compile-time.\n");
|
||||
return OQS_ERROR;
|
||||
}
|
||||
|
||||
public_key = malloc(kem->length_public_key);
|
||||
secret_key = malloc(kem->length_secret_key);
|
||||
ciphertext = malloc(kem->length_ciphertext);
|
||||
shared_secret_e = malloc(kem->length_shared_secret);
|
||||
shared_secret_d = malloc(kem->length_shared_secret);
|
||||
if ((public_key == NULL) || (secret_key == NULL) || (ciphertext == NULL) ||
|
||||
(shared_secret_e == NULL) || (shared_secret_d == NULL)) {
|
||||
fprintf(stderr, "ERROR: malloc failed!\n");
|
||||
cleanup_heap(secret_key, shared_secret_e, shared_secret_d, public_key,
|
||||
ciphertext, kem);
|
||||
|
||||
return OQS_ERROR;
|
||||
}
|
||||
|
||||
OQS_STATUS rc = OQS_KEM_keypair(kem, public_key, secret_key);
|
||||
if (rc != OQS_SUCCESS) {
|
||||
fprintf(stderr, "ERROR: OQS_KEM_keypair failed!\n");
|
||||
cleanup_heap(secret_key, shared_secret_e, shared_secret_d, public_key,
|
||||
ciphertext, kem);
|
||||
|
||||
return OQS_ERROR;
|
||||
}
|
||||
rc = OQS_KEM_encaps(kem, ciphertext, shared_secret_e, public_key);
|
||||
if (rc != OQS_SUCCESS) {
|
||||
fprintf(stderr, "ERROR: OQS_KEM_encaps failed!\n");
|
||||
cleanup_heap(secret_key, shared_secret_e, shared_secret_d, public_key,
|
||||
ciphertext, kem);
|
||||
|
||||
return OQS_ERROR;
|
||||
}
|
||||
rc = OQS_KEM_decaps(kem, shared_secret_d, ciphertext, secret_key);
|
||||
if (rc != OQS_SUCCESS) {
|
||||
fprintf(stderr, "ERROR: OQS_KEM_decaps failed!\n");
|
||||
cleanup_heap(secret_key, shared_secret_e, shared_secret_d, public_key,
|
||||
ciphertext, kem);
|
||||
|
||||
return OQS_ERROR;
|
||||
}
|
||||
|
||||
printf("[example_heap] OQS_KEM_frodokem_640_aes operations completed.\n");
|
||||
cleanup_heap(secret_key, shared_secret_e, shared_secret_d, public_key,
|
||||
ciphertext, kem);
|
||||
|
||||
return OQS_SUCCESS; // success
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
if (example_stack() == OQS_SUCCESS && example_heap() == OQS_SUCCESS) {
|
||||
return EXIT_SUCCESS;
|
||||
} else {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
void cleanup_stack(uint8_t *secret_key, size_t secret_key_len,
|
||||
uint8_t *shared_secret_e, uint8_t *shared_secret_d,
|
||||
size_t shared_secret_len) {
|
||||
OQS_MEM_cleanse(secret_key, secret_key_len);
|
||||
OQS_MEM_cleanse(shared_secret_e, shared_secret_len);
|
||||
OQS_MEM_cleanse(shared_secret_d, shared_secret_len);
|
||||
}
|
||||
|
||||
void cleanup_heap(uint8_t *secret_key, uint8_t *shared_secret_e,
|
||||
uint8_t *shared_secret_d, uint8_t *public_key,
|
||||
uint8_t *ciphertext, OQS_KEM *kem) {
|
||||
if (kem != NULL) {
|
||||
OQS_MEM_secure_free(secret_key, kem->length_secret_key);
|
||||
OQS_MEM_secure_free(shared_secret_e, kem->length_shared_secret);
|
||||
OQS_MEM_secure_free(shared_secret_d, kem->length_shared_secret);
|
||||
}
|
||||
OQS_MEM_insecure_free(public_key);
|
||||
OQS_MEM_insecure_free(ciphertext);
|
||||
OQS_KEM_free(kem);
|
||||
}
|
||||
12
src/kem/frodokem/Makefile.am
Normal file
12
src/kem/frodokem/Makefile.am
Normal file
@ -0,0 +1,12 @@
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
noinst_LTLIBRARIES = libkemfrodokem.la
|
||||
|
||||
libkemfrodokem_la_SOURCES = kem_frodokem.c frodo640_aes.c frodo640_cshake.c frodo976_aes.c frodo976_cshake.c util.c
|
||||
|
||||
libkemfrodokem_la_CPPFLAGS = -I../../../include -I. -fPIC -w
|
||||
libkemfrodokem_la_CPPFLAGS += $(AM_CPPFLAGS)
|
||||
|
||||
frodo640_aes.c: frodo_macrify.h frodo_macrify.c frodo640_params.h kem.c
|
||||
frodo640_cshake.c: frodo_macrify.h frodo_macrify.c frodo640_params.h kem.c
|
||||
frodo976_aes.c: frodo_macrify.h frodo_macrify.c frodo976_params.h kem.c
|
||||
frodo976_cshake.c: frodo_macrify.h frodo_macrify.c frodo976_params.h kem.c
|
||||
90
src/kem/frodokem/config.h
Normal file
90
src/kem/frodokem/config.h
Normal file
@ -0,0 +1,90 @@
|
||||
/********************************************************************************************
|
||||
* FrodoKEM: Learning with Errors Key Encapsulation
|
||||
*
|
||||
* Abstract: configuration file
|
||||
*********************************************************************************************/
|
||||
|
||||
#ifndef _CONFIG_H_
|
||||
#define _CONFIG_H_
|
||||
|
||||
// Definition of operating system
|
||||
|
||||
#define OS_WIN 1
|
||||
#define OS_NIX 2
|
||||
|
||||
#if defined(WINDOWS) // Microsoft Windows
|
||||
#define OS_TARGET OS_WIN
|
||||
#elif defined(NIX) // Unix-like operative systems
|
||||
#define OS_TARGET OS_NIX
|
||||
#else
|
||||
#error-- "Unsupported OS"
|
||||
#endif
|
||||
|
||||
// Definition of compiler
|
||||
|
||||
#define COMPILER_VC 1
|
||||
#define COMPILER_GCC 2
|
||||
#define COMPILER_CLANG 3
|
||||
|
||||
#if defined(_MSC_VER) // Microsoft Visual C compiler
|
||||
#define COMPILER COMPILER_VC
|
||||
#elif defined(__GNUC__) // GNU GCC compiler
|
||||
#define COMPILER COMPILER_GCC
|
||||
#elif defined(__clang__) // Clang compiler
|
||||
#define COMPILER COMPILER_CLANG
|
||||
#else
|
||||
#error-- "Unsupported COMPILER"
|
||||
#endif
|
||||
|
||||
// Definition of the targeted architecture and basic data types
|
||||
|
||||
#define TARGET_AMD64 1
|
||||
#define TARGET_x86 2
|
||||
#define TARGET_ARM 3
|
||||
|
||||
#if defined(_AMD64_)
|
||||
#define TARGET TARGET_AMD64
|
||||
#elif defined(_X86_)
|
||||
#define TARGET TARGET_x86
|
||||
#elif defined(_ARM_)
|
||||
#define TARGET TARGET_ARM
|
||||
#else
|
||||
#error-- "Unsupported ARCHITECTURE"
|
||||
#endif
|
||||
|
||||
#if defined(WINDOWS)
|
||||
#define ALIGN_HEADER(N) __declspec(align(N))
|
||||
#define ALIGN_FOOTER(N)
|
||||
#else
|
||||
#define ALIGN_HEADER(N)
|
||||
#define ALIGN_FOOTER(N) __attribute__((aligned(N)))
|
||||
#endif
|
||||
|
||||
// Selecting implementation: fast, generic or reference
|
||||
#if defined(_FAST_) // The "fast" implementation requires support for AVX2 and AES_NI instructions
|
||||
#define USE_AVX2
|
||||
#define AES_ENABLE_NI
|
||||
#define USE_FAST
|
||||
#elif defined(_FAST_GENERIC_)
|
||||
#define USE_FAST_GENERIC
|
||||
#elif defined(_REFERENCE_)
|
||||
#define USE_REFERENCE
|
||||
#else
|
||||
#error-- unsupported implementation
|
||||
#endif
|
||||
|
||||
// Defining method for generating matrix A
|
||||
#if defined(_AES128_FOR_A_)
|
||||
#define USE_AES128_FOR_A
|
||||
#elif defined(_CSHAKE128_FOR_A_)
|
||||
#define USE_CSHAKE128_FOR_A
|
||||
#else
|
||||
##error -- missing method for generating matrix A
|
||||
#endif
|
||||
|
||||
// Selecting use of OpenSSL's AES functions
|
||||
#if defined(_USE_OPENSSL_)
|
||||
#define USE_OPENSSL
|
||||
#endif
|
||||
|
||||
#endif
|
||||
20
src/kem/frodokem/frodo640_aes.c
Normal file
20
src/kem/frodokem/frodo640_aes.c
Normal file
@ -0,0 +1,20 @@
|
||||
/********************************************************************************************
|
||||
* FrodoKEM: Learning with Errors Key Encapsulation
|
||||
*
|
||||
* Abstract: functions for FrodoKEM-640
|
||||
* Instantiates "frodo_macrify.c" with the necessary matrix arithmetic functions
|
||||
*********************************************************************************************/
|
||||
|
||||
#include "frodo640_params.h"
|
||||
#define _AES128_FOR_A_
|
||||
|
||||
// Selecting cSHAKE XOF function for the KEM and noise sampling
|
||||
#define cshake OQS_SHA3_cshake128_simple
|
||||
|
||||
#define crypto_kem_keypair OQS_KEM_frodokem_640_aes_keypair
|
||||
#define crypto_kem_enc OQS_KEM_frodokem_640_aes_encaps
|
||||
#define crypto_kem_dec OQS_KEM_frodokem_640_aes_decaps
|
||||
|
||||
#include "frodo_macrify.h"
|
||||
#include "kem.c"
|
||||
#include "frodo_macrify.c"
|
||||
20
src/kem/frodokem/frodo640_cshake.c
Normal file
20
src/kem/frodokem/frodo640_cshake.c
Normal file
@ -0,0 +1,20 @@
|
||||
/********************************************************************************************
|
||||
* FrodoKEM: Learning with Errors Key Encapsulation
|
||||
*
|
||||
* Abstract: functions for FrodoKEM-640
|
||||
* Instantiates "frodo_macrify.c" with the necessary matrix arithmetic functions
|
||||
*********************************************************************************************/
|
||||
|
||||
#include "frodo640_params.h"
|
||||
#define _CSHAKE128_FOR_A_
|
||||
|
||||
// Selecting cSHAKE XOF function for the KEM and noise sampling
|
||||
#define cshake OQS_SHA3_cshake128_simple
|
||||
|
||||
#define crypto_kem_keypair OQS_KEM_frodokem_640_cshake_keypair
|
||||
#define crypto_kem_enc OQS_KEM_frodokem_640_cshake_encaps
|
||||
#define crypto_kem_dec OQS_KEM_frodokem_640_cshake_decaps
|
||||
|
||||
#include "frodo_macrify.h"
|
||||
#include "kem.c"
|
||||
#include "frodo_macrify.c"
|
||||
34
src/kem/frodokem/frodo640_params.h
Normal file
34
src/kem/frodokem/frodo640_params.h
Normal file
@ -0,0 +1,34 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#define CRYPTO_SECRETKEYBYTES 19872 // sizeof(s) + CRYPTO_PUBLICKEYBYTES + 2*PARAMS_N*PARAMS_NBAR
|
||||
#define CRYPTO_PUBLICKEYBYTES 9616 // sizeof(seed_A) + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8
|
||||
#define CRYPTO_BYTES 16
|
||||
#define CRYPTO_CIPHERTEXTBYTES 9736 // (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 + (PARAMS_LOGQ*PARAMS_NBAR*PARAMS_NBAR)/8 + CRYPTO_BYTES
|
||||
|
||||
#define PARAMS_N 640
|
||||
#define PARAMS_NBAR 8
|
||||
#define PARAMS_LOGQ 15
|
||||
#define PARAMS_Q (1 << PARAMS_LOGQ)
|
||||
#define PARAMS_EXTRACTED_BITS 2
|
||||
#define PARAMS_STRIPE_STEP 8
|
||||
#define PARAMS_PARALLEL 4
|
||||
#define BYTES_SEED_A 16
|
||||
#define BYTES_MU (PARAMS_EXTRACTED_BITS * PARAMS_NBAR * PARAMS_NBAR) / 8
|
||||
|
||||
// CDF table
|
||||
static uint16_t CDF_TABLE[12] = {4727, 13584, 20864, 26113, 29434, 31278, 32176, 32560, 32704, 32751, 32764, 32767};
|
||||
static uint16_t CDF_TABLE_LEN = 12;
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define WINDOWS
|
||||
#else
|
||||
#define NIX
|
||||
#endif
|
||||
|
||||
#if defined(__amd64) || defined(__x86_64)
|
||||
#define _AMD64_
|
||||
#elif defined(__i386)
|
||||
#define _X86_
|
||||
#endif
|
||||
|
||||
#define _FAST_GENERIC_
|
||||
20
src/kem/frodokem/frodo976_aes.c
Normal file
20
src/kem/frodokem/frodo976_aes.c
Normal file
@ -0,0 +1,20 @@
|
||||
/********************************************************************************************
|
||||
* FrodoKEM: Learning with Errors Key Encapsulation
|
||||
*
|
||||
* Abstract: functions for FrodoKEM-976
|
||||
* Instantiates "frodo_macrify.c" with the necessary matrix arithmetic functions
|
||||
*********************************************************************************************/
|
||||
|
||||
#include "frodo976_params.h"
|
||||
#define _AES128_FOR_A_
|
||||
|
||||
// Selecting cSHAKE XOF function for the KEM and noise sampling
|
||||
#define cshake OQS_SHA3_cshake256_simple
|
||||
|
||||
#define crypto_kem_keypair OQS_KEM_frodokem_976_aes_keypair
|
||||
#define crypto_kem_enc OQS_KEM_frodokem_976_aes_encaps
|
||||
#define crypto_kem_dec OQS_KEM_frodokem_976_aes_decaps
|
||||
|
||||
#include "frodo_macrify.h"
|
||||
#include "kem.c"
|
||||
#include "frodo_macrify.c"
|
||||
20
src/kem/frodokem/frodo976_cshake.c
Normal file
20
src/kem/frodokem/frodo976_cshake.c
Normal file
@ -0,0 +1,20 @@
|
||||
/********************************************************************************************
|
||||
* FrodoKEM: Learning with Errors Key Encapsulation
|
||||
*
|
||||
* Abstract: functions for FrodoKEM-976
|
||||
* Instantiates "frodo_macrify.c" with the necessary matrix arithmetic functions
|
||||
*********************************************************************************************/
|
||||
|
||||
#include "frodo976_params.h"
|
||||
#define _CSHAKE128_FOR_A_
|
||||
|
||||
// Selecting cSHAKE XOF function for the KEM and noise sampling
|
||||
#define cshake OQS_SHA3_cshake256_simple
|
||||
|
||||
#define crypto_kem_keypair OQS_KEM_frodokem_976_cshake_keypair
|
||||
#define crypto_kem_enc OQS_KEM_frodokem_976_cshake_encaps
|
||||
#define crypto_kem_dec OQS_KEM_frodokem_976_cshake_decaps
|
||||
|
||||
#include "frodo_macrify.h"
|
||||
#include "kem.c"
|
||||
#include "frodo_macrify.c"
|
||||
34
src/kem/frodokem/frodo976_params.h
Normal file
34
src/kem/frodokem/frodo976_params.h
Normal file
@ -0,0 +1,34 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#define CRYPTO_SECRETKEYBYTES 31272 // sizeof(s) + CRYPTO_PUBLICKEYBYTES + 2*PARAMS_N*PARAMS_NBAR
|
||||
#define CRYPTO_PUBLICKEYBYTES 15632 // sizeof(seed_A) + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8
|
||||
#define CRYPTO_BYTES 24
|
||||
#define CRYPTO_CIPHERTEXTBYTES 15768 // (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 + (PARAMS_LOGQ*PARAMS_NBAR*PARAMS_NBAR)/8 + CRYPTO_BYTES
|
||||
|
||||
#define PARAMS_N 976
|
||||
#define PARAMS_NBAR 8
|
||||
#define PARAMS_LOGQ 16
|
||||
#define PARAMS_Q (1 << PARAMS_LOGQ)
|
||||
#define PARAMS_EXTRACTED_BITS 3
|
||||
#define PARAMS_STRIPE_STEP 8
|
||||
#define PARAMS_PARALLEL 4
|
||||
#define BYTES_SEED_A 16
|
||||
#define BYTES_MU (PARAMS_EXTRACTED_BITS * PARAMS_NBAR * PARAMS_NBAR) / 8
|
||||
|
||||
// CDF table
|
||||
static uint16_t CDF_TABLE[11] = {5638, 15915, 23689, 28571, 31116, 32217, 32613, 32731, 32760, 32766, 32767};
|
||||
static uint16_t CDF_TABLE_LEN = 11;
|
||||
|
||||
#if defined(_WIN32)
|
||||
#define WINDOWS
|
||||
#else
|
||||
#define NIX
|
||||
#endif
|
||||
|
||||
#if defined(__amd64) || defined(__x86_64)
|
||||
#define _AMD64_
|
||||
#elif defined(__i386)
|
||||
#define _X86_
|
||||
#endif
|
||||
|
||||
#define _FAST_GENERIC_
|
||||
342
src/kem/frodokem/frodo_macrify.c
Normal file
342
src/kem/frodokem/frodo_macrify.c
Normal file
@ -0,0 +1,342 @@
|
||||
/********************************************************************************************
|
||||
* FrodoKEM: Learning with Errors Key Encapsulation
|
||||
*
|
||||
* Abstract: matrix arithmetic functions used by the KEM
|
||||
*********************************************************************************************/
|
||||
|
||||
#import <oqs/aes.h>
|
||||
|
||||
#if defined(USE_AVX2)
|
||||
#include <immintrin.h>
|
||||
#endif
|
||||
|
||||
static int frodo_mul_add_as_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A) { // Generate-and-multiply: generate matrix A (N x N) row-wise, multiply by s on the right.
|
||||
// Inputs: s, e (N x N_BAR)
|
||||
// Output: out = A*s + e (N x N_BAR)
|
||||
int i, j, k;
|
||||
ALIGN_HEADER(32)
|
||||
int16_t a_row[4 * PARAMS_N] ALIGN_FOOTER(32) = {0};
|
||||
|
||||
for (i = 0; i < (PARAMS_N * PARAMS_NBAR); i += 2) {
|
||||
*((uint32_t *) &out[i]) = *((uint32_t *) &e[i]);
|
||||
}
|
||||
|
||||
#if defined(USE_AES128_FOR_A)
|
||||
int16_t a_row_temp[4 * PARAMS_N] = {0}; // Take four lines of A at once
|
||||
void *aes_key_schedule = NULL;
|
||||
OQS_AES128_load_schedule(seed_A, &aes_key_schedule, 1);
|
||||
|
||||
for (j = 0; j < PARAMS_N; j += PARAMS_STRIPE_STEP) {
|
||||
a_row_temp[j + 1 + 0 * PARAMS_N] = j; // Loading values in the little-endian order
|
||||
a_row_temp[j + 1 + 1 * PARAMS_N] = j;
|
||||
a_row_temp[j + 1 + 2 * PARAMS_N] = j;
|
||||
a_row_temp[j + 1 + 3 * PARAMS_N] = j;
|
||||
}
|
||||
|
||||
for (i = 0; i < PARAMS_N; i += 4) {
|
||||
for (j = 0; j < PARAMS_N; j += PARAMS_STRIPE_STEP) { // Go through A, four rows at a time
|
||||
a_row_temp[j + 0 * PARAMS_N] = i + 0; // Loading values in the little-endian order
|
||||
a_row_temp[j + 1 * PARAMS_N] = i + 1;
|
||||
a_row_temp[j + 2 * PARAMS_N] = i + 2;
|
||||
a_row_temp[j + 3 * PARAMS_N] = i + 3;
|
||||
}
|
||||
|
||||
OQS_AES128_ECB_enc_sch((uint8_t *) a_row_temp, 4 * PARAMS_N * sizeof(int16_t), aes_key_schedule, (uint8_t *) a_row);
|
||||
#elif defined(USE_CSHAKE128_FOR_A)
|
||||
#if defined(WINDOWS) | !defined(USE_AVX2)
|
||||
for (i = 0; i < PARAMS_N; i += 4) {
|
||||
OQS_SHA3_cshake128_simple((unsigned char *) (a_row + 0 * PARAMS_N), (unsigned long long) (2 * PARAMS_N), (uint16_t)(256 + i + 0), seed_A, (unsigned long long) BYTES_SEED_A);
|
||||
OQS_SHA3_cshake128_simple((unsigned char *) (a_row + 1 * PARAMS_N), (unsigned long long) (2 * PARAMS_N), (uint16_t)(256 + i + 1), seed_A, (unsigned long long) BYTES_SEED_A);
|
||||
OQS_SHA3_cshake128_simple((unsigned char *) (a_row + 2 * PARAMS_N), (unsigned long long) (2 * PARAMS_N), (uint16_t)(256 + i + 2), seed_A, (unsigned long long) BYTES_SEED_A);
|
||||
OQS_SHA3_cshake128_simple((unsigned char *) (a_row + 3 * PARAMS_N), (unsigned long long) (2 * PARAMS_N), (uint16_t)(256 + i + 3), seed_A, (unsigned long long) BYTES_SEED_A);
|
||||
#else
|
||||
for (i = 0; i < PARAMS_N; i += 4) {
|
||||
cshake128_simple4x((unsigned char *) (a_row), (unsigned char *) (a_row + PARAMS_N), (unsigned char *) (a_row + 2 * PARAMS_N), (unsigned char *) (a_row + 3 * PARAMS_N),
|
||||
(unsigned long long) (2 * PARAMS_N), (uint16_t)(256 + i), (uint16_t)(256 + i + 1), (uint16_t)(256 + i + 2), (uint16_t)(256 + i + 3), seed_A, (unsigned long long) BYTES_SEED_A);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
for (k = 0; k < PARAMS_NBAR; k++) {
|
||||
uint16_t sum[4] = {0};
|
||||
for (j = 0; j < PARAMS_N; j++) { // Matrix-vector multiplication
|
||||
uint16_t sp = s[k * PARAMS_N + j];
|
||||
sum[0] += a_row[0 * PARAMS_N + j] * sp; // Go through four lines with same s
|
||||
sum[1] += a_row[1 * PARAMS_N + j] * sp;
|
||||
sum[2] += a_row[2 * PARAMS_N + j] * sp;
|
||||
sum[3] += a_row[3 * PARAMS_N + j] * sp;
|
||||
}
|
||||
out[(i + 0) * PARAMS_NBAR + k] += sum[0];
|
||||
out[(i + 2) * PARAMS_NBAR + k] += sum[2];
|
||||
out[(i + 1) * PARAMS_NBAR + k] += sum[1];
|
||||
out[(i + 3) * PARAMS_NBAR + k] += sum[3];
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(USE_AES128_FOR_A)
|
||||
OQS_AES128_free_schedule(aes_key_schedule);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int frodo_mul_add_sa_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A) { // Generate-and-multiply: generate matrix A (N x N) column-wise, multiply by s' on the left.
|
||||
// Inputs: s', e' (N_BAR x N)
|
||||
// Output: out = s'*A + e' (N_BAR x N)
|
||||
int i, j, kk;
|
||||
|
||||
for (i = 0; i < (PARAMS_N * PARAMS_NBAR); i += 2) {
|
||||
*((uint32_t *) &out[i]) = *((uint32_t *) &e[i]);
|
||||
}
|
||||
|
||||
#if defined(USE_AES128_FOR_A)
|
||||
int k;
|
||||
uint16_t a_cols[PARAMS_N * PARAMS_STRIPE_STEP] = {0};
|
||||
ALIGN_HEADER(32)
|
||||
uint16_t a_cols_t[PARAMS_N * PARAMS_STRIPE_STEP] ALIGN_FOOTER(32) = {0};
|
||||
uint16_t a_cols_temp[PARAMS_N * PARAMS_STRIPE_STEP] = {0};
|
||||
void *aes_key_schedule = NULL;
|
||||
OQS_AES128_load_schedule(seed_A, &aes_key_schedule, 1);
|
||||
|
||||
for (i = 0, j = 0; i < PARAMS_N; i++, j += PARAMS_STRIPE_STEP) {
|
||||
a_cols_temp[j] = i; // Loading values in the little-endian order
|
||||
}
|
||||
|
||||
for (kk = 0; kk < PARAMS_N; kk += PARAMS_STRIPE_STEP) { // Go through A's columns, 8 (== PARAMS_STRIPE_STEP) columns at a time.
|
||||
for (i = 0; i < (PARAMS_N * PARAMS_STRIPE_STEP); i += PARAMS_STRIPE_STEP) {
|
||||
a_cols_temp[i + 1] = kk; // Loading values in the little-endian order
|
||||
}
|
||||
|
||||
OQS_AES128_ECB_enc_sch((uint8_t *) a_cols_temp, PARAMS_N * PARAMS_STRIPE_STEP * sizeof(int16_t), aes_key_schedule, (uint8_t *) a_cols);
|
||||
|
||||
for (i = 0; i < PARAMS_N; i++) { // Transpose a_cols to have access to it in the column-major order.
|
||||
for (k = 0; k < PARAMS_STRIPE_STEP; k++) {
|
||||
a_cols_t[k * PARAMS_N + i] = a_cols[i * PARAMS_STRIPE_STEP + k];
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(USE_AVX2)
|
||||
for (i = 0; i < PARAMS_NBAR; i++) {
|
||||
for (k = 0; k < PARAMS_STRIPE_STEP; k += PARAMS_PARALLEL) {
|
||||
uint16_t sum[PARAMS_PARALLEL] = {0};
|
||||
for (j = 0; j < PARAMS_N; j++) { // Matrix-vector multiplication
|
||||
uint16_t sp = s[i * PARAMS_N + j];
|
||||
sum[0] += sp * a_cols_t[(k + 0) * PARAMS_N + j];
|
||||
sum[1] += sp * a_cols_t[(k + 1) * PARAMS_N + j];
|
||||
sum[2] += sp * a_cols_t[(k + 2) * PARAMS_N + j];
|
||||
sum[3] += sp * a_cols_t[(k + 3) * PARAMS_N + j];
|
||||
}
|
||||
out[i * PARAMS_N + kk + k + 0] += sum[0];
|
||||
out[i * PARAMS_N + kk + k + 2] += sum[2];
|
||||
out[i * PARAMS_N + kk + k + 1] += sum[1];
|
||||
out[i * PARAMS_N + kk + k + 3] += sum[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
#else // Using vector intrinsics
|
||||
for (i = 0; i < PARAMS_NBAR; i++) {
|
||||
for (k = 0; k < PARAMS_STRIPE_STEP; k += PARAMS_PARALLEL) {
|
||||
ALIGN_HEADER(32)
|
||||
uint32_t sum[8 * PARAMS_PARALLEL] ALIGN_FOOTER(32);
|
||||
__m256i a[PARAMS_PARALLEL], b, acc[PARAMS_PARALLEL];
|
||||
acc[0] = _mm256_setzero_si256();
|
||||
acc[1] = _mm256_setzero_si256();
|
||||
acc[2] = _mm256_setzero_si256();
|
||||
acc[3] = _mm256_setzero_si256();
|
||||
for (j = 0; j < PARAMS_N; j += 16) { // Matrix-vector multiplication
|
||||
b = _mm256_load_si256((__m256i *) &s[i * PARAMS_N + j]);
|
||||
a[0] = _mm256_load_si256((__m256i *) &a_cols_t[(k + 0) * PARAMS_N + j]);
|
||||
a[0] = _mm256_madd_epi16(a[0], b);
|
||||
acc[0] = _mm256_add_epi16(a[0], acc[0]);
|
||||
a[1] = _mm256_load_si256((__m256i *) &a_cols_t[(k + 1) * PARAMS_N + j]);
|
||||
a[1] = _mm256_madd_epi16(a[1], b);
|
||||
acc[1] = _mm256_add_epi16(a[1], acc[1]);
|
||||
a[2] = _mm256_load_si256((__m256i *) &a_cols_t[(k + 2) * PARAMS_N + j]);
|
||||
a[2] = _mm256_madd_epi16(a[2], b);
|
||||
acc[2] = _mm256_add_epi16(a[2], acc[2]);
|
||||
a[3] = _mm256_load_si256((__m256i *) &a_cols_t[(k + 3) * PARAMS_N + j]);
|
||||
a[3] = _mm256_madd_epi16(a[3], b);
|
||||
acc[3] = _mm256_add_epi16(a[3], acc[3]);
|
||||
}
|
||||
_mm256_store_si256((__m256i *) (sum + (8 * 0)), acc[0]);
|
||||
out[i * PARAMS_N + kk + k + 0] += sum[8 * 0 + 0] + sum[8 * 0 + 1] + sum[8 * 0 + 2] + sum[8 * 0 + 3] + sum[8 * 0 + 4] + sum[8 * 0 + 5] + sum[8 * 0 + 6] + sum[8 * 0 + 7];
|
||||
_mm256_store_si256((__m256i *) (sum + (8 * 1)), acc[1]);
|
||||
out[i * PARAMS_N + kk + k + 1] += sum[8 * 1 + 0] + sum[8 * 1 + 1] + sum[8 * 1 + 2] + sum[8 * 1 + 3] + sum[8 * 1 + 4] + sum[8 * 1 + 5] + sum[8 * 1 + 6] + sum[8 * 1 + 7];
|
||||
_mm256_store_si256((__m256i *) (sum + (8 * 2)), acc[2]);
|
||||
out[i * PARAMS_N + kk + k + 2] += sum[8 * 2 + 0] + sum[8 * 2 + 1] + sum[8 * 2 + 2] + sum[8 * 2 + 3] + sum[8 * 2 + 4] + sum[8 * 2 + 5] + sum[8 * 2 + 6] + sum[8 * 2 + 7];
|
||||
_mm256_store_si256((__m256i *) (sum + (8 * 3)), acc[3]);
|
||||
out[i * PARAMS_N + kk + k + 3] += sum[8 * 3 + 0] + sum[8 * 3 + 1] + sum[8 * 3 + 2] + sum[8 * 3 + 3] + sum[8 * 3 + 4] + sum[8 * 3 + 5] + sum[8 * 3 + 6] + sum[8 * 3 + 7];
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
OQS_AES128_free_schedule(aes_key_schedule);
|
||||
|
||||
#elif defined(USE_CSHAKE128_FOR_A) // cSHAKE128
|
||||
int t = 0;
|
||||
ALIGN_HEADER(32)
|
||||
uint16_t a_cols[4 * PARAMS_N] ALIGN_FOOTER(32) = {0};
|
||||
|
||||
#if defined(WINDOWS) | !defined(USE_AVX2)
|
||||
int k;
|
||||
for (kk = 0; kk < PARAMS_N; kk += 4) {
|
||||
OQS_SHA3_cshake128_simple((unsigned char *) (a_cols + 0 * PARAMS_N), (unsigned long long) (2 * PARAMS_N), (uint16_t)(256 + kk + 0), seed_A, (unsigned long long) BYTES_SEED_A);
|
||||
OQS_SHA3_cshake128_simple((unsigned char *) (a_cols + 1 * PARAMS_N), (unsigned long long) (2 * PARAMS_N), (uint16_t)(256 + kk + 1), seed_A, (unsigned long long) BYTES_SEED_A);
|
||||
OQS_SHA3_cshake128_simple((unsigned char *) (a_cols + 2 * PARAMS_N), (unsigned long long) (2 * PARAMS_N), (uint16_t)(256 + kk + 2), seed_A, (unsigned long long) BYTES_SEED_A);
|
||||
OQS_SHA3_cshake128_simple((unsigned char *) (a_cols + 3 * PARAMS_N), (unsigned long long) (2 * PARAMS_N), (uint16_t)(256 + kk + 3), seed_A, (unsigned long long) BYTES_SEED_A);
|
||||
|
||||
for (i = 0; i < PARAMS_NBAR; i++) {
|
||||
uint16_t sum[PARAMS_N] = {0};
|
||||
for (j = 0; j < 4; j++) {
|
||||
uint16_t sp = s[i * PARAMS_N + kk + j];
|
||||
for (k = 0; k < PARAMS_N; k++) { // Matrix-vector multiplication
|
||||
sum[k] += sp * a_cols[(t + j) * PARAMS_N + k];
|
||||
}
|
||||
}
|
||||
for (k = 0; k < PARAMS_N; k++) {
|
||||
out[i * PARAMS_N + k] += sum[k];
|
||||
}
|
||||
}
|
||||
}
|
||||
#else // Using vector intrinsics
|
||||
for (kk = 0; kk < PARAMS_N; kk += 4) {
|
||||
cshake128_simple4x((unsigned char *) (a_cols), (unsigned char *) (a_cols + PARAMS_N), (unsigned char *) (a_cols + 2 * PARAMS_N), (unsigned char *) (a_cols + 3 * PARAMS_N),
|
||||
(unsigned long long) (2 * PARAMS_N), (uint16_t)(256 + kk), (uint16_t)(256 + kk + 1), (uint16_t)(256 + kk + 2), (uint16_t)(256 + kk + 3), seed_A, (unsigned long long) BYTES_SEED_A);
|
||||
|
||||
for (i = 0; i < PARAMS_NBAR; i++) {
|
||||
__m256i a, b0, b1, b2, b3, acc[PARAMS_N / 16];
|
||||
b0 = _mm256_set1_epi16(s[i * PARAMS_N + kk + 0]);
|
||||
b1 = _mm256_set1_epi16(s[i * PARAMS_N + kk + 1]);
|
||||
b2 = _mm256_set1_epi16(s[i * PARAMS_N + kk + 2]);
|
||||
b3 = _mm256_set1_epi16(s[i * PARAMS_N + kk + 3]);
|
||||
for (j = 0; j < PARAMS_N; j += 16) { // Matrix-vector multiplication
|
||||
acc[j / 16] = _mm256_load_si256((__m256i *) &out[i * PARAMS_N + j]);
|
||||
a = _mm256_load_si256((__m256i *) &a_cols[(t + 0) * PARAMS_N + j]);
|
||||
a = _mm256_mullo_epi16(a, b0);
|
||||
acc[j / 16] = _mm256_add_epi16(a, acc[j / 16]);
|
||||
a = _mm256_load_si256((__m256i *) &a_cols[(t + 1) * PARAMS_N + j]);
|
||||
a = _mm256_mullo_epi16(a, b1);
|
||||
acc[j / 16] = _mm256_add_epi16(a, acc[j / 16]);
|
||||
a = _mm256_load_si256((__m256i *) &a_cols[(t + 2) * PARAMS_N + j]);
|
||||
a = _mm256_mullo_epi16(a, b2);
|
||||
acc[j / 16] = _mm256_add_epi16(a, acc[j / 16]);
|
||||
a = _mm256_load_si256((__m256i *) &a_cols[(t + 3) * PARAMS_N + j]);
|
||||
a = _mm256_mullo_epi16(a, b3);
|
||||
acc[j / 16] = _mm256_add_epi16(a, acc[j / 16]);
|
||||
}
|
||||
|
||||
for (j = 0; j < PARAMS_N / 16; j++) {
|
||||
_mm256_store_si256((__m256i *) &out[i * PARAMS_N + 16 * j], acc[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void frodo_mul_bs(uint16_t *out, const uint16_t *b, const uint16_t *s) { // Multiply by s on the right
|
||||
// Inputs: b (N_BAR x N), s (N x N_BAR)
|
||||
// Output: out = b*s (N_BAR x N_BAR)
|
||||
int i, j, k;
|
||||
|
||||
for (i = 0; i < PARAMS_NBAR; i++) {
|
||||
for (j = 0; j < PARAMS_NBAR; j++) {
|
||||
out[i * PARAMS_NBAR + j] = 0;
|
||||
for (k = 0; k < PARAMS_N; k++) {
|
||||
out[i * PARAMS_NBAR + j] += b[i * PARAMS_N + k] * s[j * PARAMS_N + k];
|
||||
}
|
||||
out[i * PARAMS_NBAR + j] = (uint32_t)(out[i * PARAMS_NBAR + j]) & ((1 << PARAMS_LOGQ) - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void frodo_mul_add_sb_plus_e(uint16_t *out, const uint16_t *b, const uint16_t *s, const uint16_t *e) { // Multiply by s on the left
|
||||
// Inputs: b (N x N_BAR), s (N_BAR x N), e (N_BAR x N_BAR)
|
||||
// Output: out = s*b + e (N_BAR x N_BAR)
|
||||
int i, j, k;
|
||||
|
||||
for (k = 0; k < PARAMS_NBAR; k++) {
|
||||
for (i = 0; i < PARAMS_NBAR; i++) {
|
||||
out[k * PARAMS_NBAR + i] = e[k * PARAMS_NBAR + i];
|
||||
for (j = 0; j < PARAMS_N; j++) {
|
||||
out[k * PARAMS_NBAR + i] += s[k * PARAMS_N + j] * b[j * PARAMS_NBAR + i];
|
||||
}
|
||||
out[k * PARAMS_NBAR + i] = (uint32_t)(out[k * PARAMS_NBAR + i]) & ((1 << PARAMS_LOGQ) - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void frodo_add(uint16_t *out, const uint16_t *a, const uint16_t *b) { // Add a and b
|
||||
// Inputs: a, b (N_BAR x N_BAR)
|
||||
// Output: c = a + b
|
||||
|
||||
for (int i = 0; i < (PARAMS_NBAR * PARAMS_NBAR); i++) {
|
||||
out[i] = (a[i] + b[i]) & ((1 << PARAMS_LOGQ) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void frodo_sub(uint16_t *out, const uint16_t *a, const uint16_t *b) { // Subtract a and b
|
||||
// Inputs: a, b (N_BAR x N_BAR)
|
||||
// Output: c = a - b
|
||||
|
||||
for (int i = 0; i < (PARAMS_NBAR * PARAMS_NBAR); i++) {
|
||||
out[i] = (a[i] - b[i]) & ((1 << PARAMS_LOGQ) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void frodo_key_encode(uint16_t *out, const uint16_t *in) { // Encoding
|
||||
unsigned int i, j, npieces_word = 8;
|
||||
unsigned int nwords = (PARAMS_NBAR * PARAMS_NBAR) / 8;
|
||||
uint64_t temp, mask = ((uint64_t) 1 << PARAMS_EXTRACTED_BITS) - 1;
|
||||
uint16_t *pos = out;
|
||||
|
||||
for (i = 0; i < nwords; i++) {
|
||||
temp = 0;
|
||||
for (j = 0; j < PARAMS_EXTRACTED_BITS; j++)
|
||||
temp |= ((uint64_t)((uint8_t *) in)[i * PARAMS_EXTRACTED_BITS + j]) << (8 * j);
|
||||
for (j = 0; j < npieces_word; j++) {
|
||||
*pos = (uint16_t)((temp & mask) << (PARAMS_LOGQ - PARAMS_EXTRACTED_BITS));
|
||||
temp >>= PARAMS_EXTRACTED_BITS;
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void frodo_key_decode(uint16_t *out, const uint16_t *in) { // Decoding
|
||||
unsigned int i, j, index = 0, npieces_word = 8;
|
||||
unsigned int nwords = (PARAMS_NBAR * PARAMS_NBAR) / 8;
|
||||
uint16_t temp, maskex = ((uint16_t) 1 << PARAMS_EXTRACTED_BITS) - 1, maskq = ((uint16_t) 1 << PARAMS_LOGQ) - 1;
|
||||
uint8_t *pos = (uint8_t *) out;
|
||||
uint64_t templong;
|
||||
|
||||
for (i = 0; i < nwords; i++) {
|
||||
templong = 0;
|
||||
for (j = 0; j < npieces_word; j++) { // temp = floor(in*2^{-11}+0.5)
|
||||
temp = ((in[index] & maskq) + (1 << (PARAMS_LOGQ - PARAMS_EXTRACTED_BITS - 1))) >> (PARAMS_LOGQ - PARAMS_EXTRACTED_BITS);
|
||||
templong |= ((uint64_t)(temp & maskex)) << (PARAMS_EXTRACTED_BITS * j);
|
||||
index++;
|
||||
}
|
||||
for (j = 0; j < PARAMS_EXTRACTED_BITS; j++)
|
||||
pos[i * PARAMS_EXTRACTED_BITS + j] = (templong >> (8 * j)) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
static void frodo_sample_n(uint16_t *s, const size_t n) { // Fills vector s with n samples from the noise distribution which requires 16 bits to sample.
|
||||
// The distribution is specified by its CDF.
|
||||
// Input: pseudo-random values (2*n bytes) passed in s. The input is overwritten by the output.
|
||||
unsigned int i, j;
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
uint8_t sample = 0;
|
||||
uint16_t prnd = s[i] >> 1; // Drop the least significant bit
|
||||
uint8_t sign = s[i] & 0x1; // Pick the least significant bit
|
||||
|
||||
// No need to compare with the last value.
|
||||
for (j = 0; j < (unsigned int) (CDF_TABLE_LEN - 1); j++) {
|
||||
// Constant time comparison: 1 if CDF_TABLE[j] < s, 0 otherwise. Uses the fact that CDF_TABLE[j] and s fit in 15 bits.
|
||||
sample += (uint16_t)(CDF_TABLE[j] - prnd) >> 15;
|
||||
}
|
||||
// Assuming that sign is either 0 or 1, flips sample iff sign = 1
|
||||
s[i] = ((-sign) ^ sample) + sign;
|
||||
}
|
||||
}
|
||||
28
src/kem/frodokem/frodo_macrify.h
Normal file
28
src/kem/frodokem/frodo_macrify.h
Normal file
@ -0,0 +1,28 @@
|
||||
/********************************************************************************************
|
||||
* FrodoKEM: Learning with Errors Key Encapsulation
|
||||
*
|
||||
* Abstract: header for internal functions
|
||||
*********************************************************************************************/
|
||||
|
||||
#ifndef _FRODO_MACRIFY_H_
|
||||
#define _FRODO_MACRIFY_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "config.h"
|
||||
|
||||
void oqs_kem_frodokem_pack(unsigned char *out, const size_t outlen, const uint16_t *in, const size_t inlen, const unsigned char lsb);
|
||||
void oqs_kem_frodokem_unpack(uint16_t *out, const size_t outlen, const unsigned char *in, const size_t inlen, const unsigned char lsb);
|
||||
static void frodo_sample_n(uint16_t *s, const size_t n);
|
||||
|
||||
static int frodo_mul_add_as_plus_e(uint16_t *b, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A);
|
||||
static int frodo_mul_add_sa_plus_e(uint16_t *b, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A);
|
||||
static void frodo_mul_add_sb_plus_e(uint16_t *out, const uint16_t *b, const uint16_t *s, const uint16_t *e);
|
||||
static void frodo_mul_bs(uint16_t *out, const uint16_t *b, const uint16_t *s);
|
||||
|
||||
static void frodo_add(uint16_t *out, const uint16_t *a, const uint16_t *b);
|
||||
static void frodo_sub(uint16_t *out, const uint16_t *a, const uint16_t *b);
|
||||
static void frodo_key_encode(uint16_t *out, const uint16_t *in);
|
||||
static void frodo_key_decode(uint16_t *out, const uint16_t *in);
|
||||
|
||||
#endif
|
||||
158
src/kem/frodokem/kem.c
Normal file
158
src/kem/frodokem/kem.c
Normal file
@ -0,0 +1,158 @@
|
||||
/********************************************************************************************
|
||||
* FrodoKEM: Learning with Errors Key Encapsulation
|
||||
*
|
||||
* Abstract: Key Encapsulation Mechanism (KEM) based on Frodo
|
||||
*********************************************************************************************/
|
||||
|
||||
#include <oqs/rand.h>
|
||||
#include <oqs/sha3.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
int crypto_kem_keypair(unsigned char *pk, unsigned char *sk) { // Frodo-KEM's key generation
|
||||
// Outputs: public key pk ( BYTES_SEED_A + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 bytes)
|
||||
// secret key sk (CRYPTO_BYTES + BYTES_SEED_A + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 + 2*PARAMS_N*PARAMS_NBAR bytes)
|
||||
uint16_t B[PARAMS_N * PARAMS_NBAR] = {0}, S[2 * PARAMS_N * PARAMS_NBAR] = {0};
|
||||
uint16_t *E = (uint16_t *) &S[PARAMS_N * PARAMS_NBAR];
|
||||
uint8_t *randomness = sk;
|
||||
|
||||
// Generate the secret value s, the seed for S and E, and the seed for A. Add seed_A to the public key
|
||||
OQS_randombytes(randomness, 2 * CRYPTO_BYTES + BYTES_SEED_A);
|
||||
cshake(pk, BYTES_SEED_A, 0, randomness + 2 * CRYPTO_BYTES, (unsigned long long) (BYTES_SEED_A));
|
||||
|
||||
// Generate S and E, and compute B = A*S + E. Generate A on-the-fly
|
||||
cshake((uint8_t *) S, 2 * PARAMS_N * PARAMS_NBAR * sizeof(uint16_t), 1, randomness + CRYPTO_BYTES, (unsigned long long) (CRYPTO_BYTES));
|
||||
frodo_sample_n(S, PARAMS_N * PARAMS_NBAR);
|
||||
frodo_sample_n(E, PARAMS_N * PARAMS_NBAR);
|
||||
frodo_mul_add_as_plus_e(B, S, E, pk);
|
||||
|
||||
// Encode the second part of the public key
|
||||
oqs_kem_frodokem_pack(pk + BYTES_SEED_A, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, B, PARAMS_N * PARAMS_NBAR, PARAMS_LOGQ);
|
||||
|
||||
// Add pk and S to the secret key
|
||||
memcpy(&sk[CRYPTO_BYTES], pk, CRYPTO_PUBLICKEYBYTES);
|
||||
memcpy(&sk[CRYPTO_BYTES + CRYPTO_PUBLICKEYBYTES], S, 2 * PARAMS_N * PARAMS_NBAR);
|
||||
|
||||
// Cleanup:
|
||||
OQS_MEM_cleanse((void *) S, PARAMS_N * PARAMS_NBAR / 2);
|
||||
OQS_MEM_cleanse((void *) E, PARAMS_N * PARAMS_NBAR / 2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) { // Frodo-KEM's key encapsulation
|
||||
unsigned char randomness[BYTES_MU];
|
||||
uint16_t B[PARAMS_N * PARAMS_NBAR] = {0}, V[PARAMS_NBAR * PARAMS_NBAR] = {0}, C[PARAMS_NBAR * PARAMS_NBAR] = {0};
|
||||
ALIGN_HEADER(32)
|
||||
uint16_t Bp[PARAMS_N * PARAMS_NBAR] ALIGN_FOOTER(32) = {0};
|
||||
ALIGN_HEADER(32)
|
||||
uint16_t Sp[(2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR] ALIGN_FOOTER(32) = {0};
|
||||
uint16_t *Ep = (uint16_t *) &Sp[PARAMS_N * PARAMS_NBAR];
|
||||
uint16_t *Epp = (uint16_t *) &Sp[2 * PARAMS_N * PARAMS_NBAR];
|
||||
uint8_t temp[CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES], G[3 * CRYPTO_BYTES];
|
||||
|
||||
// temp <- pk||mu, and generate (r||KK||d) = G(pk||mu)
|
||||
OQS_randombytes(randomness, BYTES_MU);
|
||||
memcpy(temp, pk, CRYPTO_PUBLICKEYBYTES);
|
||||
memcpy(&temp[CRYPTO_PUBLICKEYBYTES], randomness, BYTES_MU);
|
||||
cshake(G, 3 * CRYPTO_BYTES, 2, temp, (unsigned long long) (CRYPTO_PUBLICKEYBYTES + BYTES_MU));
|
||||
|
||||
// Generate Sp and Ep, and compute Bp = Sp*A + Ep. Generate A on-the-fly
|
||||
cshake((uint8_t *) Sp, (2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR * sizeof(uint16_t), 3, G, (unsigned long long) (CRYPTO_BYTES));
|
||||
frodo_sample_n(Sp, PARAMS_N * PARAMS_NBAR);
|
||||
frodo_sample_n(Ep, PARAMS_N * PARAMS_NBAR);
|
||||
frodo_mul_add_sa_plus_e(Bp, Sp, Ep, temp);
|
||||
oqs_kem_frodokem_pack(ct, (PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8, Bp, PARAMS_N * PARAMS_NBAR, PARAMS_LOGQ);
|
||||
|
||||
// Generate Epp, and compute V = Sp*B + Epp
|
||||
frodo_sample_n(Epp, PARAMS_NBAR * PARAMS_NBAR);
|
||||
oqs_kem_frodokem_unpack(B, PARAMS_N * PARAMS_NBAR, temp + BYTES_SEED_A, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, PARAMS_LOGQ);
|
||||
frodo_mul_add_sb_plus_e(V, B, Sp, Epp);
|
||||
|
||||
// Encode mu, and compute C = V + enc(mu) (mode q)
|
||||
frodo_key_encode(C, (uint16_t *) (temp + CRYPTO_PUBLICKEYBYTES));
|
||||
frodo_add(C, V, C);
|
||||
oqs_kem_frodokem_pack(ct + (PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8, (PARAMS_LOGQ * PARAMS_NBAR * PARAMS_NBAR) / 8, C, PARAMS_NBAR * PARAMS_NBAR, PARAMS_LOGQ);
|
||||
|
||||
// Compute ss = F(ct||KK||d) and the ciphertext CT = ct||d
|
||||
memcpy(temp, ct, CRYPTO_CIPHERTEXTBYTES - CRYPTO_BYTES);
|
||||
memcpy(&temp[CRYPTO_CIPHERTEXTBYTES - CRYPTO_BYTES], &G[CRYPTO_BYTES], 2 * CRYPTO_BYTES);
|
||||
cshake(ss, CRYPTO_BYTES, 4, temp, (unsigned long long) (CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES));
|
||||
memcpy(&ct[CRYPTO_CIPHERTEXTBYTES - CRYPTO_BYTES], &G[2 * CRYPTO_BYTES], CRYPTO_BYTES);
|
||||
|
||||
// Cleanup:
|
||||
OQS_MEM_cleanse((void *) Sp, PARAMS_N * PARAMS_NBAR / 2);
|
||||
OQS_MEM_cleanse((void *) Ep, PARAMS_N * PARAMS_NBAR / 2);
|
||||
OQS_MEM_cleanse((void *) Epp, PARAMS_NBAR * PARAMS_NBAR / 2);
|
||||
OQS_MEM_cleanse((void *) V, PARAMS_NBAR * PARAMS_NBAR / 2);
|
||||
OQS_MEM_cleanse((void *) G, CRYPTO_BYTES / 2);
|
||||
OQS_MEM_cleanse((void *) (temp + CRYPTO_CIPHERTEXTBYTES - CRYPTO_BYTES), CRYPTO_BYTES / 2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) { // Frodo-KEM's key decapsulation
|
||||
uint16_t B[PARAMS_N * PARAMS_NBAR] = {0}, Bp[PARAMS_N * PARAMS_NBAR] = {0}, W[PARAMS_NBAR * PARAMS_NBAR] = {0};
|
||||
uint16_t C[PARAMS_NBAR * PARAMS_NBAR] = {0}, CC[PARAMS_NBAR * PARAMS_NBAR] = {0};
|
||||
uint16_t *S = (uint16_t *) (sk + CRYPTO_BYTES + CRYPTO_PUBLICKEYBYTES);
|
||||
ALIGN_HEADER(32)
|
||||
uint16_t BBp[PARAMS_N * PARAMS_NBAR] ALIGN_FOOTER(32) = {0};
|
||||
ALIGN_HEADER(32)
|
||||
uint16_t Sp[(2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR] ALIGN_FOOTER(32) = {0};
|
||||
uint16_t *Ep = (uint16_t *) &Sp[PARAMS_N * PARAMS_NBAR];
|
||||
uint16_t *Epp = (uint16_t *) &Sp[2 * PARAMS_N * PARAMS_NBAR];
|
||||
uint8_t temp[CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES], G[3 * CRYPTO_BYTES], *seed_A = temp;
|
||||
|
||||
// temp <- pk
|
||||
memcpy(temp, &sk[CRYPTO_BYTES], CRYPTO_PUBLICKEYBYTES);
|
||||
|
||||
// Compute W = C - Bp*S (mod q), and decode the randomness mu
|
||||
oqs_kem_frodokem_unpack(Bp, PARAMS_N * PARAMS_NBAR, ct, (PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8, PARAMS_LOGQ);
|
||||
oqs_kem_frodokem_unpack(C, PARAMS_NBAR * PARAMS_NBAR, ct + (PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8, (PARAMS_LOGQ * PARAMS_NBAR * PARAMS_NBAR) / 8, PARAMS_LOGQ);
|
||||
frodo_mul_bs(W, Bp, S);
|
||||
frodo_sub(W, C, W);
|
||||
frodo_key_decode((uint16_t *) (temp + CRYPTO_PUBLICKEYBYTES), W);
|
||||
|
||||
// Generate (r||KK||d) = G(pk||mu)
|
||||
cshake(G, 3 * CRYPTO_BYTES, 2, temp, (unsigned long long) (CRYPTO_PUBLICKEYBYTES + BYTES_MU));
|
||||
|
||||
// Generate Sp and Ep, and compute BBp = Sp*A + Ep. Generate A on-the-fly
|
||||
cshake((uint8_t *) Sp, (2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR * sizeof(uint16_t), 3, G, (unsigned long long) (CRYPTO_BYTES));
|
||||
frodo_sample_n(Sp, PARAMS_N * PARAMS_NBAR);
|
||||
frodo_sample_n(Ep, PARAMS_N * PARAMS_NBAR);
|
||||
frodo_mul_add_sa_plus_e(BBp, Sp, Ep, seed_A);
|
||||
|
||||
// Generate Epp, and compute W = Sp*B + Epp
|
||||
frodo_sample_n(Epp, PARAMS_NBAR * PARAMS_NBAR);
|
||||
oqs_kem_frodokem_unpack(B, PARAMS_N * PARAMS_NBAR, temp + BYTES_SEED_A, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, PARAMS_LOGQ);
|
||||
frodo_mul_add_sb_plus_e(W, B, Sp, Epp);
|
||||
|
||||
// Encode mu, and compute CC = W + enc(mu) (mode q)
|
||||
frodo_key_encode(CC, (uint16_t *) (temp + CRYPTO_PUBLICKEYBYTES));
|
||||
frodo_add(CC, W, CC);
|
||||
|
||||
// temp <- ct
|
||||
memcpy(temp, ct, CRYPTO_CIPHERTEXTBYTES - CRYPTO_BYTES);
|
||||
|
||||
// Reducing BBp modulo q
|
||||
for (int i = 0; i < PARAMS_N * PARAMS_NBAR; i++)
|
||||
BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1);
|
||||
|
||||
// Is (dd == d & Bp == BBp & C == CC) = true
|
||||
if (memcmp(G + 2 * CRYPTO_BYTES, ct + CRYPTO_CIPHERTEXTBYTES - CRYPTO_BYTES, CRYPTO_BYTES) == 0 &&
|
||||
memcmp(Bp, BBp, 2 * PARAMS_N * PARAMS_NBAR) == 0 &&
|
||||
memcmp(C, CC, 2 * PARAMS_NBAR * PARAMS_NBAR) == 0) { // Load (KK || d) to do ss = F(ct||KK||d)
|
||||
memcpy(&temp[CRYPTO_CIPHERTEXTBYTES - CRYPTO_BYTES], &G[CRYPTO_BYTES], 2 * CRYPTO_BYTES);
|
||||
} else { // Load (s || d) to do ss = F(ct||s||d)
|
||||
memcpy(&temp[CRYPTO_CIPHERTEXTBYTES - CRYPTO_BYTES], sk, CRYPTO_BYTES);
|
||||
memcpy(&temp[CRYPTO_CIPHERTEXTBYTES], &G[2 * CRYPTO_BYTES], CRYPTO_BYTES);
|
||||
}
|
||||
cshake(ss, CRYPTO_BYTES, 4, temp, (unsigned long long) (CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES));
|
||||
|
||||
// Cleanup:
|
||||
OQS_MEM_cleanse((void *) Sp, PARAMS_N * PARAMS_NBAR / 2);
|
||||
OQS_MEM_cleanse((void *) Ep, PARAMS_N * PARAMS_NBAR / 2);
|
||||
OQS_MEM_cleanse((void *) Epp, PARAMS_NBAR * PARAMS_NBAR / 2);
|
||||
OQS_MEM_cleanse((void *) W, PARAMS_NBAR * PARAMS_NBAR / 2);
|
||||
OQS_MEM_cleanse((void *) G, CRYPTO_BYTES / 2);
|
||||
OQS_MEM_cleanse((void *) (temp + CRYPTO_CIPHERTEXTBYTES - CRYPTO_BYTES), CRYPTO_BYTES / 2);
|
||||
return 0;
|
||||
}
|
||||
111
src/kem/frodokem/kem_frodokem.c
Normal file
111
src/kem/frodokem/kem_frodokem.c
Normal file
@ -0,0 +1,111 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <oqs/kem_frodokem.h>
|
||||
|
||||
#ifdef OQS_ENABLE_KEM_frodokem_640_aes
|
||||
|
||||
OQS_KEM *OQS_KEM_frodokem_640_aes_new() {
|
||||
|
||||
OQS_KEM *kem = malloc(sizeof(OQS_KEM));
|
||||
if (kem == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
kem->method_name = OQS_KEM_alg_frodokem_640_aes;
|
||||
|
||||
kem->claimed_nist_level = 1;
|
||||
kem->ind_cca = true;
|
||||
|
||||
kem->length_public_key = OQS_KEM_frodokem_640_aes_length_public_key;
|
||||
kem->length_secret_key = OQS_KEM_frodokem_640_aes_length_secret_key;
|
||||
kem->length_ciphertext = OQS_KEM_frodokem_640_aes_length_ciphertext;
|
||||
kem->length_shared_secret = OQS_KEM_frodokem_640_aes_length_shared_secret;
|
||||
|
||||
kem->keypair = OQS_KEM_frodokem_640_aes_keypair;
|
||||
kem->encaps = OQS_KEM_frodokem_640_aes_encaps;
|
||||
kem->decaps = OQS_KEM_frodokem_640_aes_decaps;
|
||||
|
||||
return kem;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef OQS_ENABLE_KEM_frodokem_976_aes
|
||||
|
||||
OQS_KEM *OQS_KEM_frodokem_976_aes_new() {
|
||||
|
||||
OQS_KEM *kem = malloc(sizeof(OQS_KEM));
|
||||
if (kem == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
kem->method_name = OQS_KEM_alg_frodokem_976_aes;
|
||||
|
||||
kem->claimed_nist_level = 3;
|
||||
kem->ind_cca = true;
|
||||
|
||||
kem->length_public_key = OQS_KEM_frodokem_976_aes_length_public_key;
|
||||
kem->length_secret_key = OQS_KEM_frodokem_976_aes_length_secret_key;
|
||||
kem->length_ciphertext = OQS_KEM_frodokem_976_aes_length_ciphertext;
|
||||
kem->length_shared_secret = OQS_KEM_frodokem_976_aes_length_shared_secret;
|
||||
|
||||
kem->keypair = OQS_KEM_frodokem_976_aes_keypair;
|
||||
kem->encaps = OQS_KEM_frodokem_976_aes_encaps;
|
||||
kem->decaps = OQS_KEM_frodokem_976_aes_decaps;
|
||||
|
||||
return kem;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef OQS_ENABLE_KEM_frodokem_640_cshake
|
||||
|
||||
OQS_KEM *OQS_KEM_frodokem_640_cshake_new() {
|
||||
|
||||
OQS_KEM *kem = malloc(sizeof(OQS_KEM));
|
||||
if (kem == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
kem->method_name = OQS_KEM_alg_frodokem_640_cshake;
|
||||
|
||||
kem->claimed_nist_level = 1;
|
||||
kem->ind_cca = true;
|
||||
|
||||
kem->length_public_key = OQS_KEM_frodokem_640_cshake_length_public_key;
|
||||
kem->length_secret_key = OQS_KEM_frodokem_640_cshake_length_secret_key;
|
||||
kem->length_ciphertext = OQS_KEM_frodokem_640_cshake_length_ciphertext;
|
||||
kem->length_shared_secret = OQS_KEM_frodokem_640_cshake_length_shared_secret;
|
||||
|
||||
kem->keypair = OQS_KEM_frodokem_640_cshake_keypair;
|
||||
kem->encaps = OQS_KEM_frodokem_640_cshake_encaps;
|
||||
kem->decaps = OQS_KEM_frodokem_640_cshake_decaps;
|
||||
|
||||
return kem;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef OQS_ENABLE_KEM_frodokem_976_cshake
|
||||
|
||||
OQS_KEM *OQS_KEM_frodokem_976_cshake_new() {
|
||||
|
||||
OQS_KEM *kem = malloc(sizeof(OQS_KEM));
|
||||
if (kem == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
kem->method_name = OQS_KEM_alg_frodokem_976_cshake;
|
||||
|
||||
kem->claimed_nist_level = 3;
|
||||
kem->ind_cca = true;
|
||||
|
||||
kem->length_public_key = OQS_KEM_frodokem_976_cshake_length_public_key;
|
||||
kem->length_secret_key = OQS_KEM_frodokem_976_cshake_length_secret_key;
|
||||
kem->length_ciphertext = OQS_KEM_frodokem_976_cshake_length_ciphertext;
|
||||
kem->length_shared_secret = OQS_KEM_frodokem_976_cshake_length_shared_secret;
|
||||
|
||||
kem->keypair = OQS_KEM_frodokem_976_cshake_keypair;
|
||||
kem->encaps = OQS_KEM_frodokem_976_cshake_encaps;
|
||||
kem->decaps = OQS_KEM_frodokem_976_cshake_decaps;
|
||||
|
||||
return kem;
|
||||
}
|
||||
|
||||
#endif
|
||||
66
src/kem/frodokem/kem_frodokem.h
Normal file
66
src/kem/frodokem/kem_frodokem.h
Normal file
@ -0,0 +1,66 @@
|
||||
#ifndef __OQS_KEM_FRODOKEM_H
|
||||
#define __OQS_KEM_FRODOKEM_H
|
||||
|
||||
#include <oqs/oqs.h>
|
||||
|
||||
#ifdef OQS_ENABLE_KEM_frodokem_640_aes
|
||||
|
||||
#define OQS_KEM_frodokem_640_aes_length_public_key 9616
|
||||
#define OQS_KEM_frodokem_640_aes_length_secret_key 19872
|
||||
#define OQS_KEM_frodokem_640_aes_length_ciphertext 9736
|
||||
#define OQS_KEM_frodokem_640_aes_length_shared_secret 16
|
||||
|
||||
OQS_KEM *OQS_KEM_frodokem_640_aes_new();
|
||||
|
||||
extern OQS_STATUS OQS_KEM_frodokem_640_aes_keypair(uint8_t *public_key, uint8_t *secret_key);
|
||||
extern OQS_STATUS OQS_KEM_frodokem_640_aes_encaps(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key);
|
||||
extern OQS_STATUS OQS_KEM_frodokem_640_aes_decaps(uint8_t *shared_secret, const unsigned char *ciphertext, const uint8_t *secret_key);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef OQS_ENABLE_KEM_frodokem_976_aes
|
||||
|
||||
#define OQS_KEM_frodokem_976_aes_length_public_key 15632
|
||||
#define OQS_KEM_frodokem_976_aes_length_secret_key 31272
|
||||
#define OQS_KEM_frodokem_976_aes_length_ciphertext 15768
|
||||
#define OQS_KEM_frodokem_976_aes_length_shared_secret 24
|
||||
|
||||
OQS_KEM *OQS_KEM_frodokem_976_aes_new();
|
||||
|
||||
extern OQS_STATUS OQS_KEM_frodokem_976_aes_keypair(uint8_t *public_key, uint8_t *secret_key);
|
||||
extern OQS_STATUS OQS_KEM_frodokem_976_aes_encaps(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key);
|
||||
extern OQS_STATUS OQS_KEM_frodokem_976_aes_decaps(uint8_t *shared_secret, const unsigned char *ciphertext, const uint8_t *secret_key);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef OQS_ENABLE_KEM_frodokem_640_cshake
|
||||
|
||||
#define OQS_KEM_frodokem_640_cshake_length_public_key 9616
|
||||
#define OQS_KEM_frodokem_640_cshake_length_secret_key 19872
|
||||
#define OQS_KEM_frodokem_640_cshake_length_ciphertext 9736
|
||||
#define OQS_KEM_frodokem_640_cshake_length_shared_secret 16
|
||||
|
||||
OQS_KEM *OQS_KEM_frodokem_640_cshake_new();
|
||||
|
||||
extern OQS_STATUS OQS_KEM_frodokem_640_cshake_keypair(uint8_t *public_key, uint8_t *secret_key);
|
||||
extern OQS_STATUS OQS_KEM_frodokem_640_cshake_encaps(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key);
|
||||
extern OQS_STATUS OQS_KEM_frodokem_640_cshake_decaps(uint8_t *shared_secret, const unsigned char *ciphertext, const uint8_t *secret_key);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef OQS_ENABLE_KEM_frodokem_976_cshake
|
||||
|
||||
#define OQS_KEM_frodokem_976_cshake_length_public_key 15632
|
||||
#define OQS_KEM_frodokem_976_cshake_length_secret_key 31272
|
||||
#define OQS_KEM_frodokem_976_cshake_length_ciphertext 15768
|
||||
#define OQS_KEM_frodokem_976_cshake_length_shared_secret 24
|
||||
|
||||
OQS_KEM *OQS_KEM_frodokem_976_cshake_new();
|
||||
|
||||
extern OQS_STATUS OQS_KEM_frodokem_976_cshake_keypair(uint8_t *public_key, uint8_t *secret_key);
|
||||
extern OQS_STATUS OQS_KEM_frodokem_976_cshake_encaps(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key);
|
||||
extern OQS_STATUS OQS_KEM_frodokem_976_cshake_decaps(uint8_t *shared_secret, const unsigned char *ciphertext, const uint8_t *secret_key);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
104
src/kem/frodokem/util.c
Normal file
104
src/kem/frodokem/util.c
Normal file
@ -0,0 +1,104 @@
|
||||
/********************************************************************************************
|
||||
* FrodoKEM: Learning with Errors Key Encapsulation
|
||||
*
|
||||
* Abstract: additional functions for FrodoKEM
|
||||
*********************************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#define min(x, y) (((x) < (y)) ? (x) : (y))
|
||||
|
||||
void oqs_kem_frodokem_pack(unsigned char *out, const size_t outlen, const uint16_t *in, const size_t inlen, const unsigned char lsb) { // Pack the input uint16 vector into a char output vector, copying lsb bits from each input element.
|
||||
// If inlen * lsb / 8 > outlen, only outlen * 8 bits are copied.
|
||||
memset(out, 0, outlen);
|
||||
|
||||
size_t i = 0; // whole bytes already filled in
|
||||
size_t j = 0; // whole uint16_t already copied
|
||||
uint16_t w = 0; // the leftover, not yet copied
|
||||
unsigned char bits = 0; // the number of lsb in w
|
||||
|
||||
while (i < outlen && (j < inlen || ((j == inlen) && (bits > 0)))) {
|
||||
/*
|
||||
in: | | |********|********|
|
||||
^
|
||||
j
|
||||
w : | ****|
|
||||
^
|
||||
bits
|
||||
out:|**|**|**|**|**|**|**|**|* |
|
||||
^^
|
||||
ib
|
||||
*/
|
||||
unsigned char b = 0; // bits in out[i] already filled in
|
||||
while (b < 8) {
|
||||
int nbits = min(8 - b, bits);
|
||||
uint16_t mask = (1 << nbits) - 1;
|
||||
unsigned char t = (w >> (bits - nbits)) & mask; // the bits to copy from w to out
|
||||
out[i] = out[i] + (t << (8 - b - nbits));
|
||||
b += nbits;
|
||||
bits -= nbits;
|
||||
w &= ~(mask << bits); // not strictly necessary; mostly for debugging
|
||||
|
||||
if (bits == 0) {
|
||||
if (j < inlen) {
|
||||
w = in[j];
|
||||
bits = lsb;
|
||||
j++;
|
||||
} else {
|
||||
break; // the input vector is exhausted
|
||||
}
|
||||
}
|
||||
}
|
||||
if (b == 8) { // out[i] is filled in
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void oqs_kem_frodokem_unpack(uint16_t *out, const size_t outlen, const unsigned char *in, const size_t inlen, const unsigned char lsb) { // Unpack the input char vector into a uint16_t output vector, copying lsb bits
|
||||
// for each output element from input. outlen must be at least ceil(inlen * 8 / lsb).
|
||||
memset(out, 0, outlen * sizeof(uint16_t));
|
||||
|
||||
size_t i = 0; // whole uint16_t already filled in
|
||||
size_t j = 0; // whole bytes already copied
|
||||
unsigned char w = 0; // the leftover, not yet copied
|
||||
unsigned char bits = 0; // the number of lsb bits of w
|
||||
|
||||
while (i < outlen && (j < inlen || ((j == inlen) && (bits > 0)))) {
|
||||
/*
|
||||
in: | | | | | | |**|**|...
|
||||
^
|
||||
j
|
||||
w : | *|
|
||||
^
|
||||
bits
|
||||
out:| *****| *****| *** | |...
|
||||
^ ^
|
||||
i b
|
||||
*/
|
||||
unsigned char b = 0; // bits in out[i] already filled in
|
||||
while (b < lsb) {
|
||||
int nbits = min(lsb - b, bits);
|
||||
uint16_t mask = (1 << nbits) - 1;
|
||||
unsigned char t = (w >> (bits - nbits)) & mask; // the bits to copy from w to out
|
||||
out[i] = out[i] + (t << (lsb - b - nbits));
|
||||
b += nbits;
|
||||
bits -= nbits;
|
||||
w &= ~(mask << bits); // not strictly necessary; mostly for debugging
|
||||
|
||||
if (bits == 0) {
|
||||
if (j < inlen) {
|
||||
w = in[j];
|
||||
bits = 8;
|
||||
j++;
|
||||
} else {
|
||||
break; // the input vector is exhausted
|
||||
}
|
||||
}
|
||||
}
|
||||
if (b == lsb) { // out[i] is filled in
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -8,7 +8,8 @@ char *OQS_KEM_alg_identifier(size_t i) {
|
||||
// EDIT-WHEN-ADDING-KEM
|
||||
char *a[OQS_KEM_algs_length] = {
|
||||
OQS_KEM_alg_default,
|
||||
OQS_KEM_alg_sike_p503, OQS_KEM_alg_sike_p751};
|
||||
OQS_KEM_alg_sike_p503, OQS_KEM_alg_sike_p751,
|
||||
OQS_KEM_alg_frodokem_640_aes, OQS_KEM_alg_frodokem_640_cshake, OQS_KEM_alg_frodokem_976_aes, OQS_KEM_alg_frodokem_976_cshake};
|
||||
if (i >= OQS_KEM_algs_length) {
|
||||
return NULL;
|
||||
} else {
|
||||
@ -30,6 +31,30 @@ OQS_KEM *OQS_KEM_new(const char *method_name) {
|
||||
return OQS_KEM_sike_p751_new();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_frodokem_640_aes)) {
|
||||
#ifdef OQS_ENABLE_KEM_frodokem_640_aes
|
||||
return OQS_KEM_frodokem_640_aes_new();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_frodokem_976_aes)) {
|
||||
#ifdef OQS_ENABLE_KEM_frodokem_976_aes
|
||||
return OQS_KEM_frodokem_976_aes_new();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_frodokem_640_cshake)) {
|
||||
#ifdef OQS_ENABLE_KEM_frodokem_640_cshake
|
||||
return OQS_KEM_frodokem_640_cshake_new();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_frodokem_976_cshake)) {
|
||||
#ifdef OQS_ENABLE_KEM_frodokem_976_cshake
|
||||
return OQS_KEM_frodokem_976_cshake_new();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
// EDIT-WHEN-ADDING-KEM
|
||||
} else {
|
||||
|
||||
@ -31,9 +31,17 @@
|
||||
#define OQS_KEM_alg_sike_p503 "Sike-p503"
|
||||
/** Algorithm identifier for Sike p751 KEM. */
|
||||
#define OQS_KEM_alg_sike_p751 "Sike-p751"
|
||||
/** Algorithm identifier for FrodoKEM-640-AES KEM. */
|
||||
#define OQS_KEM_alg_frodokem_640_aes "FrodoKEM-640-AES"
|
||||
/** Algorithm identifier for FrodoKEM-640-cSHAKE KEM. */
|
||||
#define OQS_KEM_alg_frodokem_640_cshake "FrodoKEM-640-cSHAKE"
|
||||
/** Algorithm identifier for FrodoKEM-976-AES KEM. */
|
||||
#define OQS_KEM_alg_frodokem_976_aes "FrodoKEM-976-AES"
|
||||
/** Algorithm identifier for FrodoKEM-976-cSHAKE KEM. */
|
||||
#define OQS_KEM_alg_frodokem_976_cshake "FrodoKEM-976-cSHAKE"
|
||||
// EDIT-WHEN-ADDING-KEM
|
||||
/** Number of algorithm identifiers above. */
|
||||
#define OQS_KEM_algs_length 3
|
||||
#define OQS_KEM_algs_length 7
|
||||
/** The default KEM. */
|
||||
#define OQS_KEM_DEFAULT OQS_KEM_alg_sike_p503
|
||||
|
||||
@ -180,6 +188,7 @@ OQS_STATUS OQS_KEM_decaps(const OQS_KEM *kem, uint8_t *shared_secret, const unsi
|
||||
void OQS_KEM_free(OQS_KEM *kem);
|
||||
|
||||
#include <oqs/kem_sike.h>
|
||||
#include <oqs/kem_frodokem.h>
|
||||
// EDIT-WHEN-ADDING-KEM
|
||||
|
||||
#endif // __OQS_KEM_H
|
||||
|
||||
@ -108,9 +108,9 @@ static const unsigned int strat_Bob[MAX_Bob - 1] = {
|
||||
#define mp_add_asm mp_add503_asm
|
||||
#define mp_addx2_asm mp_add503x2_asm
|
||||
#define mp_subx2_asm mp_sub503x2_asm
|
||||
#define crypto_kem_keypair oqs_kem_sike_p503_keypair
|
||||
#define crypto_kem_enc oqs_kem_sike_p503_enc
|
||||
#define crypto_kem_dec oqs_kem_sike_p503_dec
|
||||
#define crypto_kem_keypair OQS_KEM_sike_p503_keypair
|
||||
#define crypto_kem_enc OQS_KEM_sike_p503_enc
|
||||
#define crypto_kem_dec OQS_KEM_sike_p503_dec
|
||||
#define random_mod_order_A oqs_kem_sike_p503_sidh_random_mod_order_A
|
||||
#define random_mod_order_B oqs_kem_sike_p503_sidh_random_mod_order_B
|
||||
#define EphemeralKeyGeneration_A oqs_kem_sike_p503_sidh_EphemeralKeyGeneration_A
|
||||
|
||||
@ -27,19 +27,19 @@
|
||||
// It produces a private key sk and computes the public key pk.
|
||||
// Outputs: secret key sk (CRYPTO_SECRETKEYBYTES = 434 bytes)
|
||||
// public key pk (CRYPTO_PUBLICKEYBYTES = 378 bytes)
|
||||
int oqs_kem_sike_p503_keypair(unsigned char *pk, unsigned char *sk);
|
||||
int OQS_KEM_sike_p503_keypair(unsigned char *pk, unsigned char *sk);
|
||||
|
||||
// SIKE's encapsulation
|
||||
// Input: public key pk (CRYPTO_PUBLICKEYBYTES = 378 bytes)
|
||||
// Outputs: shared secret ss (CRYPTO_BYTES = 16 bytes)
|
||||
// ciphertext message ct (CRYPTO_CIPHERTEXTBYTES = 402 bytes)
|
||||
int oqs_kem_sike_p503_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk);
|
||||
int OQS_KEM_sike_p503_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk);
|
||||
|
||||
// SIKE's decapsulation
|
||||
// Input: secret key sk (CRYPTO_SECRETKEYBYTES = 434 bytes)
|
||||
// ciphertext message ct (CRYPTO_CIPHERTEXTBYTES = 402 bytes)
|
||||
// Outputs: shared secret ss (CRYPTO_BYTES = 16 bytes)
|
||||
int oqs_kem_sike_p503_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk);
|
||||
int OQS_KEM_sike_p503_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk);
|
||||
|
||||
// Encoding of keys for KEM-based isogeny system "SIKEp503" (wire format):
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
@ -113,9 +113,9 @@ static const unsigned int strat_Bob[MAX_Bob - 1] = {
|
||||
#define mp_add_asm mp_add751_asm
|
||||
#define mp_addx2_asm mp_add751x2_asm
|
||||
#define mp_subx2_asm mp_sub751x2_asm
|
||||
#define crypto_kem_keypair oqs_kem_sike_p751_keypair
|
||||
#define crypto_kem_enc oqs_kem_sike_p751_enc
|
||||
#define crypto_kem_dec oqs_kem_sike_p751_dec
|
||||
#define crypto_kem_keypair OQS_KEM_sike_p751_keypair
|
||||
#define crypto_kem_enc OQS_KEM_sike_p751_enc
|
||||
#define crypto_kem_dec OQS_KEM_sike_p751_dec
|
||||
#define random_mod_order_A oqs_kem_sike_p751_sidh_random_mod_order_A
|
||||
#define random_mod_order_B oqs_kem_sike_p751_sidh_random_mod_order_B
|
||||
#define EphemeralKeyGeneration_A oqs_kem_sike_p751_sidh_EphemeralKeyGeneration_A
|
||||
|
||||
@ -26,19 +26,19 @@
|
||||
// It produces a private key sk and computes the public key pk.
|
||||
// Outputs: secret key sk (CRYPTO_SECRETKEYBYTES = 644 bytes)
|
||||
// public key pk (CRYPTO_PUBLICKEYBYTES = 564 bytes)
|
||||
int oqs_kem_sike_p751_keypair(unsigned char *pk, unsigned char *sk);
|
||||
int OQS_KEM_sike_p751_keypair(unsigned char *pk, unsigned char *sk);
|
||||
|
||||
// SIKE's encapsulation
|
||||
// Input: public key pk (CRYPTO_PUBLICKEYBYTES = 564 bytes)
|
||||
// Outputs: shared secret ss (CRYPTO_BYTES = 24 bytes)
|
||||
// ciphertext message ct (CRYPTO_CIPHERTEXTBYTES = 596 bytes)
|
||||
int oqs_kem_sike_p751_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk);
|
||||
int OQS_KEM_sike_p751_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk);
|
||||
|
||||
// SIKE's decapsulation
|
||||
// Input: secret key sk (CRYPTO_SECRETKEYBYTES = 644 bytes)
|
||||
// ciphertext message ct (CRYPTO_CIPHERTEXTBYTES = 596 bytes)
|
||||
// Outputs: shared secret ss (CRYPTO_BYTES = 24 bytes)
|
||||
int oqs_kem_sike_p751_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk);
|
||||
int OQS_KEM_sike_p751_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk);
|
||||
|
||||
// Encoding of keys for KEM-based isogeny system "SIKEp751" (wire format):
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
@ -22,9 +22,9 @@ OQS_KEM *OQS_KEM_sike_p503_new() {
|
||||
kem->length_ciphertext = OQS_KEM_sike_p503_length_ciphertext;
|
||||
kem->length_shared_secret = OQS_KEM_sike_p503_length_shared_secret;
|
||||
|
||||
kem->keypair = oqs_kem_sike_p503_keypair;
|
||||
kem->encaps = oqs_kem_sike_p503_enc;
|
||||
kem->decaps = oqs_kem_sike_p503_dec;
|
||||
kem->keypair = OQS_KEM_sike_p503_keypair;
|
||||
kem->encaps = OQS_KEM_sike_p503_enc;
|
||||
kem->decaps = OQS_KEM_sike_p503_dec;
|
||||
|
||||
return kem;
|
||||
}
|
||||
@ -51,9 +51,9 @@ OQS_KEM *OQS_KEM_sike_p751_new() {
|
||||
kem->length_ciphertext = OQS_KEM_sike_p751_length_ciphertext;
|
||||
kem->length_shared_secret = OQS_KEM_sike_p751_length_shared_secret;
|
||||
|
||||
kem->keypair = oqs_kem_sike_p751_keypair;
|
||||
kem->encaps = oqs_kem_sike_p751_enc;
|
||||
kem->decaps = oqs_kem_sike_p751_dec;
|
||||
kem->keypair = OQS_KEM_sike_p751_keypair;
|
||||
kem->encaps = OQS_KEM_sike_p751_enc;
|
||||
kem->decaps = OQS_KEM_sike_p751_dec;
|
||||
|
||||
return kem;
|
||||
}
|
||||
|
||||
@ -12,9 +12,9 @@
|
||||
|
||||
OQS_KEM *OQS_KEM_sike_p503_new();
|
||||
|
||||
extern OQS_STATUS OQS_KEM_sike_p503_keypair(uint8_t *public_key, uint8_t *secret_key);
|
||||
extern OQS_STATUS OQS_KEM_sike_p503_encaps(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key);
|
||||
extern OQS_STATUS OQS_KEM_sike_p503_decaps(uint8_t *shared_secret, const unsigned char *ciphertext, const uint8_t *secret_key);
|
||||
OQS_STATUS OQS_KEM_sike_p503_keypair(uint8_t *public_key, uint8_t *secret_key);
|
||||
OQS_STATUS OQS_KEM_sike_p503_encaps(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key);
|
||||
OQS_STATUS OQS_KEM_sike_p503_decaps(uint8_t *shared_secret, const unsigned char *ciphertext, const uint8_t *secret_key);
|
||||
|
||||
#endif
|
||||
|
||||
@ -27,9 +27,9 @@ extern OQS_STATUS OQS_KEM_sike_p503_decaps(uint8_t *shared_secret, const unsigne
|
||||
|
||||
OQS_KEM *OQS_KEM_sike_p751_new();
|
||||
|
||||
extern OQS_STATUS OQS_KEM_sike_p751_keypair(uint8_t *public_key, uint8_t *secret_key);
|
||||
extern OQS_STATUS OQS_KEM_sike_p751_encaps(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key);
|
||||
extern OQS_STATUS OQS_KEM_sike_p751_decaps(uint8_t *shared_secret, const unsigned char *ciphertext, const uint8_t *secret_key);
|
||||
OQS_STATUS OQS_KEM_sike_p751_keypair(uint8_t *public_key, uint8_t *secret_key);
|
||||
OQS_STATUS OQS_KEM_sike_p751_encaps(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key);
|
||||
OQS_STATUS OQS_KEM_sike_p751_decaps(uint8_t *shared_secret, const unsigned char *ciphertext, const uint8_t *secret_key);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
#include <oqs/kex.h>
|
||||
|
||||
#include <oqs/kex_lwe_frodo.h>
|
||||
#include <oqs/kex_ntru.h>
|
||||
#include <oqs/kex_rlwe_newhope.h>
|
||||
#include <oqs/kex_sidh_msr.h>
|
||||
@ -31,12 +30,6 @@ OQS_KEX *OQS_KEX_new(OQS_RAND *rand, enum OQS_KEX_alg_name alg_name, const uint8
|
||||
switch (alg_name) {
|
||||
case OQS_KEX_alg_default:
|
||||
return OQS_KEX_rlwe_newhope_new(rand);
|
||||
case OQS_KEX_alg_lwe_frodo:
|
||||
#ifdef ENABLE_KEX_LWE_FRODO
|
||||
return OQS_KEX_lwe_frodo_new_recommended(rand, seed, seed_len, named_parameters);
|
||||
#else
|
||||
assert(0);
|
||||
#endif
|
||||
case OQS_KEX_alg_code_mcbits:
|
||||
#ifdef ENABLE_CODE_MCBITS
|
||||
return OQS_KEX_code_mcbits_new(rand);
|
||||
|
||||
@ -21,7 +21,6 @@
|
||||
enum OQS_KEX_alg_name {
|
||||
OQS_KEX_alg_default,
|
||||
OQS_KEX_alg_rlwe_newhope,
|
||||
OQS_KEX_alg_lwe_frodo,
|
||||
OQS_KEX_alg_sidh_msr_503,
|
||||
OQS_KEX_alg_sidh_msr_751,
|
||||
OQS_KEX_alg_sike_msr_503,
|
||||
|
||||
@ -23,9 +23,6 @@ struct kex_testcase {
|
||||
|
||||
/* Add new testcases here */
|
||||
struct kex_testcase kex_testcases[] = {
|
||||
#ifdef ENABLE_KEX_LWE_FRODO
|
||||
{OQS_KEX_alg_lwe_frodo, (unsigned char *) "01234567890123456", 16, "recommended", "lwe_frodo_recommended", 0, 100},
|
||||
#endif
|
||||
#ifdef ENABLE_CODE_MCBITS
|
||||
{OQS_KEX_alg_code_mcbits, NULL, 0, NULL, "code_mcbits", 0, 25},
|
||||
#endif
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
noinst_LTLIBRARIES = libfrodo.la
|
||||
|
||||
libfrodo_la_SOURCES = kex_lwe_frodo.c lwe.c lwe_noise.c
|
||||
libfrodo_la_CPPFLAGS = -I../../include -I.
|
||||
libfrodo_la_CPPFLAGS += $(AM_CPPFLAGS)
|
||||
|
||||
@ -1,51 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#if !defined(_WIN32)
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <oqs/common.h>
|
||||
#include <oqs/kex.h>
|
||||
#include <oqs/rand.h>
|
||||
|
||||
#include "kex_lwe_frodo.h"
|
||||
#include "local.h"
|
||||
|
||||
#define LWE_DIV_ROUNDUP(x, y) (((x) + (y) -1) / y)
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
// pre-process code to obtain "recommended" functions
|
||||
#include "recommended.h"
|
||||
#define MACRIFY(NAME) NAME##_recommended
|
||||
#include "kex_lwe_frodo_macrify.c"
|
||||
// undefine macros to avoid any confusion later
|
||||
#include "recommended.h"
|
||||
#undef MACRIFY
|
||||
|
||||
void OQS_KEX_lwe_frodo_alice_priv_free(UNUSED OQS_KEX *k, void *alice_priv) {
|
||||
free(alice_priv);
|
||||
}
|
||||
|
||||
void OQS_KEX_lwe_frodo_free(OQS_KEX *k) {
|
||||
if (!k) {
|
||||
return;
|
||||
}
|
||||
if (k->params) {
|
||||
struct oqs_kex_lwe_frodo_params *params = (struct oqs_kex_lwe_frodo_params *) k->params;
|
||||
free(params->cdf_table);
|
||||
params->cdf_table = NULL;
|
||||
free(params->seed);
|
||||
params->seed = NULL;
|
||||
free(params->param_name);
|
||||
params->param_name = NULL;
|
||||
free(k->params);
|
||||
k->params = NULL;
|
||||
}
|
||||
free(k->named_parameters);
|
||||
k->named_parameters = NULL;
|
||||
free(k->method_name);
|
||||
k->method_name = NULL;
|
||||
free(k);
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
/**
|
||||
* \file kex_lwe_frodo.h
|
||||
* \brief Header for LWE key exchange protocol Frodo.
|
||||
*/
|
||||
|
||||
#ifndef __OQS_KEX_LWE_FRODO_H
|
||||
#define __OQS_KEX_LWE_FRODO_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <oqs/common.h>
|
||||
#include <oqs/kex.h>
|
||||
#include <oqs/rand.h>
|
||||
|
||||
OQS_KEX *OQS_KEX_lwe_frodo_new_recommended(OQS_RAND *rand, const uint8_t *seed, const size_t seed_len, const char *named_parameters);
|
||||
|
||||
OQS_STATUS OQS_KEX_lwe_frodo_alice_0_recommended(OQS_KEX *k, void **alice_priv, uint8_t **alice_msg, size_t *alice_msg_len);
|
||||
OQS_STATUS OQS_KEX_lwe_frodo_bob_recommended(OQS_KEX *k, const uint8_t *alice_msg, const size_t alice_msg_len, uint8_t **bob_msg, size_t *bob_msg_len, uint8_t **key, size_t *key_len);
|
||||
OQS_STATUS OQS_KEX_lwe_frodo_alice_1_recommended(OQS_KEX *k, const void *alice_priv, const uint8_t *bob_msg, const size_t bob_msg_len, uint8_t **key, size_t *key_len);
|
||||
|
||||
void OQS_KEX_lwe_frodo_alice_priv_free(OQS_KEX *k, void *alice_priv);
|
||||
void OQS_KEX_lwe_frodo_free(OQS_KEX *k);
|
||||
|
||||
#endif
|
||||
@ -1,260 +0,0 @@
|
||||
#if defined(_WIN32)
|
||||
#define strdup _strdup // for strdup deprecation warning
|
||||
#endif
|
||||
|
||||
OQS_KEX *MACRIFY(OQS_KEX_lwe_frodo_new)(OQS_RAND *rand, const uint8_t *seed, const size_t seed_len, const char *named_parameters) {
|
||||
|
||||
OQS_KEX *k;
|
||||
struct oqs_kex_lwe_frodo_params *params;
|
||||
|
||||
if ((seed_len == 0) || (seed == NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
k = malloc(sizeof(OQS_KEX));
|
||||
if (k == NULL) {
|
||||
goto err;
|
||||
}
|
||||
k->named_parameters = NULL;
|
||||
k->method_name = NULL;
|
||||
|
||||
k->params = malloc(sizeof(struct oqs_kex_lwe_frodo_params));
|
||||
if (NULL == k->params) {
|
||||
goto err;
|
||||
}
|
||||
params = (struct oqs_kex_lwe_frodo_params *) k->params;
|
||||
params->cdf_table = NULL;
|
||||
params->seed = NULL;
|
||||
params->param_name = NULL;
|
||||
|
||||
k->rand = rand;
|
||||
k->ctx = NULL;
|
||||
k->alice_priv_free = &OQS_KEX_lwe_frodo_alice_priv_free;
|
||||
k->free = &OQS_KEX_lwe_frodo_free;
|
||||
|
||||
if (strcmp(named_parameters, "recommended") == 0) {
|
||||
|
||||
k->alice_0 = &OQS_KEX_lwe_frodo_alice_0_recommended;
|
||||
k->bob = &OQS_KEX_lwe_frodo_bob_recommended;
|
||||
k->alice_1 = &OQS_KEX_lwe_frodo_alice_1_recommended;
|
||||
|
||||
k->method_name = strdup("LWE Frodo recommended");
|
||||
if (NULL == k->method_name) {
|
||||
goto err;
|
||||
}
|
||||
k->estimated_classical_security = 144;
|
||||
k->estimated_quantum_security = 130;
|
||||
k->named_parameters = strdup(named_parameters);
|
||||
if (k->named_parameters == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
params->seed = malloc(seed_len);
|
||||
if (NULL == params->seed) {
|
||||
goto err;
|
||||
}
|
||||
memcpy(params->seed, seed, seed_len);
|
||||
params->seed_len = seed_len;
|
||||
params->param_name = strdup("recommended");
|
||||
if (NULL == params->param_name) {
|
||||
goto err;
|
||||
}
|
||||
params->log2_q = PARAMS_LOG2Q;
|
||||
params->q = PARAMS_Q;
|
||||
params->n = PARAMS_N;
|
||||
params->extracted_bits = PARAMS_EXTRACTED_BITS;
|
||||
params->nbar = PARAMS_NBAR;
|
||||
params->key_bits = PARAMS_KEY_BITS;
|
||||
params->rec_hint_len = PARAMS_REC_HINT_LENGTH;
|
||||
params->pub_len = PARAMS_REC_PUB_LENGTH;
|
||||
params->stripe_step = PARAMS_STRIPE_STEP;
|
||||
params->sampler_num = 12;
|
||||
params->cdf_table_len = 6;
|
||||
params->cdf_table = malloc(params->cdf_table_len * sizeof(uint16_t));
|
||||
if (NULL == params->cdf_table) {
|
||||
goto err;
|
||||
}
|
||||
uint16_t cdf_table_tmp[6] = {602, 1521, 1927, 2031, 2046, 2047};
|
||||
memcpy(params->cdf_table, cdf_table_tmp, sizeof(cdf_table_tmp));
|
||||
} else {
|
||||
goto err;
|
||||
}
|
||||
return k;
|
||||
err:
|
||||
OQS_KEX_lwe_frodo_free(k);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OQS_STATUS MACRIFY(OQS_KEX_lwe_frodo_alice_0)(OQS_KEX *k, void **alice_priv, uint8_t **alice_msg, size_t *alice_msg_len) {
|
||||
|
||||
OQS_STATUS ret;
|
||||
|
||||
struct oqs_kex_lwe_frodo_params *params = (struct oqs_kex_lwe_frodo_params *) k->params;
|
||||
|
||||
*alice_priv = NULL;
|
||||
*alice_msg = NULL;
|
||||
|
||||
/* allocate private key, error, and outgoing message */
|
||||
*alice_priv = malloc(PARAMS_N * PARAMS_NBAR * sizeof(uint16_t));
|
||||
if (*alice_priv == NULL) {
|
||||
goto err;
|
||||
}
|
||||
uint16_t b[PARAMS_N * PARAMS_NBAR];
|
||||
uint16_t e[PARAMS_N * PARAMS_NBAR];
|
||||
|
||||
*alice_msg = malloc(PARAMS_REC_PUB_LENGTH);
|
||||
*alice_msg_len = PARAMS_REC_PUB_LENGTH;
|
||||
if (*alice_msg == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* generate S and E */
|
||||
oqs_kex_lwe_frodo_sample_n(*alice_priv, PARAMS_N * PARAMS_NBAR, params, k->rand);
|
||||
oqs_kex_lwe_frodo_sample_n(e, PARAMS_N * PARAMS_NBAR, params, k->rand);
|
||||
|
||||
/* compute B = AS + E */
|
||||
MACRIFY(oqs_kex_lwe_frodo_mul_add_as_plus_e_on_the_fly)
|
||||
(b, *alice_priv, e, params);
|
||||
|
||||
oqs_kex_lwe_frodo_pack(*alice_msg, PARAMS_REC_PUB_LENGTH, b, PARAMS_N * PARAMS_NBAR, PARAMS_LOG2Q);
|
||||
|
||||
ret = OQS_SUCCESS;
|
||||
goto cleanup;
|
||||
|
||||
err:
|
||||
OQS_MEM_cleanse(e, sizeof(e));
|
||||
free(*alice_msg);
|
||||
*alice_msg = NULL;
|
||||
free(*alice_priv);
|
||||
*alice_priv = NULL;
|
||||
ret = OQS_ERROR;
|
||||
|
||||
cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
OQS_STATUS MACRIFY(OQS_KEX_lwe_frodo_bob)(OQS_KEX *k, const uint8_t *alice_msg, const size_t alice_msg_len, uint8_t **bob_msg, size_t *bob_msg_len, uint8_t **key, size_t *key_len) {
|
||||
|
||||
OQS_STATUS ret;
|
||||
|
||||
struct oqs_kex_lwe_frodo_params *params = (struct oqs_kex_lwe_frodo_params *) k->params;
|
||||
|
||||
uint8_t *bob_rec = NULL;
|
||||
*bob_msg = NULL;
|
||||
*key = NULL;
|
||||
|
||||
/* check length of other party's public key */
|
||||
if (alice_msg_len != PARAMS_REC_PUB_LENGTH) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* allocate private key, errors, outgoing message, and key */
|
||||
uint16_t bob_priv[PARAMS_N * PARAMS_NBAR];
|
||||
uint16_t bprime[PARAMS_N * PARAMS_NBAR];
|
||||
uint16_t eprime[PARAMS_N * PARAMS_NBAR];
|
||||
uint16_t eprimeprime[PARAMS_N * PARAMS_NBAR];
|
||||
uint16_t b[PARAMS_N * PARAMS_NBAR];
|
||||
uint16_t v[PARAMS_N * PARAMS_NBAR];
|
||||
*bob_msg = malloc(PARAMS_REC_PUB_LENGTH + PARAMS_REC_HINT_LENGTH);
|
||||
if (*bob_msg == NULL) {
|
||||
goto err;
|
||||
}
|
||||
bob_rec = *bob_msg + PARAMS_REC_PUB_LENGTH;
|
||||
*key = malloc(PARAMS_KEY_BYTES);
|
||||
if (*key == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* generate S' and E' */
|
||||
oqs_kex_lwe_frodo_sample_n(bob_priv, PARAMS_N * PARAMS_NBAR, params, k->rand);
|
||||
oqs_kex_lwe_frodo_sample_n(eprime, PARAMS_N * PARAMS_NBAR, params, k->rand);
|
||||
|
||||
/* compute B' = S'A + E' */
|
||||
MACRIFY(oqs_kex_lwe_frodo_mul_add_sa_plus_e_on_the_fly)
|
||||
(bprime, bob_priv, eprime, params);
|
||||
|
||||
oqs_kex_lwe_frodo_pack(*bob_msg, PARAMS_REC_PUB_LENGTH, bprime, PARAMS_N * PARAMS_NBAR, PARAMS_LOG2Q);
|
||||
|
||||
/* generate E'' */
|
||||
oqs_kex_lwe_frodo_sample_n(eprimeprime, PARAMS_NBAR * PARAMS_NBAR, params, k->rand);
|
||||
|
||||
/* unpack B */
|
||||
oqs_kex_lwe_frodo_unpack(b, PARAMS_N * PARAMS_NBAR, alice_msg, alice_msg_len, PARAMS_LOG2Q);
|
||||
|
||||
/* compute V = S'B + E'' */
|
||||
MACRIFY(oqs_kex_lwe_frodo_mul_add_sb_plus_e)
|
||||
(v, b, bob_priv, eprimeprime);
|
||||
|
||||
/* compute C = <V>_{2^B} */
|
||||
MACRIFY(oqs_kex_lwe_frodo_crossround2)
|
||||
(bob_rec, v);
|
||||
|
||||
/* compute K = round(V)_{2^B} */
|
||||
MACRIFY(oqs_kex_lwe_frodo_round2)
|
||||
(*key, v);
|
||||
|
||||
*bob_msg_len = PARAMS_REC_PUB_LENGTH + PARAMS_REC_HINT_LENGTH;
|
||||
*key_len = PARAMS_KEY_BYTES;
|
||||
|
||||
ret = OQS_SUCCESS;
|
||||
goto cleanup;
|
||||
|
||||
err:
|
||||
ret = OQS_ERROR;
|
||||
free(*bob_msg);
|
||||
*bob_msg = NULL;
|
||||
OQS_MEM_secure_free(*key, PARAMS_KEY_BYTES);
|
||||
*key = NULL;
|
||||
|
||||
cleanup:
|
||||
OQS_MEM_cleanse(eprime, sizeof(eprime));
|
||||
OQS_MEM_cleanse(eprimeprime, sizeof(eprimeprime));
|
||||
OQS_MEM_cleanse(v, sizeof(v));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
OQS_STATUS MACRIFY(OQS_KEX_lwe_frodo_alice_1)(UNUSED OQS_KEX *k, const void *alice_priv, const uint8_t *bob_msg, const size_t bob_msg_len, uint8_t **key, size_t *key_len) {
|
||||
|
||||
OQS_STATUS ret;
|
||||
*key = NULL;
|
||||
|
||||
/* check length of other party's public key */
|
||||
if (bob_msg_len != PARAMS_REC_PUB_LENGTH + PARAMS_REC_HINT_LENGTH) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* allocate working values and session key */
|
||||
uint16_t bprime[PARAMS_N * PARAMS_NBAR];
|
||||
uint16_t w[PARAMS_N * PARAMS_NBAR];
|
||||
|
||||
*key = malloc(PARAMS_KEY_BYTES);
|
||||
if (*key == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* unpack B' */
|
||||
oqs_kex_lwe_frodo_unpack(bprime, PARAMS_N * PARAMS_NBAR, bob_msg, PARAMS_REC_PUB_LENGTH, PARAMS_LOG2Q);
|
||||
|
||||
/* compute W = B'S */
|
||||
MACRIFY(oqs_kex_lwe_frodo_mul_bs)
|
||||
(w, bprime, (uint16_t *) alice_priv);
|
||||
|
||||
/* compute K = rec(B'S, C) */
|
||||
const uint8_t *bob_rec = bob_msg + PARAMS_REC_PUB_LENGTH;
|
||||
MACRIFY(oqs_kex_lwe_frodo_reconcile)
|
||||
(*key, w, bob_rec);
|
||||
|
||||
*key_len = PARAMS_KEY_BYTES;
|
||||
|
||||
ret = OQS_SUCCESS;
|
||||
goto cleanup;
|
||||
|
||||
err:
|
||||
ret = OQS_ERROR;
|
||||
OQS_MEM_secure_free(*key, PARAMS_KEY_BYTES);
|
||||
*key = NULL;
|
||||
|
||||
cleanup:
|
||||
return ret;
|
||||
}
|
||||
@ -1,42 +0,0 @@
|
||||
#ifndef _OQS_KEX_LWE_FRODO_LOCAL_H_
|
||||
#define _OQS_KEX_LWE_FRODO_LOCAL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <oqs/rand.h>
|
||||
|
||||
struct oqs_kex_lwe_frodo_params {
|
||||
uint8_t *seed;
|
||||
size_t seed_len;
|
||||
char *param_name;
|
||||
uint16_t log2_q;
|
||||
uint16_t q;
|
||||
uint16_t n;
|
||||
uint16_t extracted_bits;
|
||||
uint16_t nbar;
|
||||
uint16_t key_bits;
|
||||
uint16_t rec_hint_len;
|
||||
uint32_t pub_len;
|
||||
uint16_t stripe_step;
|
||||
int sampler_num;
|
||||
uint16_t *cdf_table;
|
||||
size_t cdf_table_len;
|
||||
};
|
||||
|
||||
void oqs_kex_lwe_frodo_crossround2_recommended(unsigned char *out, const uint16_t *in);
|
||||
void oqs_kex_lwe_frodo_round2_recommended(unsigned char *out, uint16_t *in);
|
||||
void oqs_kex_lwe_frodo_reconcile_recommended(unsigned char *out, uint16_t *w, const unsigned char *hint);
|
||||
|
||||
void oqs_kex_lwe_frodo_key_round(uint16_t *vec, const size_t length, const int b);
|
||||
void oqs_kex_lwe_frodo_key_round_hints(uint16_t *vec, const size_t length, const int b, const unsigned char *hint);
|
||||
void oqs_kex_lwe_frodo_pack(unsigned char *out, const size_t outlen, const uint16_t *in, const size_t inlen, const unsigned char lsb);
|
||||
void oqs_kex_lwe_frodo_unpack(uint16_t *out, const size_t outlen, const unsigned char *in, const size_t inlen, const unsigned char lsb);
|
||||
|
||||
void oqs_kex_lwe_frodo_sample_n(uint16_t *s, const size_t n, struct oqs_kex_lwe_frodo_params *params, OQS_RAND *rand);
|
||||
|
||||
void oqs_kex_lwe_frodo_mul_add_as_plus_e_on_the_fly_recommended(uint16_t *b, const uint16_t *s, const uint16_t *e, struct oqs_kex_lwe_frodo_params *params);
|
||||
void oqs_kex_lwe_frodo_mul_add_sa_plus_e_on_the_fly_recommended(uint16_t *b, const uint16_t *s, const uint16_t *e, struct oqs_kex_lwe_frodo_params *params);
|
||||
void oqs_kex_lwe_frodo_mul_add_sb_plus_e_recommended(uint16_t *out, const uint16_t *b, const uint16_t *s, const uint16_t *e);
|
||||
void oqs_kex_lwe_frodo_mul_bs_recommended(uint16_t *out, const uint16_t *b, const uint16_t *s);
|
||||
|
||||
#endif /* _OQS_KEX_LWE_FRODO_LOCAL_H_ */
|
||||
@ -1,150 +0,0 @@
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "local.h"
|
||||
|
||||
#include <oqs/aes.h>
|
||||
|
||||
#define min(x, y) (((x) < (y)) ? (x) : (y))
|
||||
|
||||
// round all elements of a vector to the nearest multiple of 2^b
|
||||
void oqs_kex_lwe_frodo_key_round(uint16_t *vec, const size_t length, const int b) {
|
||||
size_t i;
|
||||
uint16_t negmask = ~((1 << b) - 1);
|
||||
uint16_t half = b > 0 ? 1 << (b - 1) : 0;
|
||||
for (i = 0; i < length; i++) {
|
||||
vec[i] = (vec[i] + half) & negmask;
|
||||
}
|
||||
}
|
||||
|
||||
// Round all elements of a vector to the multiple of 2^b, with a hint for the
|
||||
// direction of rounding when close to the boundary.
|
||||
void oqs_kex_lwe_frodo_key_round_hints(uint16_t *vec, const size_t length, const int b, const unsigned char *hint) {
|
||||
size_t i;
|
||||
uint16_t whole = 1 << b;
|
||||
uint16_t mask = whole - 1;
|
||||
uint16_t negmask = ~mask;
|
||||
uint16_t half = 1 << (b - 1);
|
||||
uint16_t quarter = 1 << (b - 2);
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
uint16_t remainder = vec[i] & mask;
|
||||
uint16_t use_hint = ((remainder + quarter) >> (b - 1)) & 0x1;
|
||||
|
||||
unsigned char h = (hint[i / 8] >> (i % 8)) % 2; // the hint
|
||||
uint16_t shift = use_hint * (2 * h - 1) * quarter;
|
||||
|
||||
// if use_hint = 1 and h = 0, adding -quarter forces rounding down
|
||||
// h = 1, adding quarter forces rounding up
|
||||
|
||||
vec[i] = (vec[i] + half + shift) & negmask;
|
||||
}
|
||||
}
|
||||
|
||||
// Pack the input uint16 vector into a char output vector, copying lsb bits
|
||||
// from each input element. If inlen * lsb / 8 > outlen, only outlen * 8 bits
|
||||
// are copied.
|
||||
void oqs_kex_lwe_frodo_pack(unsigned char *out, const size_t outlen, const uint16_t *in, const size_t inlen, const unsigned char lsb) {
|
||||
memset(out, 0, outlen);
|
||||
|
||||
size_t i = 0; // whole bytes already filled in
|
||||
size_t j = 0; // whole uint16_t already copied
|
||||
uint16_t w = 0; // the leftover, not yet copied
|
||||
unsigned char bits = 0; // the number of lsb in w
|
||||
while (i < outlen && (j < inlen || ((j == inlen) && (bits > 0)))) {
|
||||
/*
|
||||
in: | | |********|********|
|
||||
^
|
||||
j
|
||||
w : | ****|
|
||||
^
|
||||
bits
|
||||
out:|**|**|**|**|**|**|**|**|* |
|
||||
^^
|
||||
ib
|
||||
*/
|
||||
unsigned char b = 0; // bits in out[i] already filled in
|
||||
while (b < 8) {
|
||||
int nbits = min(8 - b, bits);
|
||||
uint16_t mask = (1 << nbits) - 1;
|
||||
unsigned char t = (w >> (bits - nbits)) & mask; // the bits to copy from w to out
|
||||
out[i] += t << (8 - b - nbits);
|
||||
b += nbits;
|
||||
bits -= nbits;
|
||||
w &= ~(mask << bits); // not strictly necessary; mostly for debugging
|
||||
|
||||
if (bits == 0) {
|
||||
if (j < inlen) {
|
||||
w = in[j];
|
||||
bits = lsb;
|
||||
j++;
|
||||
} else {
|
||||
break; // the input vector is exhausted
|
||||
}
|
||||
}
|
||||
}
|
||||
if (b == 8) { // out[i] is filled in
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unpack the input char vector into a uint16_t output vector, copying lsb bits
|
||||
// for each output element from input. outlen must be at least ceil(inlen * 8 /
|
||||
// lsb).
|
||||
void oqs_kex_lwe_frodo_unpack(uint16_t *out, const size_t outlen, const unsigned char *in, const size_t inlen, const unsigned char lsb) {
|
||||
memset(out, 0, outlen * sizeof(uint16_t));
|
||||
|
||||
size_t i = 0; // whole uint16_t already filled in
|
||||
size_t j = 0; // whole bytes already copied
|
||||
unsigned char w = 0; // the leftover, not yet copied
|
||||
unsigned char bits = 0; // the number of lsb bits of w
|
||||
while (i < outlen && (j < inlen || ((j == inlen) && (bits > 0)))) {
|
||||
/*
|
||||
in: | | | | | | |**|**|...
|
||||
^
|
||||
j
|
||||
w : | *|
|
||||
^
|
||||
bits
|
||||
out:| *****| *****| *** | |...
|
||||
^ ^
|
||||
i b
|
||||
*/
|
||||
unsigned char b = 0; // bits in out[i] already filled in
|
||||
while (b < lsb) {
|
||||
int nbits = min(lsb - b, bits);
|
||||
uint16_t mask = (1 << nbits) - 1;
|
||||
unsigned char t = (w >> (bits - nbits)) & mask; // the bits to copy from w to out
|
||||
out[i] += t << (lsb - b - nbits);
|
||||
b += nbits;
|
||||
bits -= nbits;
|
||||
w &= ~(mask << bits); // not strictly necessary; mostly for debugging
|
||||
|
||||
if (bits == 0) {
|
||||
if (j < inlen) {
|
||||
w = in[j];
|
||||
bits = 8;
|
||||
j++;
|
||||
} else {
|
||||
break; // the input vector is exhausted
|
||||
}
|
||||
}
|
||||
}
|
||||
if (b == lsb) { // out[i] is filled in
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// define parameters for "recommended" parameter set
|
||||
#include "recommended.h"
|
||||
// pre-process code to obtain "recommended" functions
|
||||
#define MACRIFY(NAME) NAME##_recommended
|
||||
#include "lwe_macrify.c"
|
||||
// undefine macros to avoid any confusion later
|
||||
#include "recommended.h"
|
||||
#undef MACRIFY
|
||||
@ -1,160 +0,0 @@
|
||||
// [.]_2
|
||||
void MACRIFY(oqs_kex_lwe_frodo_round2)(unsigned char *out, uint16_t *in) {
|
||||
oqs_kex_lwe_frodo_key_round(in, PARAMS_NBAR * PARAMS_NBAR, PARAMS_LOG2Q - PARAMS_EXTRACTED_BITS);
|
||||
for (int i = 0; i < PARAMS_NBAR * PARAMS_NBAR; i++) {
|
||||
in[i] >>= PARAMS_LOG2Q - PARAMS_EXTRACTED_BITS; // drop bits that were zeroed out
|
||||
}
|
||||
|
||||
// out should have enough space for the key
|
||||
oqs_kex_lwe_frodo_pack(out, PARAMS_KEY_BITS / 8, in, PARAMS_NBAR * PARAMS_NBAR, PARAMS_EXTRACTED_BITS);
|
||||
}
|
||||
|
||||
void MACRIFY(oqs_kex_lwe_frodo_crossround2)(unsigned char *out, const uint16_t *in) {
|
||||
// out should have enough space for N_BAR * N_BAR bits
|
||||
memset((unsigned char *) out, 0, PARAMS_REC_HINT_LENGTH);
|
||||
|
||||
uint16_t whole = 1 << (PARAMS_LOG2Q - PARAMS_EXTRACTED_BITS);
|
||||
uint16_t half = whole >> 1;
|
||||
uint16_t mask = whole - 1;
|
||||
|
||||
for (int i = 0; i < PARAMS_NBAR * PARAMS_NBAR; i++) {
|
||||
uint16_t remainder = in[i] & mask;
|
||||
out[i / 8] += (remainder >= half) << (i % 8);
|
||||
}
|
||||
}
|
||||
|
||||
void MACRIFY(oqs_kex_lwe_frodo_reconcile)(unsigned char *out, uint16_t *w, const unsigned char *hint) {
|
||||
oqs_kex_lwe_frodo_key_round_hints(w, PARAMS_NBAR * PARAMS_NBAR, PARAMS_LOG2Q - PARAMS_EXTRACTED_BITS, hint);
|
||||
for (int i = 0; i < PARAMS_NBAR * PARAMS_NBAR; i++) {
|
||||
w[i] >>= PARAMS_LOG2Q - PARAMS_EXTRACTED_BITS; // drop bits that were zeroed out
|
||||
}
|
||||
oqs_kex_lwe_frodo_pack(out, PARAMS_KEY_BITS / 8, w, PARAMS_NBAR * PARAMS_NBAR, PARAMS_EXTRACTED_BITS);
|
||||
}
|
||||
|
||||
// Generate-and-multiply: generate A row-wise, multiply by s on the right.
|
||||
void MACRIFY(oqs_kex_lwe_frodo_mul_add_as_plus_e_on_the_fly)(uint16_t *out, const uint16_t *s, const uint16_t *e, struct oqs_kex_lwe_frodo_params *params) {
|
||||
// A (N x N)
|
||||
// s,e (N x N_BAR)
|
||||
// out = A * s + e (N x N_BAR)
|
||||
|
||||
memcpy(out, e, PARAMS_NBAR * PARAMS_N * sizeof(uint16_t));
|
||||
|
||||
// transpose s to store it in the column-major order
|
||||
uint16_t s_transpose[PARAMS_NBAR * PARAMS_N];
|
||||
for (int j = 0; j < PARAMS_N; j++) {
|
||||
for (int k = 0; k < PARAMS_NBAR; k++) {
|
||||
s_transpose[k * PARAMS_N + j] = s[j * PARAMS_NBAR + k];
|
||||
}
|
||||
}
|
||||
|
||||
assert(params->seed_len == 16);
|
||||
void *aes_key_schedule = NULL;
|
||||
OQS_AES128_load_schedule(params->seed, &aes_key_schedule, 1);
|
||||
|
||||
for (int i = 0; i < PARAMS_N; i++) {
|
||||
uint16_t a_row[PARAMS_N] = {0};
|
||||
// go through A's rows
|
||||
for (int j = 0; j < PARAMS_N; j += PARAMS_STRIPE_STEP) {
|
||||
// Loading values in the little-endian order!
|
||||
a_row[j] = i;
|
||||
a_row[j + 1] = j;
|
||||
}
|
||||
|
||||
OQS_AES128_ECB_enc_sch((uint8_t *) a_row, sizeof(a_row), aes_key_schedule, (uint8_t *) a_row);
|
||||
|
||||
for (int k = 0; k < PARAMS_NBAR; k++) {
|
||||
uint16_t sum = 0;
|
||||
for (int j = 0; j < PARAMS_N; j++) {
|
||||
// matrix-vector multiplication happens here
|
||||
sum += a_row[j] * s_transpose[k * PARAMS_N + j];
|
||||
}
|
||||
out[i * PARAMS_NBAR + k] += sum;
|
||||
//Equivalent to %= PARAMS_Q if PARAMS_Q is a power of 2
|
||||
out[i * PARAMS_NBAR + k] &= PARAMS_Q - 1;
|
||||
}
|
||||
}
|
||||
|
||||
OQS_AES128_free_schedule(aes_key_schedule);
|
||||
}
|
||||
|
||||
// Generate-and-multiply: generate A column-wise, multiply by s' on the left.
|
||||
void MACRIFY(oqs_kex_lwe_frodo_mul_add_sa_plus_e_on_the_fly)(uint16_t *out, const uint16_t *s, const uint16_t *e, struct oqs_kex_lwe_frodo_params *params) {
|
||||
// a (N x N)
|
||||
// s',e' (N_BAR x N)
|
||||
// out = s'a + e' (N_BAR x N)
|
||||
|
||||
memcpy(out, e, PARAMS_NBAR * PARAMS_N * sizeof(uint16_t));
|
||||
|
||||
assert(params->seed_len == 16);
|
||||
|
||||
void *aes_key_schedule = NULL;
|
||||
OQS_AES128_load_schedule(params->seed, &aes_key_schedule, 1);
|
||||
|
||||
for (int kk = 0; kk < PARAMS_N; kk += PARAMS_STRIPE_STEP) {
|
||||
// Go through A's columns, 8 (== PARAMS_STRIPE_STEP) columns at a time.
|
||||
// a_cols stores 8 columns of A at a time.
|
||||
uint16_t a_cols[PARAMS_N * PARAMS_STRIPE_STEP] = {0};
|
||||
for (int i = 0; i < PARAMS_N; i++) {
|
||||
// Loading values in the little-endian order!
|
||||
a_cols[i * PARAMS_STRIPE_STEP] = i;
|
||||
a_cols[i * PARAMS_STRIPE_STEP + 1] = kk;
|
||||
}
|
||||
|
||||
OQS_AES128_ECB_enc_sch((uint8_t *) a_cols, sizeof(a_cols), aes_key_schedule, (uint8_t *) a_cols);
|
||||
|
||||
// transpose a_cols to have access to it in the column-major order.
|
||||
uint16_t a_cols_t[PARAMS_N * PARAMS_STRIPE_STEP];
|
||||
for (int i = 0; i < PARAMS_N; i++) {
|
||||
for (int k = 0; k < PARAMS_STRIPE_STEP; k++) {
|
||||
a_cols_t[k * PARAMS_N + i] = a_cols[i * PARAMS_STRIPE_STEP + k];
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < PARAMS_NBAR; i++) {
|
||||
for (int k = 0; k < PARAMS_STRIPE_STEP; k++) {
|
||||
uint16_t sum = 0;
|
||||
for (int j = 0; j < PARAMS_N; j++) {
|
||||
sum += s[i * PARAMS_N + j] * a_cols_t[k * PARAMS_N + j];
|
||||
}
|
||||
out[i * PARAMS_N + kk + k] += sum;
|
||||
out[i * PARAMS_N + kk + k] &= PARAMS_Q - 1; //Works as long as PARAMS_Q is a power of 2
|
||||
}
|
||||
}
|
||||
}
|
||||
OQS_AES128_free_schedule(aes_key_schedule);
|
||||
}
|
||||
|
||||
// multiply by s on the right
|
||||
void MACRIFY(oqs_kex_lwe_frodo_mul_bs)(uint16_t *out, const uint16_t *b, const uint16_t *s) {
|
||||
// b (N_BAR x N)
|
||||
// s (N x N_BAR)
|
||||
// out = bs
|
||||
for (int i = 0; i < PARAMS_NBAR; i++) {
|
||||
for (int j = 0; j < PARAMS_NBAR; j++) {
|
||||
uint16_t sum = 0;
|
||||
for (int k = 0; k < PARAMS_N; k++) {
|
||||
sum += b[i * PARAMS_N + k] * s[k * PARAMS_NBAR + j];
|
||||
}
|
||||
out[i * PARAMS_NBAR + j] = sum & (PARAMS_Q - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// multiply by s on the left
|
||||
void MACRIFY(oqs_kex_lwe_frodo_mul_add_sb_plus_e)(uint16_t *out, const uint16_t *b, const uint16_t *s, const uint16_t *e) {
|
||||
// b (N x N_BAR)
|
||||
// s (N_BAR x N)
|
||||
// e (N_BAR x N_BAR)
|
||||
// out = sb + e
|
||||
memcpy(out, e, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t));
|
||||
for (int k = 0; k < PARAMS_NBAR; k++) {
|
||||
for (int i = 0; i < PARAMS_NBAR; i++) {
|
||||
uint16_t sum = 0;
|
||||
for (int j = 0; j < PARAMS_N; j++) {
|
||||
sum += s[k * PARAMS_N + j] * b[j * PARAMS_NBAR + i];
|
||||
}
|
||||
out[k * PARAMS_NBAR + i] += sum;
|
||||
out[k * PARAMS_NBAR + i] &= PARAMS_Q - 1; // not really necessary since LWE_Q is a power of 2.
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,136 +0,0 @@
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <oqs/common.h>
|
||||
#include <oqs/rand.h>
|
||||
|
||||
#include "local.h"
|
||||
|
||||
#define RECOMMENDED_N_ARRAY_SIZE (752 * 8)
|
||||
#define RECOMMENDED_CDF_TABLE_LEN 6
|
||||
#if defined(_WIN32)
|
||||
// VS complains about arrays initialized with const param. On Windows,
|
||||
// we use directly the recommended value passed down from calling functions.
|
||||
// Currently there is only one set of params, so that works. Need to fix this
|
||||
// in a more general setting (TODO).
|
||||
#define IS_WINDOWS(windows, nix) (windows)
|
||||
#else
|
||||
#define IS_WINDOWS(windows, nix) (nix)
|
||||
#endif
|
||||
|
||||
static void lwe_sample_n_inverse_8(uint16_t *s, const size_t n, const uint8_t *cdf_table, const size_t cdf_table_len, OQS_RAND *rand) {
|
||||
/* Fills vector s with n samples from the noise distribution which requires
|
||||
* 8 bits to sample. The distribution is specified by its CDF. Super-constant
|
||||
* timing: the CDF table is ingested for every sample.
|
||||
*/
|
||||
|
||||
uint8_t rndvec[IS_WINDOWS(RECOMMENDED_N_ARRAY_SIZE, n)];
|
||||
OQS_RAND_n(rand, rndvec, sizeof(rndvec));
|
||||
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
uint8_t sample = 0;
|
||||
uint8_t rnd = rndvec[i] >> 1; // drop the least significant bit
|
||||
uint8_t sign = rndvec[i] & 0x1; // pick the least significant bit
|
||||
|
||||
// No need to compare with the last value.
|
||||
for (int64_t j = 0; j < (int64_t)(cdf_table_len - 1); j++) {
|
||||
// Constant time comparison: 1 if cdf_table[j] < rnd, 0 otherwise.
|
||||
// Critically uses the fact that cdf_table[j] and rnd fit in 7 bits.
|
||||
sample += (uint8_t)(cdf_table[j] - rnd) >> 7;
|
||||
}
|
||||
// Assuming that sign is either 0 or 1, flips sample iff sign = 1
|
||||
s[i] = ((-sign) ^ sample) + sign;
|
||||
}
|
||||
OQS_MEM_cleanse(rndvec, sizeof(rndvec));
|
||||
}
|
||||
|
||||
static void lwe_sample_n_inverse_12(uint16_t *s, const size_t n, const uint16_t *cdf_table, const size_t cdf_table_len, OQS_RAND *rand) {
|
||||
/* Fills vector s with n samples from the noise distribution which requires
|
||||
* 12 bits to sample. The distribution is specified by its CDF. Super-constant
|
||||
* timing: the CDF table is ingested for every sample.
|
||||
*/
|
||||
|
||||
uint8_t rnd[3 * ((IS_WINDOWS(RECOMMENDED_N_ARRAY_SIZE, n) + 1) / 2)]; // 12 bits of unif randomness per output element
|
||||
OQS_RAND_n(rand, rnd, sizeof(rnd));
|
||||
|
||||
for (size_t i = 0; i < n; i += 2) { // two output elements at a time
|
||||
uint8_t *pRnd = (rnd + 3 * i / 2);
|
||||
|
||||
uint16_t rnd1 = (((pRnd[0] << 8) + pRnd[1]) & 0xFFE0) >> 5; // first 11 bits (0..10)
|
||||
uint16_t rnd2 = (((pRnd[1] << 8) + pRnd[2]) & 0x1FFC) >> 2; // next 11 bits (11..21)
|
||||
|
||||
uint8_t sample1 = 0;
|
||||
uint8_t sample2 = 0;
|
||||
|
||||
// No need to compare with the last value.
|
||||
for (size_t j = 0; j < cdf_table_len - 1; j++) {
|
||||
// Constant time comparison: 1 if LWE_CDF_TABLE[j] < rnd1, 0 otherwise.
|
||||
// Critically uses the fact that LWE_CDF_TABLE[j] and rnd1 fit in 15 bits.
|
||||
sample1 += (uint16_t)(cdf_table[j] - rnd1) >> 15;
|
||||
sample2 += (uint16_t)(cdf_table[j] - rnd2) >> 15;
|
||||
}
|
||||
|
||||
uint8_t sign1 = (pRnd[2] & 0x02) >> 1; // 22nd bit
|
||||
uint8_t sign2 = pRnd[2] & 0x01; // 23rd bit
|
||||
|
||||
// Assuming that sign1 is either 0 or 1, flips sample1 iff sign1 = 1
|
||||
s[i] = ((-sign1) ^ sample1) + sign1;
|
||||
|
||||
if (i + 1 < n) {
|
||||
s[i + 1] = ((-sign2) ^ sample2) + sign2;
|
||||
}
|
||||
}
|
||||
OQS_MEM_cleanse(rnd, sizeof(rnd));
|
||||
}
|
||||
|
||||
static void lwe_sample_n_inverse_16(uint16_t *s, const size_t n, const uint16_t *cdf_table, const size_t cdf_table_len, OQS_RAND *rand) {
|
||||
/* Fills vector s with n samples from the noise distribution which requires
|
||||
* 16 bits to sample. The distribution is specified by its CDF. Super-constant
|
||||
* timing: the CDF table is ingested for every sample.
|
||||
*/
|
||||
|
||||
uint16_t rndvec[IS_WINDOWS(RECOMMENDED_N_ARRAY_SIZE, n)];
|
||||
OQS_RAND_n(rand, (uint8_t *) rndvec, sizeof(rndvec));
|
||||
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
uint8_t sample = 0;
|
||||
uint16_t rnd = rndvec[i] >> 1; // drop the least significant bit
|
||||
uint8_t sign = rndvec[i] & 0x1; // pick the least significant bit
|
||||
|
||||
// No need to compare with the last value.
|
||||
for (size_t j = 0; j < cdf_table_len - 1; j++) {
|
||||
// Constant time comparison: 1 if LWE_CDF_TABLE[j] < rnd, 0 otherwise.
|
||||
// Critically uses the fact that LWE_CDF_TABLE[j] and rnd fit in 15 bits.
|
||||
sample += (uint16_t)(cdf_table[j] - rnd) >> 15;
|
||||
}
|
||||
// Assuming that sign is either 0 or 1, flips sample iff sign = 1
|
||||
s[i] = ((-sign) ^ sample) + sign;
|
||||
}
|
||||
OQS_MEM_cleanse(rndvec, sizeof(rndvec));
|
||||
}
|
||||
|
||||
void oqs_kex_lwe_frodo_sample_n(uint16_t *s, const size_t n, struct oqs_kex_lwe_frodo_params *params, OQS_RAND *rand) {
|
||||
switch (params->sampler_num) {
|
||||
case 8: {
|
||||
// have to copy cdf_table from uint16_t to uint8_t
|
||||
uint8_t cdf_table_8[IS_WINDOWS(RECOMMENDED_CDF_TABLE_LEN, params->cdf_table_len) * sizeof(uint8_t)];
|
||||
|
||||
for (size_t i = 0; i < params->cdf_table_len; i++) {
|
||||
cdf_table_8[i] = (uint8_t) params->cdf_table[i];
|
||||
}
|
||||
lwe_sample_n_inverse_8(s, n, cdf_table_8, params->cdf_table_len, rand);
|
||||
} break;
|
||||
case 12:
|
||||
lwe_sample_n_inverse_12(s, n, params->cdf_table, params->cdf_table_len, rand);
|
||||
break;
|
||||
case 16:
|
||||
lwe_sample_n_inverse_16(s, n, params->cdf_table, params->cdf_table_len, rand);
|
||||
break;
|
||||
default:
|
||||
assert(0); //ERROR
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
//Recommended parameter set. Include twice to undefine
|
||||
|
||||
#ifndef OQS_LWE_FRODO_RECOMMENDED_H
|
||||
#define OQS_LWE_FRODO_RECOMMENDED_H
|
||||
#define PARAMS_N 752
|
||||
#define PARAMS_NBAR 8
|
||||
#define PARAMS_LOG2Q 15
|
||||
#define PARAMS_Q (1 << PARAMS_LOG2Q)
|
||||
#define PARAMS_EXTRACTED_BITS 4
|
||||
#define PARAMS_KEY_BITS 256
|
||||
#define PARAMS_KEY_BYTES (PARAMS_KEY_BITS >> 3)
|
||||
#define PARAMS_STRIPE_STEP 8
|
||||
#define LWE_DIV_ROUNDUP(x, y) (((x) + (y) -1) / y)
|
||||
#define PARAMS_REC_HINT_LENGTH LWE_DIV_ROUNDUP(PARAMS_NBAR *PARAMS_NBAR, 8)
|
||||
#define PARAMS_REC_PUB_LENGTH LWE_DIV_ROUNDUP(PARAMS_N *PARAMS_NBAR *PARAMS_LOG2Q, 8)
|
||||
|
||||
#else
|
||||
|
||||
#undef OQS_LWE_FRODO_RECOMMENDED_H
|
||||
#undef PARAMS_N
|
||||
#undef PARAMS_NBAR
|
||||
#undef PARAMS_LOG2Q
|
||||
#undef PARAMS_Q
|
||||
#undef PARAMS_EXTRACTED_BITS
|
||||
#undef PARAMS_KEY_BITS
|
||||
#undef PARAMS_STRIPE_STEP
|
||||
#undef LWE_DIV_ROUNDUP
|
||||
#undef PARAMS_REC_HINT_LENGTH
|
||||
#endif
|
||||
Loading…
x
Reference in New Issue
Block a user