Merge pull request #513 from open-quantum-safe/ds-add-saber

Add SABER from PQClean
This commit is contained in:
Douglas Stebila 2019-07-04 17:29:06 -04:00 committed by GitHub
commit eda92b0b4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
68 changed files with 3956 additions and 2 deletions

View File

@ -40,6 +40,9 @@ endif
if ENABLE_KEM_NTRU
liboqs_la_LIBADD += src/kem/ntru/libkemntru.la
endif
if ENABLE_KEM_SABER
liboqs_la_LIBADD += src/kem/saber/libkemsaber.la
endif
if ENABLE_SIG_DILITHIUM
liboqs_la_LIBADD += src/sig/dilithium/libsigdilithium.la
@ -72,6 +75,7 @@ installheader_HEADERS= src/oqs.h \
src/kem/kyber/kem_kyber.h \
src/kem/newhope/kem_newhope.h \
src/kem/ntru/kem_ntru.h \
src/kem/saber/kem_saber.h \
src/kem/frodokem/kem_frodokem.h \
src/kem/sike/kem_sike.h \
src/sig/sig.h \
@ -112,6 +116,7 @@ links:
cp -f src/kem/kyber/kem_kyber.h include/oqs
cp -f src/kem/newhope/kem_newhope.h include/oqs
cp -f src/kem/ntru/kem_ntru.h include/oqs
cp -f src/kem/saber/kem_saber.h include/oqs
cp -f src/sig/dilithium/sig_dilithium.h include/oqs
cp -f src/sig/mqdss/sig_mqdss.h include/oqs
##### OQS_COPY_FROM_PQCLEAN_FRAGMENT_LINKS_END

View File

@ -34,6 +34,15 @@ EXPORTS
OQS_KEM_ntru_hrss701_decaps
OQS_KEM_ntru_hrss701_encaps
OQS_KEM_ntru_hrss701_keypair
OQS_KEM_saber_lightsaber_decaps
OQS_KEM_saber_lightsaber_encaps
OQS_KEM_saber_lightsaber_keypair
OQS_KEM_saber_saber_decaps
OQS_KEM_saber_saber_encaps
OQS_KEM_saber_saber_keypair
OQS_KEM_saber_firesaber_decaps
OQS_KEM_saber_firesaber_encaps
OQS_KEM_saber_firesaber_keypair
OQS_KEM_frodokem_640_aes_decaps
OQS_KEM_frodokem_640_aes_encaps
OQS_KEM_frodokem_640_aes_keypair

View File

@ -40,6 +40,7 @@
<ClInclude Include="..\..\src\kem\kyber\kem_kyber.h" />
<ClInclude Include="..\..\src\kem\newhope\kem_newhope.h" />
<ClInclude Include="..\..\src\kem\ntru\kem_ntru.h" />
<ClInclude Include="..\..\src\kem\saber\kem_saber.h" />
<ClInclude Include="..\..\src\sig\dilithium\sig_dilithium.h" />
<ClInclude Include="..\..\src\sig\mqdss\sig_mqdss.h" />
<!-- OQS_COPY_FROM_PQCLEAN_FRAGMENT_CLINCLUDE_END -->
@ -188,6 +189,30 @@
<ClCompile Include="..\..\src\kem\ntru\pqclean_ntruhrss701_clean\poly.c" />
<ClCompile Include="..\..\src\kem\ntru\pqclean_ntruhrss701_clean\sample.c" />
<ClCompile Include="..\..\src\kem\ntru\pqclean_ntruhrss701_clean\verify.c" />
<ClCompile Include="..\..\src\kem\saber\kem_saber_lightsaber.c" />
<ClCompile Include="..\..\src\kem\saber\pqclean_lightsaber_clean\cbd.c" />
<ClCompile Include="..\..\src\kem\saber\pqclean_lightsaber_clean\kem.c" />
<ClCompile Include="..\..\src\kem\saber\pqclean_lightsaber_clean\pack_unpack.c" />
<ClCompile Include="..\..\src\kem\saber\pqclean_lightsaber_clean\poly.c" />
<ClCompile Include="..\..\src\kem\saber\pqclean_lightsaber_clean\poly_mul.c" />
<ClCompile Include="..\..\src\kem\saber\pqclean_lightsaber_clean\SABER_indcpa.c" />
<ClCompile Include="..\..\src\kem\saber\pqclean_lightsaber_clean\verify.c" />
<ClCompile Include="..\..\src\kem\saber\kem_saber_saber.c" />
<ClCompile Include="..\..\src\kem\saber\pqclean_saber_clean\cbd.c" />
<ClCompile Include="..\..\src\kem\saber\pqclean_saber_clean\kem.c" />
<ClCompile Include="..\..\src\kem\saber\pqclean_saber_clean\pack_unpack.c" />
<ClCompile Include="..\..\src\kem\saber\pqclean_saber_clean\poly.c" />
<ClCompile Include="..\..\src\kem\saber\pqclean_saber_clean\poly_mul.c" />
<ClCompile Include="..\..\src\kem\saber\pqclean_saber_clean\SABER_indcpa.c" />
<ClCompile Include="..\..\src\kem\saber\pqclean_saber_clean\verify.c" />
<ClCompile Include="..\..\src\kem\saber\kem_saber_firesaber.c" />
<ClCompile Include="..\..\src\kem\saber\pqclean_firesaber_clean\cbd.c" />
<ClCompile Include="..\..\src\kem\saber\pqclean_firesaber_clean\kem.c" />
<ClCompile Include="..\..\src\kem\saber\pqclean_firesaber_clean\pack_unpack.c" />
<ClCompile Include="..\..\src\kem\saber\pqclean_firesaber_clean\poly.c" />
<ClCompile Include="..\..\src\kem\saber\pqclean_firesaber_clean\poly_mul.c" />
<ClCompile Include="..\..\src\kem\saber\pqclean_firesaber_clean\SABER_indcpa.c" />
<ClCompile Include="..\..\src\kem\saber\pqclean_firesaber_clean\verify.c" />
<ClCompile Include="..\..\src\sig\dilithium\sig_dilithium_2.c" />
<ClCompile Include="..\..\src\sig\dilithium\pqclean_dilithium2_clean\sign.c" />
<ClCompile Include="..\..\src\sig\dilithium\pqclean_dilithium2_clean\polyvec.c" />
@ -417,6 +442,7 @@ copy "$(SolutionDir)..\src\kem\bike\kem_bike.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\kyber\kem_kyber.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\newhope\kem_newhope.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\ntru\kem_ntru.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\saber\kem_saber.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\frodokem\kem_frodokem.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\sike\kem_sike.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\sig\sig.h" "$(SolutionDir)include\oqs\"
@ -458,6 +484,7 @@ copy "$(SolutionDir)..\src\kem\bike\kem_bike.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\kyber\kem_kyber.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\newhope\kem_newhope.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\ntru\kem_ntru.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\saber\kem_saber.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\frodokem\kem_frodokem.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\sike\kem_sike.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\sig\sig.h" "$(SolutionDir)include\oqs\"
@ -499,6 +526,7 @@ copy "$(SolutionDir)..\src\kem\bike\kem_bike.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\kyber\kem_kyber.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\newhope\kem_newhope.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\ntru\kem_ntru.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\saber\kem_saber.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\frodokem\kem_frodokem.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\sike\kem_sike.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\sig\sig.h" "$(SolutionDir)include\oqs\"
@ -548,6 +576,7 @@ copy "$(SolutionDir)..\src\kem\bike\kem_bike.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\kyber\kem_kyber.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\newhope\kem_newhope.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\ntru\kem_ntru.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\saber\kem_saber.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\frodokem\kem_frodokem.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\sike\kem_sike.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\sig\sig.h" "$(SolutionDir)include\oqs\"
@ -596,6 +625,7 @@ copy "$(SolutionDir)..\src\kem\bike\kem_bike.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\kyber\kem_kyber.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\newhope\kem_newhope.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\ntru\kem_ntru.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\saber\kem_saber.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\frodokem\kem_frodokem.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\sike\kem_sike.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\sig\sig.h" "$(SolutionDir)include\oqs\"
@ -641,6 +671,7 @@ copy "$(SolutionDir)..\src\kem\bike\kem_bike.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\kyber\kem_kyber.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\newhope\kem_newhope.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\ntru\kem_ntru.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\saber\kem_saber.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\frodokem\kem_frodokem.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\sike\kem_sike.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\sig\sig.h" "$(SolutionDir)include\oqs\"
@ -686,6 +717,7 @@ copy "$(SolutionDir)..\src\kem\bike\kem_bike.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\kyber\kem_kyber.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\newhope\kem_newhope.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\ntru\kem_ntru.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\saber\kem_saber.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\frodokem\kem_frodokem.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\sike\kem_sike.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\sig\sig.h" "$(SolutionDir)include\oqs\"
@ -739,6 +771,7 @@ copy "$(SolutionDir)..\src\kem\bike\kem_bike.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\kyber\kem_kyber.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\newhope\kem_newhope.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\ntru\kem_ntru.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\saber\kem_saber.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\frodokem\kem_frodokem.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\kem\sike\kem_sike.h" "$(SolutionDir)include\oqs\"
copy "$(SolutionDir)..\src\sig\sig.h" "$(SolutionDir)include\oqs\"

View File

@ -269,6 +269,78 @@
<ClCompile Include="..\..\src\kem\ntru\pqclean_ntruhrss701_clean\verify.c">
<Filter>ntru\hrss701</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kem\saber\kem_saber_lightsaber.c">
<Filter>saber\lightsaber</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kem\saber\pqclean_lightsaber_clean\cbd.c">
<Filter>saber\lightsaber</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kem\saber\pqclean_lightsaber_clean\kem.c">
<Filter>saber\lightsaber</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kem\saber\pqclean_lightsaber_clean\pack_unpack.c">
<Filter>saber\lightsaber</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kem\saber\pqclean_lightsaber_clean\poly.c">
<Filter>saber\lightsaber</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kem\saber\pqclean_lightsaber_clean\poly_mul.c">
<Filter>saber\lightsaber</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kem\saber\pqclean_lightsaber_clean\SABER_indcpa.c">
<Filter>saber\lightsaber</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kem\saber\pqclean_lightsaber_clean\verify.c">
<Filter>saber\lightsaber</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kem\saber\kem_saber_saber.c">
<Filter>saber\saber</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kem\saber\pqclean_saber_clean\cbd.c">
<Filter>saber\saber</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kem\saber\pqclean_saber_clean\kem.c">
<Filter>saber\saber</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kem\saber\pqclean_saber_clean\pack_unpack.c">
<Filter>saber\saber</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kem\saber\pqclean_saber_clean\poly.c">
<Filter>saber\saber</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kem\saber\pqclean_saber_clean\poly_mul.c">
<Filter>saber\saber</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kem\saber\pqclean_saber_clean\SABER_indcpa.c">
<Filter>saber\saber</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kem\saber\pqclean_saber_clean\verify.c">
<Filter>saber\saber</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kem\saber\kem_saber_firesaber.c">
<Filter>saber\firesaber</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kem\saber\pqclean_firesaber_clean\cbd.c">
<Filter>saber\firesaber</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kem\saber\pqclean_firesaber_clean\kem.c">
<Filter>saber\firesaber</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kem\saber\pqclean_firesaber_clean\pack_unpack.c">
<Filter>saber\firesaber</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kem\saber\pqclean_firesaber_clean\poly.c">
<Filter>saber\firesaber</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kem\saber\pqclean_firesaber_clean\poly_mul.c">
<Filter>saber\firesaber</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kem\saber\pqclean_firesaber_clean\SABER_indcpa.c">
<Filter>saber\firesaber</Filter>
</ClCompile>
<ClCompile Include="..\..\src\kem\saber\pqclean_firesaber_clean\verify.c">
<Filter>saber\firesaber</Filter>
</ClCompile>
<ClCompile Include="..\..\src\sig\dilithium\sig_dilithium_2.c">
<Filter>dilithium\2</Filter>
</ClCompile>
@ -533,6 +605,9 @@
<ClInclude Include="..\..\src\kem\ntru\kem_ntru.h">
<Filter>ntru</Filter>
</ClInclude>
<ClInclude Include="..\..\src\kem\saber\kem_saber.h">
<Filter>saber</Filter>
</ClInclude>
<ClInclude Include="..\..\src\sig\dilithium\sig_dilithium.h">
<Filter>dilithium</Filter>
</ClInclude>
@ -741,6 +816,18 @@
<Filter Include="ntru\hrss701">
<UniqueIdentifier>{96485f85-7dd5-4df3-a1cd-769da06d3ada}</UniqueIdentifier>
</Filter>
<Filter Include="saber">
<UniqueIdentifier>{281a0a06-959f-43bb-afc3-d72cf9816fc5}</UniqueIdentifier>
</Filter>
<Filter Include="saber\lightsaber">
<UniqueIdentifier>{64918521-b019-48f6-89c3-ad2ce40a8c72}</UniqueIdentifier>
</Filter>
<Filter Include="saber\saber">
<UniqueIdentifier>{3cbb7630-a3ce-4d70-a37d-8fd780a20aba}</UniqueIdentifier>
</Filter>
<Filter Include="saber\firesaber">
<UniqueIdentifier>{f7014d1d-26fc-4fa6-87b2-0c4552cdc0d2}</UniqueIdentifier>
</Filter>
<Filter Include="dilithium">
<UniqueIdentifier>{2a035f7e-7c7e-4ca3-94ac-140aac970a73}</UniqueIdentifier>
</Filter>

View File

@ -12,6 +12,9 @@
#define OQS_ENABLE_KEM_ntru_hps2048677
#define OQS_ENABLE_KEM_ntru_hps4096821
#define OQS_ENABLE_KEM_ntru_hrss701
#define OQS_ENABLE_KEM_saber_lightsaber
#define OQS_ENABLE_KEM_saber_saber
#define OQS_ENABLE_KEM_saber_firesaber
///// OQS_COPY_FROM_PQCLEAN_FRAGMENT_KEMS_END
#define OQS_ENABLE_KEM_frodokem_640_aes
#define OQS_ENABLE_KEM_frodokem_640_shake

View File

@ -47,6 +47,7 @@ AC_DEFUN([CONFIG_FEATURE_FLAGS],
ARG_DISBL_SET_WRAP([kem-kyber], [kem_kyber], [ENABLE_KEM_KYBER], [src/kem/kyber])
ARG_DISBL_SET_WRAP([kem-newhope], [kem_newhope], [ENABLE_KEM_NEWHOPE], [src/kem/newhope])
ARG_DISBL_SET_WRAP([kem-ntru], [kem_ntru], [ENABLE_KEM_NTRU], [src/kem/ntru])
ARG_DISBL_SET_WRAP([kem-saber], [kem_saber], [ENABLE_KEM_SABER], [src/kem/saber])
ARG_DISBL_SET_WRAP([sig-dilithium], [sig_dilithium], [ENABLE_SIG_DILITHIUM], [src/sig/dilithium])
ARG_DISBL_SET_WRAP([sig-mqdss], [sig_mqdss], [ENABLE_SIG_MQDSS], [src/sig/mqdss])
##### OQS_COPY_FROM_PQCLEAN_FRAGMENT_ARG_DISBL_SET_WRAP_END
@ -100,6 +101,11 @@ AC_DEFUN([CONFIG_FEATURES],
AC_DEFINE(OQS_ENABLE_KEM_ntru_hps4096821, 1, "Define to 1 when NTRU-HPS-4096-821 enabled")
AC_DEFINE(OQS_ENABLE_KEM_ntru_hrss701, 1, "Define to 1 when NTRU-HRSS-701 enabled")
])
AM_COND_IF([ENABLE_KEM_SABER], [
AC_DEFINE(OQS_ENABLE_KEM_saber_lightsaber, 1, "Define to 1 when LightSaber-KEM enabled")
AC_DEFINE(OQS_ENABLE_KEM_saber_saber, 1, "Define to 1 when Saber-KEM enabled")
AC_DEFINE(OQS_ENABLE_KEM_saber_firesaber, 1, "Define to 1 when FireSaber-KEM enabled")
])
AM_COND_IF([ENABLE_SIG_DILITHIUM], [
AC_DEFINE(OQS_ENABLE_SIG_dilithium_2, 1, "Define to 1 when DILITHIUM_2 enabled")
AC_DEFINE(OQS_ENABLE_SIG_dilithium_3, 1, "Define to 1 when DILITHIUM_3 enabled")

View File

@ -77,6 +77,7 @@ AC_CONFIG_FILES([Makefile
src/kem/kyber/Makefile
src/kem/newhope/Makefile
src/kem/ntru/Makefile
src/kem/saber/Makefile
src/kem/frodokem/Makefile
src/kem/sike/Makefile
tests/Makefile

View File

@ -0,0 +1,32 @@
liboqs master branch algorithm datasheet: `kem_saber`
=====================================================
Summary
-------
- **Name**: SABER
- **Algorithm type**: key encapsulation mechanism
- **Main cryptographic assumption**: module learning with rounding
- **Scheme authors**: Jan-Pieter D'Anvers, Angshuman Karmakar, Sujoy Sinha Roy, Frederic Vercauteren
- **Authors' website**: https://www.esat.kuleuven.be/cosic/pqcrypto/saber/
- **Added to liboqs by**: Douglas Stebila
- **NIST Round 2 submission**
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) |
|----------------|:--------------:|:---------------------------:|:-----------------------:|:-----------------------:|:-----------------------:|:--------------------------:|
| LightSaber-KEM | IND-CCA | 1 | 672 | 1568 | 736 | 32 |
| Saber-KEM | IND-CCA | 3 | 992 | 2304 | 1088 | 32 |
| FireSaber-KEM | IND-CCA | 5 | 1312 | 3040 | 1472 | 32 |
Implementation
--------------
- **Source of implementation:** https://github.com/PQClean/PQClean/ based on https://github.com/KULeuven-COSIC/SABER/commit/14ede83f1ff3bcc41f0464543542366c68b55871
- **Implementation version:** https://github.com/PQClean/PQClean/commit/0ed5ba4a30ee509f8227ced5739d8359b5380eb1
- **License:** Public domain
- **Language:** C
- **Constant-time:** Yes
- **Architectures supported in liboqs master branch**: x86, x64

View File

@ -74,6 +74,31 @@ kems:
implementation: clean
sources: ['kem.c', 'owcpa.c', 'pack3.c', 'packq.c', 'poly.c', 'sample.c', 'verify.c']
visual_studio_guid: 96485f85-7dd5-4df3-a1cd-769da06d3ada
-
name: saber
visual_studio_guid: 281a0a06-959f-43bb-afc3-d72cf9816fc5
schemes:
-
scheme: lightsaber
pqclean_scheme: lightsaber
pretty_name_full: LightSaber-KEM
implementation: clean
sources: ['cbd.c', 'kem.c', 'pack_unpack.c', 'poly.c', 'poly_mul.c', 'SABER_indcpa.c', 'verify.c']
visual_studio_guid: 64918521-b019-48f6-89c3-ad2ce40a8c72
-
scheme: saber
pqclean_scheme: saber
pretty_name_full: Saber-KEM
implementation: clean
sources: ['cbd.c', 'kem.c', 'pack_unpack.c', 'poly.c', 'poly_mul.c', 'SABER_indcpa.c', 'verify.c']
visual_studio_guid: 3cbb7630-a3ce-4d70-a37d-8fd780a20aba
-
scheme: firesaber
pqclean_scheme: firesaber
pretty_name_full: FireSaber-KEM
implementation: clean
sources: ['cbd.c', 'kem.c', 'pack_unpack.c', 'poly.c', 'poly_mul.c', 'SABER_indcpa.c', 'verify.c']
visual_studio_guid: f7014d1d-26fc-4fa6-87b2-0c4552cdc0d2
sigs:
-
name: dilithium

View File

@ -1,4 +1,4 @@
{% set unary %}{% for family in instructions['kems'] %}{% for scheme in family['schemes'] %}1{% endfor %}{% endfor %}{% endset %}
/** Number of algorithm identifiers above. */
#define OQS_KEM_algs_length {{ unary|length + 20 }}
#define OQS_KEM_algs_length {{ unary|length + 24 }}

View File

@ -17,6 +17,7 @@ OQS_API const char *OQS_KEM_alg_identifier(size_t i) {
OQS_KEM_alg_kyber_512, OQS_KEM_alg_kyber_768, OQS_KEM_alg_kyber_1024,
OQS_KEM_alg_newhope_512cca, OQS_KEM_alg_newhope_1024cca,
OQS_KEM_alg_ntru_hps2048509, OQS_KEM_alg_ntru_hps2048677, OQS_KEM_alg_ntru_hps4096821, OQS_KEM_alg_ntru_hrss701,
OQS_KEM_alg_saber_lightsaber, OQS_KEM_alg_saber_saber, OQS_KEM_alg_saber_firesaber,
///// OQS_COPY_FROM_PQCLEAN_FRAGMENT_ALG_IDENTIFIER_END
OQS_KEM_alg_frodokem_640_aes, OQS_KEM_alg_frodokem_640_shake, OQS_KEM_alg_frodokem_976_aes, OQS_KEM_alg_frodokem_976_shake, OQS_KEM_alg_frodokem_1344_aes, OQS_KEM_alg_frodokem_1344_shake,
OQS_KEM_alg_sidh_p434, OQS_KEM_alg_sidh_p503, OQS_KEM_alg_sidh_p610, OQS_KEM_alg_sidh_p751,
@ -146,6 +147,24 @@ OQS_API OQS_KEM *OQS_KEM_new(const char *method_name) {
return OQS_KEM_ntru_hrss701_new();
#else
return NULL;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_saber_lightsaber)) {
#ifdef OQS_ENABLE_KEM_saber_lightsaber
return OQS_KEM_saber_lightsaber_new();
#else
return NULL;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_saber_saber)) {
#ifdef OQS_ENABLE_KEM_saber_saber
return OQS_KEM_saber_saber_new();
#else
return NULL;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_saber_firesaber)) {
#ifdef OQS_ENABLE_KEM_saber_firesaber
return OQS_KEM_saber_firesaber_new();
#else
return NULL;
#endif
///// OQS_COPY_FROM_PQCLEAN_FRAGMENT_NEW_CASE_END
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_frodokem_640_aes)) {

View File

@ -68,6 +68,12 @@ extern "C" {
#define OQS_KEM_alg_ntru_hps4096821 "NTRU-HPS-4096-821"
/** Algorithm identifier for NTRU-HRSS-701 KEM. */
#define OQS_KEM_alg_ntru_hrss701 "NTRU-HRSS-701"
/** Algorithm identifier for LightSaber-KEM KEM. */
#define OQS_KEM_alg_saber_lightsaber "LightSaber-KEM"
/** Algorithm identifier for Saber-KEM KEM. */
#define OQS_KEM_alg_saber_saber "Saber-KEM"
/** Algorithm identifier for FireSaber-KEM KEM. */
#define OQS_KEM_alg_saber_firesaber "FireSaber-KEM"
///// OQS_COPY_FROM_PQCLEAN_FRAGMENT_ALG_IDENTIFIER_END
/** Algorithm identifier for FrodoKEM-640-AES KEM. */
#define OQS_KEM_alg_frodokem_640_aes "FrodoKEM-640-AES"
@ -100,7 +106,7 @@ extern "C" {
// EDIT-WHEN-ADDING-KEM
///// OQS_COPY_FROM_PQCLEAN_FRAGMENT_ALGS_LENGTH_START
/** Number of algorithm identifiers above. */
#define OQS_KEM_algs_length 33
#define OQS_KEM_algs_length 36
///// OQS_COPY_FROM_PQCLEAN_FRAGMENT_ALGS_LENGTH_END
/**
@ -268,6 +274,7 @@ OQS_API void OQS_KEM_free(OQS_KEM *kem);
#include <oqs/kem_kyber.h>
#include <oqs/kem_newhope.h>
#include <oqs/kem_ntru.h>
#include <oqs/kem_saber.h>
///// OQS_COPY_FROM_PQCLEAN_FRAGMENT_INCLUDE_END
#include <oqs/kem_frodokem.h>
#include <oqs/kem_sike.h>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,6 @@
count = 0
seed = 061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA1
pk = A92CBDB022F926BCE5679BB3EE3481209318011388EA10E68CD067C9E095775E5E9DB940B6D737646D87298B7984E4FE8EDA669A0584F12CF0EC6EFEB5C85AD69A2F57DCF5DC41CFF6FD7573C5FBFC977A672AC60583A791D618E69A5EE6B28370CC5BBBA22349A4ABF84641863B934655F27C8ADF25651B430FBC5C30CE52DC3160CC47C0CA21B0D11EC0A94449D62B41D362560AC88D2EF9384FBC3992F30038640509287F903DB46008D44C6B9AB07F8529C64485633E5CFE5E47375012DC943769CF58682B2090231B8C08B549C6E3242C7003C0C7CD9B62650ED28E5FA0732A6D4DFC69F024A47CD66B7A28B91790A7D0D590871B54FFA0FBF9763613FC02392A497C4B1F7FD9E9EC9E90117F1924CBD627CBAA35955728EFA441A7A4BA40D8A1BBAB53900B6EF179F037F3DA5C511473B0FC3493291D314698E8FE4733D7B39203E33129A457F72C7ACE27DC68C0C02F358F6ECCF912ADF69EC06271842BCCD45A4D9EC1351DF05C4A89C08DDCD00CE0EE8D4A37BF2BC35D5113B771173221DB0AD38EDE91E6199B6565BCAD4C769849A45AFD47D7D1B5D770A1DF7466AA7AD1DECC58FB667A0DCE98F5735A673AE29F5109039D815FC594C7E34759ED26C5CDC0BF469D60DE2AB30E2D61E9F8EB815BB36DFFD5F6E81550EB00DCECAA4E9C30CE1059592463A747C68AC4D522E59BD9E7CB7565E0F1F2ECDAD7F215EA1ED08AD05D871FF272D5C041226C9D14EF4A2CAA7ACFA7CCA3DA563D8A642F65CCF1CC417BB5EB3589C6AB160E301EBE6DB04D0E6E5BE1D54A27D77F2F540363562CE869ED3EF5B78C6632E7AB8EBBE8517DCEF42F181DFB7B859813F35F4BC7F1E7AF08E55E49D87F4A1D0DE3D295D97593529CC9F13FA80A8CDB7C760D7BDBE9F2AC32935489C7EDD064BBA9A78CEAB09D29E020C0EA8F1C70D33A813889C3
sk = FEBFFF038000D0FFFFBFFF1F00012000048001E0FFFDBFFFEFFFFF3F00008000F0FF01C0FF1700002000F87F000000FC7F0000000000000080FFFFFFFF3F010800032000F8FFFFFFFF03000000000040000000010000FE7F000000006000F87F01E0FFFD3F001000000000F8FFFE0F0000C0FFF7FF00E0FF03000110000080FF1F00FE3F00FC7F001000FCFFFFFFFFFDFFFF0780FF1F00FEBFFFF7FFFE5F00040000F0FF0180000800FCFFFFFFFF003000004000F8FFFFFFFF0300FF0F0000C0FFFFFF022000FCFF00F0FF01C0FF0F00FF3F00F87F01100000C0FFF7FFFDDFFFF77FFFFFFF01C0FFFFFF0100000000FF1F00048000100003E0FFFFFF003000FEBFFF0700FF1F00FC7F000000020000F0FFFE5F000C80FFFFFF05C0FF1F00FEDFFF030000300000C0FF1700FFDFFFFF7F000000004001F8FF0200000080FFFFFFFFFFFF070000C0FF0300FFFFFF0180FFFFFF0100000000012000000000080001E0FF078000F0FFFDFFFF17000020000880FF1F000280001000FE1F00040000F0FF07C00000000000000400FFFFFFFF7F000800FF1F00148000200002C0FF1F00016000000000F0FF014000F0FFFF1F00FC7F01000002C0FF070000E0FF0380FF1F00FCBF000000FFFFFFFB7F0040000000000000010000F8FF01300000C0FF0F00000000F8FFFF0F000040000800010000F47F000000000000100000E0FF0300FFDFFF030000080003C0FF0380FFEFFF03C0FF0F00010000FC7F010000FCBFFF2700010000F4FF00F0FF050000000001E0FFF77F002000020000F0FF0080FFFB7F00000002C0FF0700FEFFFFFB7F0000000200000800034000040000F0FFFD3F002000FF1F000400FE2F0000C0FFEFFF00E0FF0780FFEFFF0180001800FD3F001000FE2F0002C0FFFFFFFFBFFFF77F001000FC3F00F0FFFE3F00040000F0FF0540FF0F0001000004800100000280FF070001E0FFFFFFFF0F00FEBFFFFFFFFFBFFF0780FF1F00FE3F001000FFFFFF0780013000004000F8FF000000FC7F00200008C0FF0700032000040001200004C0FF0F0001E0FF0380004000FC3F001000000000000000C0FF0300000000FE5F000000000000FC3F01F8FF02C0FFFFFFFFEFFF0340000800FEDFFF0B000100000600000000020000000001F0FF0580FF0700A92CBDB022F926BCE5679BB3EE3481209318011388EA10E68CD067C9E095775E5E9DB940B6D737646D87298B7984E4FE8EDA669A0584F12CF0EC6EFEB5C85AD69A2F57DCF5DC41CFF6FD7573C5FBFC977A672AC60583A791D618E69A5EE6B28370CC5BBBA22349A4ABF84641863B934655F27C8ADF25651B430FBC5C30CE52DC3160CC47C0CA21B0D11EC0A94449D62B41D362560AC88D2EF9384FBC3992F30038640509287F903DB46008D44C6B9AB07F8529C64485633E5CFE5E47375012DC943769CF58682B2090231B8C08B549C6E3242C7003C0C7CD9B62650ED28E5FA0732A6D4DFC69F024A47CD66B7A28B91790A7D0D590871B54FFA0FBF9763613FC02392A497C4B1F7FD9E9EC9E90117F1924CBD627CBAA35955728EFA441A7A4BA40D8A1BBAB53900B6EF179F037F3DA5C511473B0FC3493291D314698E8FE4733D7B39203E33129A457F72C7ACE27DC68C0C02F358F6ECCF912ADF69EC06271842BCCD45A4D9EC1351DF05C4A89C08DDCD00CE0EE8D4A37BF2BC35D5113B771173221DB0AD38EDE91E6199B6565BCAD4C769849A45AFD47D7D1B5D770A1DF7466AA7AD1DECC58FB667A0DCE98F5735A673AE29F5109039D815FC594C7E34759ED26C5CDC0BF469D60DE2AB30E2D61E9F8EB815BB36DFFD5F6E81550EB00DCECAA4E9C30CE1059592463A747C68AC4D522E59BD9E7CB7565E0F1F2ECDAD7F215EA1ED08AD05D871FF272D5C041226C9D14EF4A2CAA7ACFA7CCA3DA563D8A642F65CCF1CC417BB5EB3589C6AB160E301EBE6DB04D0E6E5BE1D54A27D77F2F540363562CE869ED3EF5B78C6632E7AB8EBBE8517DCEF42F181DFB7B859813F35F4BC7F1E7AF08E55E49D87F4A1D0DE3D295D97593529CC9F13FA80A8CDB7C760D7BDBE9F2AC32935489C7EDD064BBA9A78CEAB09D29E020C0EA8F1C70D33A813889C396138744DF873BB04D151F98662646DD8E5565AFB6E1214B8D445130455C1988147C03F7A5BEBBA406C8FAE1874D7F13C80EFE79A3A9A874CC09FE76F6997615
ct = 10AE4CDAE6B0917BA5F624EC788D243B52CAFE591DBAB1E224A216015E9CC65F925443C687C89BA4F44A6EC9FCF51F2F80FE7B00C152D2AE4A18F756D1D2A09E0E0F4C5619972892F2FFC3EF19940B45D38B02F2AA3D2A877070598AFD57689B66EE429D55E155C8D3F0FB8C32547304F45BB2C1EF6D49BBE0390B25293D54870B9FF2A9CC1AC079DC05F18EEADC1468065FB06777BBF828D8D92B661148EDA354DA5721B842EA979FB122296BDEB383B32DF40C4F1C41A8A06572C2E86917A6AF3FB7CDFA83C33FEFB0F01C6507E1EF3FC22E7B0F184578C77C2B97755256593C1325D24AC9668F79D4ADB563539A6EA648E22CDDB8E5306A81871988C7761424C36E0EC670C852C7CBE2D4E15F0C944F893C68AD9C4E2C2A0913328C47FA67C26D6906D07CB406E0871CA6A51A2F0B90F27AD7EFFB56D01C0ECA0DD8022075EC466B7E76F93793305E1EC67876505810454B4E48F630D82149DD02D51665CC715142A89B58ECDB8612EA6398D0A1E6E7531738B13BB8992948EB0A1AEC624C94E2518ECAC77E810524E13B31013C36E4C5477CD36BC534C261C48C146397AC990889C13E957B12C8DE2DEF26DBE9BF4F33FA6822D229377450F7EAA91626C3B6ADB8E7E07A0C87D6404C6948E1EA760C9E39AA19C77BD68B58A1682415A963EBF67E7BB3F9DB1040B7ECA2905993A105CCF06D1EE180A9A91F8037147177AED298F30DA84AC860D48F93258BCC1DCC265EF7D86199E8F374EBC26AFCB2DA2234FD04812D0A2229B3FEA956AB0DB2D4C9CE64BAC75FB67CAD513891D9CF4A6238C7D03BEF767BDEE40FE4B66703BDC5D495BC9999E8940B985068687592E331C9482D95F5134711CE92A4247A4E8C7793E461B488758918B0EEBC42969280FFB50F7FED29F2AFD6F3EFE8E74C1D82B3D9E264EB675D974924B830BB9CA44EB66E1C10E85B61293941B658D4D9943AA973AE8BDBE23E193008DAF3CEC0810E568D41FDB8C8768A8EED17E1E3F46BCDB6F29D1A94F39A1AB266B3F6D8ECF7C80F
ss = BC9B4B82360B9079E6D26FDD12A58994A12EAF458A3DD5F310322A35A65752F5

16
src/kem/saber/Makefile.am Normal file
View File

@ -0,0 +1,16 @@
AUTOMAKE_OPTIONS = foreign
noinst_LTLIBRARIES = libkemsaber.la
noinst_LTLIBRARIES += libkemsaber_lightsaber.la libkemsaber_saber.la libkemsaber_firesaber.la
libkemsaber_la_LIBADD = libkemsaber_lightsaber.la libkemsaber_saber.la libkemsaber_firesaber.la
libkemsaber_la_SOURCES =
libkemsaber_lightsaber_la_SOURCES = kem_saber_lightsaber.c pqclean_lightsaber_clean/cbd.c pqclean_lightsaber_clean/kem.c pqclean_lightsaber_clean/pack_unpack.c pqclean_lightsaber_clean/poly.c pqclean_lightsaber_clean/poly_mul.c pqclean_lightsaber_clean/SABER_indcpa.c pqclean_lightsaber_clean/verify.c
libkemsaber_lightsaber_la_CFLAGS = $(AM_CFLAGS) -I../../common/pqclean_shims
libkemsaber_saber_la_SOURCES = kem_saber_saber.c pqclean_saber_clean/cbd.c pqclean_saber_clean/kem.c pqclean_saber_clean/pack_unpack.c pqclean_saber_clean/poly.c pqclean_saber_clean/poly_mul.c pqclean_saber_clean/SABER_indcpa.c pqclean_saber_clean/verify.c
libkemsaber_saber_la_CFLAGS = $(AM_CFLAGS) -I../../common/pqclean_shims
libkemsaber_firesaber_la_SOURCES = kem_saber_firesaber.c pqclean_firesaber_clean/cbd.c pqclean_firesaber_clean/kem.c pqclean_firesaber_clean/pack_unpack.c pqclean_firesaber_clean/poly.c pqclean_firesaber_clean/poly_mul.c pqclean_firesaber_clean/SABER_indcpa.c pqclean_firesaber_clean/verify.c
libkemsaber_firesaber_la_CFLAGS = $(AM_CFLAGS) -I../../common/pqclean_shims

6
src/kem/saber/Saber-KEM.kat Executable file
View File

@ -0,0 +1,6 @@
count = 0
seed = 061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA1
pk = 29157C69A067DD1C151115A9BBEB2D6E627F4E747716EFA1569C7B7858CB2E71FB52C9984C2B2F98EF255C008024C277F6A5803C6F225AFD169E0FB3E87DFA11457786CCB7D6CDCD472AD7BAB58A5F8F09F40A2718E9C415C2EA7113960ED0E642FE35D01BC639548F2841C0A97D057083DD86ACF474C63CB715EB815E75D738ADFB2106D4EC4BB2FCD419DE1DD8273FE4E18CEF3ECDC48E02875484CB59B561CEA994E1104D295EC6129EC6874D3871E5FF01EC53E86635D907A5A59432557B475AFB8158EC006FFB19ED7FA6B67E5F129B5195146E6BECA2F796C68D42335CB518A9455FDF72696C2C6352D91617DAB38C4855C504F7755D14225413E7E3EE062BE01A405D75D5A8EA2793EEEF962B193C1811EA8169E318363DD88C013B319053B4E7F2F930EC34E52C8131FC2D0F26FB1A08B7F49701F6EBCC67DC7ECF5B314214C7897136EDD0551CA6C828D3507D57521153DE39F2EC7C7935F07C20D5B30086CEE8964E9BE5BC74DE5B95AA2210E952EF5234222934AF1E1AB519D527CF8E3AA40AB34CF30229D2061F18BAA2429410B8FC7AAF949178F6473B0CE2EA094B2BFD4A338B80AB6B7F002B9AA56856C4132F32A001B341EBBA593A8BFE661B50CAB2CDFE80D867AB655C7B7423FA483B080FDB7E059F3CFC6528014D0F7D0DC5526FBA29208EA197493B8A92D66A0A047942264302E61A08A4DF3A91E8E94DDDF469D08EA54A2ECAFD8E64F28D3C40D5BA885D63134550430D205E7E5CAAFE854E494C483AC6CE455D8A1B35F9FD2252E2741E24747EBC052C0B3FE0046FA6FC9B0CCF038088B18EA5B7A3F77A7965640BF6C4FB89F33E30BBDD3C95889206DE51960FDD6A5AA41F80C537E3BAB1576214511CA21A4FD210B2A479E1D414B2A012F789F0D296E22E4A5941434400A3FFC7229068A605891FA15AF03C177D0736A6C2C4FE0D481F48C45568AD92FE1850215AEDED9F97B1219C2E250ECAECB99DFC01101F5D26F36B710E2DA088FD989A0DCE00BB18FB76903BFBD4BBE1CD66DAD049EA12540E81F619FA0478D7687207FFB4EDA6544192629A5BC5E51D927FC143DAC7CEA36B0C7C6D13969F383B0A3BD4C978D04C65E954F82EB883A62825445E2593F5CB23745684F66E5B69D6FCBEDF47507C7B942C1DDAA054F0CACF64EAA5FF31DC213E827D211D47AB0D1D6E2E507F56842D74FC2D94FBCAA9C4BF701ACE46DEC65A2CB9E0B69E75041C9EAED891199C95EC280201E63FC2BCEF11C6ED272FECEB7EA4C3C45785DE6CB4CED51182B25A149F7BC005D68074CD58D916BF48EB13D509714DF03954552B3F1FD2026987CCE4CEC86E09596A1BFCD81CE9F2AC32935489C7EDD064BBA9A78CEAB09D29E020C0EA8F1C70D33A813889C3
sk = FF3F000480000000FEFF000800FE5F00088000F0FF018000F0FFFF5F00FCFFFFEFFF010000F8FF000000FC7F0100000200000800000000000000100000800010000100000080001000FE7F00000000E0FF0700FF0F0002C0FFFFFF00E0FF030000F0FF0380FF0F000120000000FFEFFFFF7F00F0FFFE3F000480FF0F000280001000012000000000D0FF01C00010000200000480FF2F00FC7F00100001E0FFFFFF00E0FF0140000000014000048000200002C0FF0700FF1F00F87F01E0FF0380FFEFFF002000FC7F00F0FF0180FFFFFFFF5F00F87F001000FE7F000800FD1F00FC7F00E0FFFF7F000000FEFFFFF77F003000024000F8FFFEDFFF0700001000020000F8FFFFDFFF030000100000C0FF070003C0FFF77F00200004C0FFFFFF002000088000F0FFFF3F00080000E0FF0700FFEFFF0380001800020000FCFF00F0FF014000F8FFFE3F00FCFFFF1F00020000F0FF01A0FFF7FF00F0FF0380FFF7FF00E0FFFFFF00D0FFFDBF001000FF3F00F8FF00C0FF0180FFFFFF020000048000F0FFFD3F000000032000000000F0FF0300001000024000000000000002C0FF07000020000400002000FA3F00F8FF0140000400002000048000F0FFFF3F0000000010000040000000FFFFFFFFFF000000FEBFFFF7FFFD5F00FC7F0010000280FF0F0000A0FF0B8000000008C0FF170000200004800010000040FF0700FE1F000880001000FE3F001000000000F8FFFF1F0002400000000200000000012000000000000000C0FFFFFF0000000000001800FF7F00FC7F00200002C0FF1700004000FC7F02F0FFFF3F00100002E0FF07800010000280FF0F00FF1F000080FE2F00000000F8FF01E0FF0380002000FEBF001000FFFFFFFFFFFF1F000480FFFFFF010000FCFFFEFFFF010000F8FF0220000400FF0F00FE3F000800FD1F00FCFFFE1F0002800000000140000400011000FC3F00F8FF01C0FFFB7FFFFFFF010000F8FF03E0FF030000F0FF014000E8FF00E0FF0700000000024000F8FF002000000000000000C0FF0F0001200004000030000000000800FE1F0004000100000440000000FF1F00F87F00C0FF038000F8FF00C0FF0780011000FAFFFF0700FF5F00FC7F01E0FF0140FF0700FEFFFF0B00000000FEFF0008000220000C8000200000C0FF070001C0FFFB7FFF0F000080FF0F0000E0FF0380FF1F000280FF0F0000E0FFFFFFFE0F00FEFFFF07000140000400FF1F0002000000000000000080FF0F00060000F0FF004000100001F0FFFF7F00F0FF0000000080FFEFFF054000F8FF0100001000FF0F000040001000012000000000300002C0FF1700004000FCFF0010000280000800FF3F000480FE0F00FCFFFF0F00FDFFFF0300FFEFFFFFFFFFFFFF0120000C80FF2F00FEFFFF0700010000F4FF000000024000F0FF002000FC7F000000028000000000E0FF070000F0FF0140000800FF3F00F8FFFFFFFFFF7F000800FFDFFF0300FFEFFF01800010000100000480FF2F00024000080001C0FF030000F0FFFD7F000800004000FC7F010000FEBFFF1700FF5F00FC7FFE2F00FC3F00F8FF000000FCFFFF0F00FEBFFF0F0002C0FFFFFF0020000400000000FCFFFFFFFFFF0F00004000100001A0FFFF7F00000002800000000200000400FF0F00FEFFFF0700FF1F000000000000040001F0FFFF1F00F87FFF0F00024000080004E0FFFBFFFE0F00FC7F00F0FFFD3F00000000E0FF0180FFF7FF010000F8FF00E0FF030000000029157C69A067DD1C151115A9BBEB2D6E627F4E747716EFA1569C7B7858CB2E71FB52C9984C2B2F98EF255C008024C277F6A5803C6F225AFD169E0FB3E87DFA11457786CCB7D6CDCD472AD7BAB58A5F8F09F40A2718E9C415C2EA7113960ED0E642FE35D01BC639548F2841C0A97D057083DD86ACF474C63CB715EB815E75D738ADFB2106D4EC4BB2FCD419DE1DD8273FE4E18CEF3ECDC48E02875484CB59B561CEA994E1104D295EC6129EC6874D3871E5FF01EC53E86635D907A5A59432557B475AFB8158EC006FFB19ED7FA6B67E5F129B5195146E6BECA2F796C68D42335CB518A9455FDF72696C2C6352D91617DAB38C4855C504F7755D14225413E7E3EE062BE01A405D75D5A8EA2793EEEF962B193C1811EA8169E318363DD88C013B319053B4E7F2F930EC34E52C8131FC2D0F26FB1A08B7F49701F6EBCC67DC7ECF5B314214C7897136EDD0551CA6C828D3507D57521153DE39F2EC7C7935F07C20D5B30086CEE8964E9BE5BC74DE5B95AA2210E952EF5234222934AF1E1AB519D527CF8E3AA40AB34CF30229D2061F18BAA2429410B8FC7AAF949178F6473B0CE2EA094B2BFD4A338B80AB6B7F002B9AA56856C4132F32A001B341EBBA593A8BFE661B50CAB2CDFE80D867AB655C7B7423FA483B080FDB7E059F3CFC6528014D0F7D0DC5526FBA29208EA197493B8A92D66A0A047942264302E61A08A4DF3A91E8E94DDDF469D08EA54A2ECAFD8E64F28D3C40D5BA885D63134550430D205E7E5CAAFE854E494C483AC6CE455D8A1B35F9FD2252E2741E24747EBC052C0B3FE0046FA6FC9B0CCF038088B18EA5B7A3F77A7965640BF6C4FB89F33E30BBDD3C95889206DE51960FDD6A5AA41F80C537E3BAB1576214511CA21A4FD210B2A479E1D414B2A012F789F0D296E22E4A5941434400A3FFC7229068A605891FA15AF03C177D0736A6C2C4FE0D481F48C45568AD92FE1850215AEDED9F97B1219C2E250ECAECB99DFC01101F5D26F36B710E2DA088FD989A0DCE00BB18FB76903BFBD4BBE1CD66DAD049EA12540E81F619FA0478D7687207FFB4EDA6544192629A5BC5E51D927FC143DAC7CEA36B0C7C6D13969F383B0A3BD4C978D04C65E954F82EB883A62825445E2593F5CB23745684F66E5B69D6FCBEDF47507C7B942C1DDAA054F0CACF64EAA5FF31DC213E827D211D47AB0D1D6E2E507F56842D74FC2D94FBCAA9C4BF701ACE46DEC65A2CB9E0B69E75041C9EAED891199C95EC280201E63FC2BCEF11C6ED272FECEB7EA4C3C45785DE6CB4CED51182B25A149F7BC005D68074CD58D916BF48EB13D509714DF03954552B3F1FD2026987CCE4CEC86E09596A1BFCD81CE9F2AC32935489C7EDD064BBA9A78CEAB09D29E020C0EA8F1C70D33A813889C315A7BA143FD2C97ED443A2383AA01C4A06A578AE152521F7AF6C64A51A8FAC17147C03F7A5BEBBA406C8FAE1874D7F13C80EFE79A3A9A874CC09FE76F6997615
ct = 719FAC31AE90417F2DA1D37E47A065B860575D1DF2DE60814A39297B902AFA2F5A12A0D66ED34F3AFED294D40E8027102240798A9F3FB38E65BC93D0BE678AEB099CFF15D9D9D88239BC40E81FC74E5CC280E0495058F7AA36B333A0E8D801ECDBC94D5E12B80273A9B37F61E255AC8FCC54D8BCEEEC8829052FB820FA6F3F93C6B0D0D246A354602EE06294EE726DB763B290738D640682106A34DD44F238E33840BD7B01261E167D3ED6DF8FA0700642FA3016B38F29CDE00FA4615D97E62AE145C9003B54501636C8A2784F7F57ED0FD9CE128530F2272AF12137E1274256EAC34C0C901E64EDF50A484178B47C971ED4F021466AE7BAF8BB8CAA5B9978F05471D9DA472D383ED46C44656CDFBA6A03B974240DF6E10D6861293B71401DF58397BEB67BBE6B716BC196CE2D3E8B0A940F07C66FA947B08EA407C57499027015F52850C7BC680BEB3CA5953F90891C45B9894421A95F5A69ED66B00DBD4F9851AB8EE5F60923A61E984A3A632B41B0A1245976F1A8C9D0BB2FD61D4E9C41340BA47EEB595C20BFCB4B88FF0B19EEC0E934F8ED69394AF2042A84EE8CE170252D8DAEFE161132870B46DAE82F3A5F067F017C5FE47CFBD3845F94D8DADBDC6DB8BF72E96694FF624526EDAC214679721A4757E65F64BE73DDC8F81926D506719AA2FE5FC32FA45FFBE75EF6A758EACEB2C07506C4166462A0E6563D3853305B8804288F0D19D22EE96AADBB12086AF3E41CBC4B08D9190368F506630378E0AAC613F5DCB8A5C5BFB63A1AD837A6563478ABB6731E8ED660BCF0FBF38A85358451E4B188519E6D42C5E876617DC8C4F8D1DBD512032642F62DA3A3E7FE0133BD39EAA0996955C21B020446D0AD95F148AA6A36245510D998F1802A61438B30502604A666559FFD013EACAEF008382D7E586622E8C34AC866EADD99291E9B5F8E6C3675A55AFAA141B9ADC0947897555A80E2A5C3824C443954DEE5B77681695363B184B40FCF7824F58775DFB299B20CDDFA10A62E340D5B3B52D21B7C27FBFD79A8565E69838DCE5DE7560BB3D6ECE880D59722908F4931ECCEE163759C193FBC1D4E1F3B3496CE10705C8552D72EC1316940F0562C54C05D7CEFAA32630A7D3B08D9FDBE24A5DD0892DB51BEB4FC80729E0BCA84B9C22DBC56D48AEA6A116BF4965B432A895DAE2DB869B1FE648793984FA283FD96F35A5477A628E477DE7F00E7255D1D6B3F123486CF993726A53193AA9882E149EB35FE8E33D90A86FC6B4FCC68E4F514E3DFBC83771315D29D187C9FF7F95DA67F4F35B6DB697240ECAB1B92F5B89973AA8966DC8DD874FA8F76C9CEDE6A37657F7B7FFE14036B97BE0604E82C07A9280F206D8C1B52CFFA347C038E3946E72F5A526E27EB50AC351925BC5632A1464D0F41E3F57CAA3A426C2546F94F2A8DF9763FAF132B4F08AC06E9C8753B065D94AE275AA452588336B70183664D9C6D1B2070823226943FDA1D116CA2D766EE95B209ADD6BB64B9CEB9DD5EFF54E76EFDCB3F62773CA8F8AE7BF5
ss = 156533536C8435F82CC36FC1EF9528DEDC49223DDA0091617DC1ACAF6058D1CA

39
src/kem/saber/kem_saber.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef __OQS_KEM_SABER_H
#define __OQS_KEM_SABER_H
#include <oqs/oqs.h>
#ifdef OQS_ENABLE_KEM_saber_lightsaber
#define OQS_KEM_saber_lightsaber_length_public_key 672
#define OQS_KEM_saber_lightsaber_length_secret_key 1568
#define OQS_KEM_saber_lightsaber_length_ciphertext 736
#define OQS_KEM_saber_lightsaber_length_shared_secret 32
OQS_KEM *OQS_KEM_saber_lightsaber_new();
OQS_API OQS_STATUS OQS_KEM_saber_lightsaber_keypair(uint8_t *public_key, uint8_t *secret_key);
OQS_API OQS_STATUS OQS_KEM_saber_lightsaber_encaps(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key);
OQS_API OQS_STATUS OQS_KEM_saber_lightsaber_decaps(uint8_t *shared_secret, const unsigned char *ciphertext, const uint8_t *secret_key);
#endif
#ifdef OQS_ENABLE_KEM_saber_saber
#define OQS_KEM_saber_saber_length_public_key 992
#define OQS_KEM_saber_saber_length_secret_key 2304
#define OQS_KEM_saber_saber_length_ciphertext 1088
#define OQS_KEM_saber_saber_length_shared_secret 32
OQS_KEM *OQS_KEM_saber_saber_new();
OQS_API OQS_STATUS OQS_KEM_saber_saber_keypair(uint8_t *public_key, uint8_t *secret_key);
OQS_API OQS_STATUS OQS_KEM_saber_saber_encaps(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key);
OQS_API OQS_STATUS OQS_KEM_saber_saber_decaps(uint8_t *shared_secret, const unsigned char *ciphertext, const uint8_t *secret_key);
#endif
#ifdef OQS_ENABLE_KEM_saber_firesaber
#define OQS_KEM_saber_firesaber_length_public_key 1312
#define OQS_KEM_saber_firesaber_length_secret_key 3040
#define OQS_KEM_saber_firesaber_length_ciphertext 1472
#define OQS_KEM_saber_firesaber_length_shared_secret 32
OQS_KEM *OQS_KEM_saber_firesaber_new();
OQS_API OQS_STATUS OQS_KEM_saber_firesaber_keypair(uint8_t *public_key, uint8_t *secret_key);
OQS_API OQS_STATUS OQS_KEM_saber_firesaber_encaps(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key);
OQS_API OQS_STATUS OQS_KEM_saber_firesaber_decaps(uint8_t *shared_secret, const unsigned char *ciphertext, const uint8_t *secret_key);
#endif
#endif

View File

@ -0,0 +1,45 @@
#include <stdlib.h>
#include <oqs/kem_saber.h>
#ifdef OQS_ENABLE_KEM_saber_firesaber
OQS_KEM *OQS_KEM_saber_firesaber_new() {
OQS_KEM *kem = malloc(sizeof(OQS_KEM));
if (kem == NULL) {
return NULL;
}
kem->method_name = OQS_KEM_alg_saber_firesaber;
kem->alg_version = "https://github.com/KULeuven-COSIC/SABER/commit/14ede83f1ff3bcc41f0464543542366c68b55871";
kem->claimed_nist_level = 5;
kem->ind_cca = true;
kem->length_public_key = OQS_KEM_saber_firesaber_length_public_key;
kem->length_secret_key = OQS_KEM_saber_firesaber_length_secret_key;
kem->length_ciphertext = OQS_KEM_saber_firesaber_length_ciphertext;
kem->length_shared_secret = OQS_KEM_saber_firesaber_length_shared_secret;
kem->keypair = OQS_KEM_saber_firesaber_keypair;
kem->encaps = OQS_KEM_saber_firesaber_encaps;
kem->decaps = OQS_KEM_saber_firesaber_decaps;
return kem;
}
int PQCLEAN_FIRESABER_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk);
int PQCLEAN_FIRESABER_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk);
int PQCLEAN_FIRESABER_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk);
OQS_API OQS_STATUS OQS_KEM_saber_firesaber_keypair(uint8_t *public_key, uint8_t *secret_key) {
return (OQS_STATUS) PQCLEAN_FIRESABER_CLEAN_crypto_kem_keypair(public_key, secret_key);
}
OQS_API OQS_STATUS OQS_KEM_saber_firesaber_encaps(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key) {
return (OQS_STATUS) PQCLEAN_FIRESABER_CLEAN_crypto_kem_enc(ciphertext, shared_secret, public_key);
}
OQS_API OQS_STATUS OQS_KEM_saber_firesaber_decaps(uint8_t *shared_secret, const unsigned char *ciphertext, const uint8_t *secret_key) {
return (OQS_STATUS) PQCLEAN_FIRESABER_CLEAN_crypto_kem_dec(shared_secret, ciphertext, secret_key);
}
#endif

View File

@ -0,0 +1,45 @@
#include <stdlib.h>
#include <oqs/kem_saber.h>
#ifdef OQS_ENABLE_KEM_saber_lightsaber
OQS_KEM *OQS_KEM_saber_lightsaber_new() {
OQS_KEM *kem = malloc(sizeof(OQS_KEM));
if (kem == NULL) {
return NULL;
}
kem->method_name = OQS_KEM_alg_saber_lightsaber;
kem->alg_version = "https://github.com/KULeuven-COSIC/SABER/commit/14ede83f1ff3bcc41f0464543542366c68b55871";
kem->claimed_nist_level = 1;
kem->ind_cca = true;
kem->length_public_key = OQS_KEM_saber_lightsaber_length_public_key;
kem->length_secret_key = OQS_KEM_saber_lightsaber_length_secret_key;
kem->length_ciphertext = OQS_KEM_saber_lightsaber_length_ciphertext;
kem->length_shared_secret = OQS_KEM_saber_lightsaber_length_shared_secret;
kem->keypair = OQS_KEM_saber_lightsaber_keypair;
kem->encaps = OQS_KEM_saber_lightsaber_encaps;
kem->decaps = OQS_KEM_saber_lightsaber_decaps;
return kem;
}
int PQCLEAN_LIGHTSABER_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk);
int PQCLEAN_LIGHTSABER_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk);
int PQCLEAN_LIGHTSABER_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk);
OQS_API OQS_STATUS OQS_KEM_saber_lightsaber_keypair(uint8_t *public_key, uint8_t *secret_key) {
return (OQS_STATUS) PQCLEAN_LIGHTSABER_CLEAN_crypto_kem_keypair(public_key, secret_key);
}
OQS_API OQS_STATUS OQS_KEM_saber_lightsaber_encaps(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key) {
return (OQS_STATUS) PQCLEAN_LIGHTSABER_CLEAN_crypto_kem_enc(ciphertext, shared_secret, public_key);
}
OQS_API OQS_STATUS OQS_KEM_saber_lightsaber_decaps(uint8_t *shared_secret, const unsigned char *ciphertext, const uint8_t *secret_key) {
return (OQS_STATUS) PQCLEAN_LIGHTSABER_CLEAN_crypto_kem_dec(shared_secret, ciphertext, secret_key);
}
#endif

View File

@ -0,0 +1,45 @@
#include <stdlib.h>
#include <oqs/kem_saber.h>
#ifdef OQS_ENABLE_KEM_saber_saber
OQS_KEM *OQS_KEM_saber_saber_new() {
OQS_KEM *kem = malloc(sizeof(OQS_KEM));
if (kem == NULL) {
return NULL;
}
kem->method_name = OQS_KEM_alg_saber_saber;
kem->alg_version = "https://github.com/KULeuven-COSIC/SABER/commit/14ede83f1ff3bcc41f0464543542366c68b55871";
kem->claimed_nist_level = 3;
kem->ind_cca = true;
kem->length_public_key = OQS_KEM_saber_saber_length_public_key;
kem->length_secret_key = OQS_KEM_saber_saber_length_secret_key;
kem->length_ciphertext = OQS_KEM_saber_saber_length_ciphertext;
kem->length_shared_secret = OQS_KEM_saber_saber_length_shared_secret;
kem->keypair = OQS_KEM_saber_saber_keypair;
kem->encaps = OQS_KEM_saber_saber_encaps;
kem->decaps = OQS_KEM_saber_saber_decaps;
return kem;
}
int PQCLEAN_SABER_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk);
int PQCLEAN_SABER_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk);
int PQCLEAN_SABER_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk);
OQS_API OQS_STATUS OQS_KEM_saber_saber_keypair(uint8_t *public_key, uint8_t *secret_key) {
return (OQS_STATUS) PQCLEAN_SABER_CLEAN_crypto_kem_keypair(public_key, secret_key);
}
OQS_API OQS_STATUS OQS_KEM_saber_saber_encaps(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key) {
return (OQS_STATUS) PQCLEAN_SABER_CLEAN_crypto_kem_enc(ciphertext, shared_secret, public_key);
}
OQS_API OQS_STATUS OQS_KEM_saber_saber_decaps(uint8_t *shared_secret, const unsigned char *ciphertext, const uint8_t *secret_key) {
return (OQS_STATUS) PQCLEAN_SABER_CLEAN_crypto_kem_dec(shared_secret, ciphertext, secret_key);
}
#endif

View File

@ -0,0 +1,8 @@
----------------------------------------------------------------------------------------
SABER_v1.1
Public domain
Authors: Jan-Pieter D'Anvers, Angshuman Karmakar, Sujoy Sinha Roy,
Frederik Vercauteren
----------------------------------------------------------------------------------------

View File

@ -0,0 +1,298 @@
#include "SABER_indcpa.h"
#include "SABER_params.h"
#include "fips202.h"
#include "pack_unpack.h"
#include "poly.h"
#include "poly_mul.h"
#include "randombytes.h"
#include <stdint.h>
#include <string.h>
/*-----------------------------------------------------------------------------------
This routine generates a=[Matrix K x K] of 256-coefficient polynomials
-------------------------------------------------------------------------------------*/
#define h1 4 //2^(EQ-EP-1)
#define h2 ( (1<<(SABER_EP-2)) - (1<<(SABER_EP-SABER_ET-1)) + (1<<(SABER_EQ-SABER_EP-1)) )
static void InnerProd(uint16_t pkcl[SABER_K][SABER_N], uint16_t skpv[SABER_K][SABER_N], uint16_t mod, uint16_t res[SABER_N]);
static void MatrixVectorMul(polyvec *a, uint16_t skpv[SABER_K][SABER_N], uint16_t res[SABER_K][SABER_N], uint16_t mod, int16_t transpose);
static void POL2MSG(const uint16_t *message_dec_unpacked, unsigned char *message_dec);
static void GenMatrix(polyvec *a, const unsigned char *seed) {
unsigned char buf[SABER_K * SABER_K * (13 * SABER_N / 8)];
uint16_t temp_ar[SABER_N];
int i, j, k;
uint16_t mod = (SABER_Q - 1);
shake128(buf, sizeof(buf), seed, SABER_SEEDBYTES);
for (i = 0; i < SABER_K; i++) {
for (j = 0; j < SABER_K; j++) {
PQCLEAN_FIRESABER_CLEAN_BS2POL(buf + (i * SABER_K + j) * (13 * SABER_N / 8), temp_ar);
for (k = 0; k < SABER_N; k++) {
a[i].vec[j].coeffs[k] = (temp_ar[k])& mod ;
}
}
}
}
void PQCLEAN_FIRESABER_CLEAN_indcpa_kem_keypair(unsigned char *pk, unsigned char *sk) {
polyvec a[SABER_K];
uint16_t skpv[SABER_K][SABER_N];
unsigned char seed[SABER_SEEDBYTES];
unsigned char noiseseed[SABER_COINBYTES];
int32_t i, j;
uint16_t mod_q = SABER_Q - 1;
uint16_t res[SABER_K][SABER_N];
randombytes(seed, SABER_SEEDBYTES);
// for not revealing system RNG state
shake128(seed, SABER_SEEDBYTES, seed, SABER_SEEDBYTES);
randombytes(noiseseed, SABER_COINBYTES);
GenMatrix(a, seed); //sample matrix A
// generate secret from constant-time binomial distribution
PQCLEAN_FIRESABER_CLEAN_GenSecret(skpv, noiseseed);
// do the matrix vector multiplication and rounding
for (i = 0; i < SABER_K; i++) {
for (j = 0; j < SABER_N; j++) {
res[i][j] = 0;
}
}
MatrixVectorMul(a, skpv, res, SABER_Q - 1, 1);
// now rounding
for (i = 0; i < SABER_K; i++) {
for (j = 0; j < SABER_N; j++) {
// shift right 3 bits
res[i][j] = (res[i][j] + h1) & (mod_q);
res[i][j] = (res[i][j] >> (SABER_EQ - SABER_EP));
}
}
// unload and pack sk=3 x (256 coefficients of 14 bits)
PQCLEAN_FIRESABER_CLEAN_POLVEC2BS(sk, skpv, SABER_Q);
// unload and pack pk=256 bits seed and 3 x (256 coefficients of 11 bits)
// load the public-key coefficients
PQCLEAN_FIRESABER_CLEAN_POLVEC2BS(pk, res, SABER_P);
// now load the seedbytes in PK. Easy since seed bytes are kept in byte format.
for (i = 0; i < SABER_SEEDBYTES; i++) {
pk[SABER_POLYVECCOMPRESSEDBYTES + i] = seed[i];
}
}
void PQCLEAN_FIRESABER_CLEAN_indcpa_kem_enc(const unsigned char *message_received, unsigned char *noiseseed, const unsigned char *pk, unsigned char *ciphertext) {
uint32_t i, j, k;
polyvec a[SABER_K];
unsigned char seed[SABER_SEEDBYTES];
// public key of received by the client
uint16_t pkcl[SABER_K][SABER_N];
uint16_t skpv1[SABER_K][SABER_N];
uint16_t message[SABER_KEYBYTES * 8];
uint16_t res[SABER_K][SABER_N];
uint16_t mod_p = SABER_P - 1;
uint16_t mod_q = SABER_Q - 1;
uint16_t vprime[SABER_N];
unsigned char msk_c[SABER_SCALEBYTES_KEM];
// extract the seedbytes from Public Key.
for (i = 0; i < SABER_SEEDBYTES; i++) {
seed[i] = pk[ SABER_POLYVECCOMPRESSEDBYTES + i];
}
GenMatrix(a, seed);
// generate secret from constant-time binomial distribution
PQCLEAN_FIRESABER_CLEAN_GenSecret(skpv1, noiseseed);
// matrix-vector multiplication and rounding
for (i = 0; i < SABER_K; i++) {
for (j = 0; j < SABER_N; j++) {
res[i][j] = 0;
}
}
MatrixVectorMul(a, skpv1, res, SABER_Q - 1, 0);
// now rounding
//shift right 3 bits
for (i = 0; i < SABER_K; i++) {
for (j = 0; j < SABER_N; j++) {
res[i][j] = ( res[i][j] + h1 ) & mod_q;
res[i][j] = (res[i][j] >> (SABER_EQ - SABER_EP) );
}
}
PQCLEAN_FIRESABER_CLEAN_POLVEC2BS(ciphertext, res, SABER_P);
// ************client matrix-vector multiplication ends************
// now calculate the v'
// unpack the public_key
// pkcl is the b in the protocol
PQCLEAN_FIRESABER_CLEAN_BS2POLVEC(pk, pkcl, SABER_P);
for (i = 0; i < SABER_N; i++) {
vprime[i] = 0;
}
for (i = 0; i < SABER_K; i++) {
for (j = 0; j < SABER_N; j++) {
skpv1[i][j] = skpv1[i][j] & (mod_p);
}
}
// vector-vector scalar multiplication with mod p
InnerProd(pkcl, skpv1, mod_p, vprime);
// addition of h1 to vprime
for (i = 0; i < SABER_N; i++) {
vprime[i] = vprime[i] + h1;
}
// unpack message_received;
for (j = 0; j < SABER_KEYBYTES; j++) {
for (i = 0; i < 8; i++) {
message[8 * j + i] = ((message_received[j] >> i) & 0x01);
}
}
// message encoding
for (i = 0; i < SABER_N; i++) {
message[i] = (message[i] << (SABER_EP - 1));
}
for (k = 0; k < SABER_N; k++) {
vprime[k] = ( (vprime[k] - message[k]) & (mod_p) ) >> (SABER_EP - SABER_ET);
}
PQCLEAN_FIRESABER_CLEAN_pack_6bit(msk_c, vprime);
for (j = 0; j < SABER_SCALEBYTES_KEM; j++) {
ciphertext[SABER_POLYVECCOMPRESSEDBYTES + j] = msk_c[j];
}
}
void PQCLEAN_FIRESABER_CLEAN_indcpa_kem_dec(const unsigned char *sk, const unsigned char *ciphertext, unsigned char message_dec[]) {
uint32_t i, j;
// secret key of the server
uint16_t sksv[SABER_K][SABER_N];
uint16_t pksv[SABER_K][SABER_N];
uint8_t scale_ar[SABER_SCALEBYTES_KEM];
uint16_t mod_p = SABER_P - 1;
uint16_t v[SABER_N];
uint16_t op[SABER_N];
// sksv is the secret-key
PQCLEAN_FIRESABER_CLEAN_BS2POLVEC(sk, sksv, SABER_Q);
// pksv is the ciphertext
PQCLEAN_FIRESABER_CLEAN_BS2POLVEC(ciphertext, pksv, SABER_P);
// vector-vector scalar multiplication with mod p
for (i = 0; i < SABER_N; i++) {
v[i] = 0;
}
for (i = 0; i < SABER_K; i++) {
for (j = 0; j < SABER_N; j++) {
sksv[i][j] = sksv[i][j] & (mod_p);
}
}
InnerProd(pksv, sksv, mod_p, v);
//Extraction
for (i = 0; i < SABER_SCALEBYTES_KEM; i++) {
scale_ar[i] = ciphertext[SABER_POLYVECCOMPRESSEDBYTES + i];
}
PQCLEAN_FIRESABER_CLEAN_un_pack6bit(scale_ar, op);
//addition of h1
for (i = 0; i < SABER_N; i++) {
v[i] = ( ( v[i] + h2 - (op[i] << (SABER_EP - SABER_ET)) ) & (mod_p) ) >> (SABER_EP - 1);
}
// pack decrypted message
POL2MSG(v, message_dec);
}
static void MatrixVectorMul(polyvec *a, uint16_t skpv[SABER_K][SABER_N], uint16_t res[SABER_K][SABER_N], uint16_t mod, int16_t transpose) {
uint16_t acc[SABER_N];
int32_t i, j, k;
if (transpose == 1) {
for (i = 0; i < SABER_K; i++) {
for (j = 0; j < SABER_K; j++) {
PQCLEAN_FIRESABER_CLEAN_pol_mul((uint16_t *)&a[j].vec[i], skpv[j], acc, SABER_Q, SABER_N);
for (k = 0; k < SABER_N; k++) {
res[i][k] = res[i][k] + acc[k];
//reduction mod p
res[i][k] = (res[i][k] & mod);
//clear the accumulator
acc[k] = 0;
}
}
}
} else {
for (i = 0; i < SABER_K; i++) {
for (j = 0; j < SABER_K; j++) {
PQCLEAN_FIRESABER_CLEAN_pol_mul((uint16_t *)&a[i].vec[j], skpv[j], acc, SABER_Q, SABER_N);
for (k = 0; k < SABER_N; k++) {
res[i][k] = res[i][k] + acc[k];
// reduction
res[i][k] = res[i][k] & mod;
// clear the accumulator
acc[k] = 0;
}
}
}
}
}
static void POL2MSG(const uint16_t *message_dec_unpacked, unsigned char *message_dec) {
int32_t i, j;
for (j = 0; j < SABER_KEYBYTES; j++) {
message_dec[j] = 0;
for (i = 0; i < 8; i++) {
message_dec[j] = message_dec[j] | (uint8_t) (message_dec_unpacked[j * 8 + i] << i);
}
}
}
static void InnerProd(uint16_t pkcl[SABER_K][SABER_N], uint16_t skpv[SABER_K][SABER_N], uint16_t mod, uint16_t res[SABER_N]) {
uint32_t j, k;
uint16_t acc[SABER_N];
// vector-vector scalar multiplication with mod p
for (j = 0; j < SABER_K; j++) {
PQCLEAN_FIRESABER_CLEAN_pol_mul(pkcl[j], skpv[j], acc, SABER_P, SABER_N);
for (k = 0; k < SABER_N; k++) {
res[k] = res[k] + acc[k];
// reduction
res[k] = res[k] & mod;
// clear the accumulator
acc[k] = 0;
}
}
}

View File

@ -0,0 +1,9 @@
#ifndef INDCPA_H
#define INDCPA_H
void PQCLEAN_FIRESABER_CLEAN_indcpa_kem_keypair(unsigned char *pk, unsigned char *sk);
void PQCLEAN_FIRESABER_CLEAN_indcpa_kem_enc(const unsigned char *message, unsigned char *noiseseed, const unsigned char *pk, unsigned char *ciphertext);
void PQCLEAN_FIRESABER_CLEAN_indcpa_kem_dec(const unsigned char *sk, const unsigned char *ciphertext, unsigned char *message_dec);
#endif

View File

@ -0,0 +1,49 @@
#ifndef PARAMS_H
#define PARAMS_H
#include "api.h"
#define SABER_K 4
#define SABER_MU 6
#define SABER_ET 6
#define SABER_EQ 13
#define SABER_EP 10
#define SABER_N 256
#define SABER_Q 8192
#define SABER_P 1024
#define SABER_SEEDBYTES 32
#define SABER_NOISESEEDBYTES 32
#define SABER_COINBYTES 32
#define SABER_KEYBYTES 32
#define SABER_HASHBYTES 32
#define SABER_POLYBYTES 416 //13*256/8
#define SABER_POLYVECBYTES (SABER_K * SABER_POLYBYTES)
#define SABER_POLYVECCOMPRESSEDBYTES (SABER_K * 320) //10*256/8 NOTE : changed till here due to parameter adaptation
#define SABER_CIPHERTEXTBYTES (SABER_POLYVECCOMPRESSEDBYTES)
#define SABER_SCALEBYTES (SABER_DELTA*SABER_N/8)
#define SABER_SCALEBYTES_KEM ((SABER_ET)*SABER_N/8)
#define SABER_INDCPA_PUBLICKEYBYTES (SABER_POLYVECCOMPRESSEDBYTES + SABER_SEEDBYTES)
#define SABER_INDCPA_SECRETKEYBYTES (SABER_POLYVECBYTES)
#define SABER_PUBLICKEYBYTES (SABER_INDCPA_PUBLICKEYBYTES)
#define SABER_SECRETKEYBYTES (SABER_INDCPA_SECRETKEYBYTES + SABER_INDCPA_PUBLICKEYBYTES + SABER_HASHBYTES + SABER_KEYBYTES)
#define SABER_BYTES_CCA_DEC (SABER_POLYVECCOMPRESSEDBYTES + SABER_SCALEBYTES_KEM) /* Second part is for Targhi-Unruh */
#endif

View File

@ -0,0 +1,14 @@
#ifndef PQCLEAN_FIRESABER_CLEAN_API_H
#define PQCLEAN_FIRESABER_CLEAN_API_H
#define PQCLEAN_FIRESABER_CLEAN_CRYPTO_ALGNAME "FireSaber"
#define PQCLEAN_FIRESABER_CLEAN_CRYPTO_SECRETKEYBYTES 3040
#define PQCLEAN_FIRESABER_CLEAN_CRYPTO_PUBLICKEYBYTES (4*320+32)
#define PQCLEAN_FIRESABER_CLEAN_CRYPTO_BYTES 32
#define PQCLEAN_FIRESABER_CLEAN_CRYPTO_CIPHERTEXTBYTES 1472
int PQCLEAN_FIRESABER_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk);
int PQCLEAN_FIRESABER_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk);
int PQCLEAN_FIRESABER_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk);
#endif /* api_h */

View File

@ -0,0 +1,52 @@
/*---------------------------------------------------------------------
This file has been adapted from the implementation
(available at, Public Domain https://github.com/pq-crystals/kyber)
of "CRYSTALS Kyber: a CCA-secure module-lattice-based KEM"
by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint,
Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle
----------------------------------------------------------------------*/
#include "SABER_params.h"
#include "api.h"
#include "cbd.h"
#include <stdint.h>
static uint64_t load_littleendian(const unsigned char *x, int bytes) {
int i;
uint64_t r = x[0];
for (i = 1; i < bytes; i++) {
r |= (uint64_t)x[i] << (8 * i);
}
return r;
}
void PQCLEAN_FIRESABER_CLEAN_cbd(uint16_t *r, const unsigned char *buf) {
uint16_t Qmod_minus1 = SABER_Q - 1;
uint32_t t, d, a[4], b[4];
int i, j;
for (i = 0; i < SABER_N / 4; i++) {
t = (uint32_t) load_littleendian(buf + 3 * i, 3);
d = 0;
for (j = 0; j < 3; j++) {
d += (t >> j) & 0x249249;
}
a[0] = d & 0x7;
b[0] = (d >> 3) & 0x7;
a[1] = (d >> 6) & 0x7;
b[1] = (d >> 9) & 0x7;
a[2] = (d >> 12) & 0x7;
b[2] = (d >> 15) & 0x7;
a[3] = (d >> 18) & 0x7;
b[3] = (d >> 21);
r[4 * i + 0] = (uint16_t)(a[0] - b[0]) & Qmod_minus1;
r[4 * i + 1] = (uint16_t)(a[1] - b[1]) & Qmod_minus1;
r[4 * i + 2] = (uint16_t)(a[2] - b[2]) & Qmod_minus1;
r[4 * i + 3] = (uint16_t)(a[3] - b[3]) & Qmod_minus1;
}
}

View File

@ -0,0 +1,17 @@
#ifndef CBD_H
#define CBD_H
/*---------------------------------------------------------------------
This file has been adapted from the implementation
(available at, Public Domain https://github.com/pq-crystals/kyber)
of "CRYSTALS Kyber: a CCA-secure module-lattice-based KEM"
by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint,
Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle
----------------------------------------------------------------------*/
#include "poly.h"
#include <stdint.h>
void PQCLEAN_FIRESABER_CLEAN_cbd(uint16_t *r, const unsigned char *buf);
#endif

View File

@ -0,0 +1,96 @@
#include "SABER_indcpa.h"
#include "SABER_params.h"
#include "fips202.h"
#include "randombytes.h"
#include "verify.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
int PQCLEAN_FIRESABER_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk) {
int i;
// sk[0:SABER_INDCPA_SECRETKEYBYTES-1] <-- sk
PQCLEAN_FIRESABER_CLEAN_indcpa_kem_keypair(pk, sk);
// sk[SABER_INDCPA_SECRETKEYBYTES:SABER_INDCPA_SECRETKEYBYTES+SABER_INDCPA_SECRETKEYBYTES-1] <-- pk
for (i = 0; i < SABER_INDCPA_PUBLICKEYBYTES; i++) {
sk[i + SABER_INDCPA_SECRETKEYBYTES] = pk[i];
}
// Then hash(pk) is appended.
sha3_256(sk + SABER_SECRETKEYBYTES - 64, pk, SABER_INDCPA_PUBLICKEYBYTES);
// Remaining part of sk contains a pseudo-random number.
// This is output when check in crypto_kem_dec() fails.
randombytes(sk + SABER_SECRETKEYBYTES - SABER_KEYBYTES, SABER_KEYBYTES );
return (0);
}
int PQCLEAN_FIRESABER_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) {
// Will contain key, coins
unsigned char kr[64];
unsigned char buf[64];
randombytes(buf, 32);
// BUF[0:31] <-- random message (will be used as the key for client) Note: hash doesnot release system RNG output
sha3_256(buf, buf, 32);
// BUF[32:63] <-- Hash(public key); Multitarget countermeasure for coins + contributory KEM
sha3_256(buf + 32, pk, SABER_INDCPA_PUBLICKEYBYTES);
// kr[0:63] <-- Hash(buf[0:63]);
sha3_512(kr, buf, 64);
// K^ <-- kr[0:31]
// noiseseed (r) <-- kr[32:63];
// buf[0:31] contains message; kr[32:63] contains randomness r;
PQCLEAN_FIRESABER_CLEAN_indcpa_kem_enc(buf, kr + 32, pk, ct);
sha3_256(kr + 32, ct, SABER_BYTES_CCA_DEC);
// hash concatenation of pre-k and h(c) to k
sha3_256(ss, kr, 64);
return (0);
}
int PQCLEAN_FIRESABER_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) {
int i;
unsigned char fail;
unsigned char cmp[SABER_BYTES_CCA_DEC];
unsigned char buf[64];
// Will contain key, coins
unsigned char kr[64];
const unsigned char *pk = sk + SABER_INDCPA_SECRETKEYBYTES;
// buf[0:31] <-- message
PQCLEAN_FIRESABER_CLEAN_indcpa_kem_dec(sk, ct, buf);
// Multitarget countermeasure for coins + contributory KEM
// Save hash by storing h(pk) in sk
for (i = 0; i < 32; i++) {
buf[32 + i] = sk[SABER_SECRETKEYBYTES - 64 + i];
}
sha3_512(kr, buf, 64);
PQCLEAN_FIRESABER_CLEAN_indcpa_kem_enc(buf, kr + 32, pk, cmp);
fail = PQCLEAN_FIRESABER_CLEAN_verify(ct, cmp, SABER_BYTES_CCA_DEC);
// overwrite coins in kr with h(c)
sha3_256(kr + 32, ct, SABER_BYTES_CCA_DEC);
PQCLEAN_FIRESABER_CLEAN_cmov(kr, sk + SABER_SECRETKEYBYTES - SABER_KEYBYTES, SABER_KEYBYTES, fail);
// hash concatenation of pre-k and h(c) to k
sha3_256(ss, kr, 64);
return (0);
}

View File

@ -0,0 +1,254 @@
#include "pack_unpack.h"
void PQCLEAN_FIRESABER_CLEAN_pack_3bit(uint8_t *bytes, const uint16_t *data) {
uint32_t j;
uint32_t offset_data, offset_byte;
for (j = 0; j < SABER_N / 8; j++) {
offset_byte = 3 * j;
offset_data = 8 * j;
bytes[offset_byte + 0] = (data[offset_data + 0] & 0x7) |
((data[offset_data + 1] & 0x7) << 3) |
((data[offset_data + 2] & 0x3) << 6);
bytes[offset_byte + 1] = ((data[offset_data + 2] >> 2 ) & 0x01) |
((data[offset_data + 3] & 0x7) << 1) |
((data[offset_data + 4] & 0x7) << 4) |
(((data[offset_data + 5]) & 0x01) << 7);
bytes[offset_byte + 2] = ((data[offset_data + 5] >> 1 ) & 0x03) |
((data[offset_data + 6] & 0x7) << 2) |
((data[offset_data + 7] & 0x7) << 5);
}
}
void PQCLEAN_FIRESABER_CLEAN_un_pack3bit(const uint8_t *bytes, uint16_t *data) {
uint32_t j;
uint32_t offset_data, offset_byte;
for (j = 0; j < SABER_N / 8; j++) {
offset_byte = 3 * j;
offset_data = 8 * j;
data[offset_data + 0] = (bytes[offset_byte + 0]) & 0x07;
data[offset_data + 1] = ((bytes[offset_byte + 0]) >> 3 ) & 0x07;
data[offset_data + 2] = (((bytes[offset_byte + 0]) >> 6 ) & 0x03) |
(((bytes[offset_byte + 1]) & 0x01) << 2);
data[offset_data + 3] = ((bytes[offset_byte + 1]) >> 1 ) & 0x07;
data[offset_data + 4] = ((bytes[offset_byte + 1]) >> 4 ) & 0x07;
data[offset_data + 5] = (((bytes[offset_byte + 1]) >> 7 ) & 0x01) |
(((bytes[offset_byte + 2]) & 0x03) << 1);
data[offset_data + 6] = ((bytes[offset_byte + 2] >> 2) & 0x07);
data[offset_data + 7] = ((bytes[offset_byte + 2] >> 5) & 0x07);
}
}
void PQCLEAN_FIRESABER_CLEAN_pack_4bit(uint8_t *bytes, const uint16_t *data) {
uint32_t j;
uint32_t offset_data;
for (j = 0; j < SABER_N / 2; j++) {
offset_data = 2 * j;
bytes[j] = (data[offset_data] & 0x0f) |
((data[offset_data + 1] & 0x0f) << 4);
}
}
void PQCLEAN_FIRESABER_CLEAN_un_pack4bit(const unsigned char *bytes, uint16_t *ar) {
uint32_t j;
uint32_t offset_data;
for (j = 0; j < SABER_N / 2; j++) {
offset_data = 2 * j;
ar[offset_data] = bytes[j] & 0x0f;
ar[offset_data + 1] = (bytes[j] >> 4) & 0x0f;
}
}
void PQCLEAN_FIRESABER_CLEAN_pack_6bit(uint8_t *bytes, const uint16_t *data) {
uint32_t j;
uint32_t offset_data, offset_byte;
for (j = 0; j < SABER_N / 4; j++) {
offset_byte = 3 * j;
offset_data = 4 * j;
bytes[offset_byte + 0] = (data[offset_data + 0] & 0x3f) |
((data[offset_data + 1] & 0x03) << 6);
bytes[offset_byte + 1] = ((data[offset_data + 1] >> 2) & 0x0f) |
((data[offset_data + 2] & 0x0f) << 4);
bytes[offset_byte + 2] = ((data[offset_data + 2] >> 4) & 0x03) |
((data[offset_data + 3] & 0x3f) << 2);
}
}
void PQCLEAN_FIRESABER_CLEAN_un_pack6bit(const unsigned char *bytes, uint16_t *data) {
uint32_t j;
uint32_t offset_data, offset_byte;
for (j = 0; j < SABER_N / 4; j++) {
offset_byte = 3 * j;
offset_data = 4 * j;
data[offset_data + 0] = bytes[offset_byte + 0] & 0x3f;
data[offset_data + 1] = ((bytes[offset_byte + 0] >> 6) & 0x03) |
((bytes[offset_byte + 1] & 0x0f) << 2);
data[offset_data + 2] = ((bytes[offset_byte + 1] & 0xff) >> 4) |
((bytes[offset_byte + 2] & 0x03) << 4);
data[offset_data + 3] = ((bytes[offset_byte + 2] & 0xff) >> 2);
}
}
static void POLVECp2BS(uint8_t *bytes, uint16_t data[SABER_K][SABER_N]) {
uint32_t i, j;
uint32_t offset_data, offset_byte, offset_byte1;
for (i = 0; i < SABER_K; i++) {
offset_byte1 = i * (SABER_N * 10) / 8;
for (j = 0; j < SABER_N / 4; j++) {
offset_byte = offset_byte1 + 5 * j;
offset_data = 4 * j;
bytes[offset_byte + 0] = (data[i][offset_data + 0] & (0xff));
bytes[offset_byte + 1] = ((data[i][offset_data + 0] >> 8) & 0x03) |
((data[i][offset_data + 1] & 0x3f) << 2);
bytes[offset_byte + 2] = ((data[i][offset_data + 1] >> 6) & 0x0f) |
((data[i][offset_data + 2] & 0x0f) << 4);
bytes[offset_byte + 3] = ((data[i][offset_data + 2] >> 4) & 0x3f) |
((data[i][offset_data + 3] & 0x03) << 6);
bytes[offset_byte + 4] = ((data[i][offset_data + 3] >> 2) & 0xff);
}
}
}
static void BS2POLVECp(const unsigned char *bytes, uint16_t data[SABER_K][SABER_N]) {
uint32_t i, j;
uint32_t offset_data, offset_byte, offset_byte1;
for (i = 0; i < SABER_K; i++) {
offset_byte1 = i * (SABER_N * 10) / 8;
for (j = 0; j < SABER_N / 4; j++) {
offset_byte = offset_byte1 + 5 * j;
offset_data = 4 * j;
data[i][offset_data + 0] = (bytes[offset_byte + 0] & (0xff)) |
((bytes[offset_byte + 1] & 0x03) << 8);
data[i][offset_data + 1] = ((bytes[offset_byte + 1] >> 2) & (0x3f)) |
((bytes[offset_byte + 2] & 0x0f) << 6);
data[i][offset_data + 2] = ((bytes[offset_byte + 2] >> 4) & (0x0f)) |
((bytes[offset_byte + 3] & 0x3f) << 4);
data[i][offset_data + 3] = ((bytes[offset_byte + 3] >> 6) & (0x03)) |
((bytes[offset_byte + 4] & 0xff) << 2);
}
}
}
static void POLVECq2BS(uint8_t *bytes, uint16_t data[SABER_K][SABER_N]) {
uint32_t i, j;
uint32_t offset_data, offset_byte, offset_byte1;
for (i = 0; i < SABER_K; i++) {
offset_byte1 = i * (SABER_N * 13) / 8;
for (j = 0; j < SABER_N / 8; j++) {
offset_byte = offset_byte1 + 13 * j;
offset_data = 8 * j;
bytes[offset_byte + 0] = (data[i][offset_data + 0] & (0xff));
bytes[offset_byte + 1] = ((data[i][offset_data + 0] >> 8) & 0x1f) |
((data[i][offset_data + 1] & 0x07) << 5);
bytes[offset_byte + 2] = ((data[i][offset_data + 1] >> 3) & 0xff);
bytes[offset_byte + 3] = ((data[i][offset_data + 1] >> 11) & 0x03) |
((data[i][offset_data + 2] & 0x3f) << 2);
bytes[offset_byte + 4] = ((data[i][offset_data + 2] >> 6) & 0x7f) |
((data[i][offset_data + 3] & 0x01) << 7);
bytes[offset_byte + 5] = ((data[i][offset_data + 3] >> 1) & 0xff);
bytes[offset_byte + 6] = ((data[i][offset_data + 3] >> 9) & 0x0f) |
((data[i][offset_data + 4] & 0x0f) << 4);
bytes[offset_byte + 7] = ((data[i][offset_data + 4] >> 4) & 0xff);
bytes[offset_byte + 8] = ((data[i][offset_data + 4] >> 12) & 0x01) |
((data[i][offset_data + 5] & 0x7f) << 1);
bytes[offset_byte + 9] = ((data[i][offset_data + 5] >> 7) & 0x3f) |
((data[i][offset_data + 6] & 0x03) << 6);
bytes[offset_byte + 10] = ((data[i][offset_data + 6] >> 2) & 0xff);
bytes[offset_byte + 11] = ((data[i][offset_data + 6] >> 10) & 0x07) |
((data[i][offset_data + 7] & 0x1f) << 3);
bytes[offset_byte + 12] = ((data[i][offset_data + 7] >> 5) & 0xff);
}
}
}
static void BS2POLVECq(const unsigned char *bytes, uint16_t data[SABER_K][SABER_N]) {
uint32_t i, j;
uint32_t offset_data, offset_byte, offset_byte1;
for (i = 0; i < SABER_K; i++) {
offset_byte1 = i * (SABER_N * 13) / 8;
for (j = 0; j < SABER_N / 8; j++) {
offset_byte = offset_byte1 + 13 * j;
offset_data = 8 * j;
data[i][offset_data + 0] = (bytes[offset_byte + 0] & (0xff)) |
((bytes[offset_byte + 1] & 0x1f) << 8);
data[i][offset_data + 1] = (bytes[offset_byte + 1] >> 5 & (0x07)) |
((bytes[offset_byte + 2] & 0xff) << 3) |
((bytes[offset_byte + 3] & 0x03) << 11);
data[i][offset_data + 2] = (bytes[offset_byte + 3] >> 2 & (0x3f)) |
((bytes[offset_byte + 4] & 0x7f) << 6);
data[i][offset_data + 3] = (bytes[offset_byte + 4] >> 7 & (0x01)) |
((bytes[offset_byte + 5] & 0xff) << 1) |
((bytes[offset_byte + 6] & 0x0f) << 9);
data[i][offset_data + 4] = (bytes[offset_byte + 6] >> 4 & (0x0f)) |
((bytes[offset_byte + 7] & 0xff) << 4) |
((bytes[offset_byte + 8] & 0x01) << 12);
data[i][offset_data + 5] = (bytes[offset_byte + 8] >> 1 & (0x7f)) |
((bytes[offset_byte + 9] & 0x3f) << 7);
data[i][offset_data + 6] = (bytes[offset_byte + 9] >> 6 & (0x03)) |
((bytes[offset_byte + 10] & 0xff) << 2) |
((bytes[offset_byte + 11] & 0x07) << 10);
data[i][offset_data + 7] = (bytes[offset_byte + 11] >> 3 & (0x1f)) |
((bytes[offset_byte + 12] & 0xff) << 5);
}
}
}
//only BS2POLq no BS2POLp
void PQCLEAN_FIRESABER_CLEAN_BS2POL(const unsigned char *bytes, uint16_t data[SABER_N]) {
uint32_t j;
uint32_t offset_data, offset_byte;
for (j = 0; j < SABER_N / 8; j++) {
offset_byte = 13 * j;
offset_data = 8 * j;
data[offset_data + 0] = (bytes[offset_byte + 0] & (0xff)) |
((bytes[offset_byte + 1] & 0x1f) << 8);
data[offset_data + 1] = (bytes[offset_byte + 1] >> 5 & (0x07)) |
((bytes[offset_byte + 2] & 0xff) << 3) |
((bytes[offset_byte + 3] & 0x03) << 11);
data[offset_data + 2] = (bytes[offset_byte + 3] >> 2 & (0x3f)) |
((bytes[offset_byte + 4] & 0x7f) << 6);
data[offset_data + 3] = (bytes[offset_byte + 4] >> 7 & (0x01)) |
((bytes[offset_byte + 5] & 0xff) << 1) |
((bytes[offset_byte + 6] & 0x0f) << 9);
data[offset_data + 4] = (bytes[offset_byte + 6] >> 4 & (0x0f)) |
((bytes[offset_byte + 7] & 0xff) << 4) |
((bytes[offset_byte + 8] & 0x01) << 12);
data[offset_data + 5] = (bytes[offset_byte + 8] >> 1 & (0x7f)) |
((bytes[offset_byte + 9] & 0x3f) << 7);
data[offset_data + 6] = (bytes[offset_byte + 9] >> 6 & (0x03)) |
((bytes[offset_byte + 10] & 0xff) << 2) |
((bytes[offset_byte + 11] & 0x07) << 10);
data[offset_data + 7] = (bytes[offset_byte + 11] >> 3 & (0x1f)) |
((bytes[offset_byte + 12] & 0xff) << 5);
}
}
void PQCLEAN_FIRESABER_CLEAN_POLVEC2BS(uint8_t *bytes, uint16_t data[SABER_K][SABER_N], uint16_t modulus) {
if (modulus == 1024) {
POLVECp2BS(bytes, data);
} else if (modulus == 8192) {
POLVECq2BS(bytes, data);
}
}
void PQCLEAN_FIRESABER_CLEAN_BS2POLVEC(const unsigned char *bytes, uint16_t data[SABER_K][SABER_N], uint16_t modulus) {
if (modulus == 1024) {
BS2POLVECp(bytes, data);
} else if (modulus == 8192) {
BS2POLVECq(bytes, data);
}
}

View File

@ -0,0 +1,28 @@
#ifndef PACK_UNPACK_H
#define PACK_UNPACK_H
#include "SABER_params.h"
#include <stdint.h>
#include <stdio.h>
void PQCLEAN_FIRESABER_CLEAN_pack_3bit(uint8_t *bytes, const uint16_t *data);
void PQCLEAN_FIRESABER_CLEAN_un_pack3bit(const uint8_t *bytes, uint16_t *data);
void PQCLEAN_FIRESABER_CLEAN_pack_4bit(uint8_t *bytes, const uint16_t *data);
void PQCLEAN_FIRESABER_CLEAN_un_pack4bit(const unsigned char *bytes, uint16_t *ar);
void PQCLEAN_FIRESABER_CLEAN_pack_6bit(uint8_t *bytes, const uint16_t *data);
void PQCLEAN_FIRESABER_CLEAN_un_pack6bit(const unsigned char *bytes, uint16_t *data);
void PQCLEAN_FIRESABER_CLEAN_BS2POL(const unsigned char *bytes, uint16_t data[SABER_N]);
void PQCLEAN_FIRESABER_CLEAN_POLVEC2BS(uint8_t *bytes, uint16_t data[SABER_K][SABER_N], uint16_t modulus);
void PQCLEAN_FIRESABER_CLEAN_BS2POLVEC(const unsigned char *bytes, uint16_t data[SABER_K][SABER_N], uint16_t modulus);
#endif

View File

@ -0,0 +1,21 @@
/*---------------------------------------------------------------------
This file has been adapted from the implementation
(available at, Public Domain https://github.com/pq-crystals/kyber)
of "CRYSTALS Kyber: a CCA-secure module-lattice-based KEM"
by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint,
Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle
----------------------------------------------------------------------*/
#include "SABER_params.h"
#include "cbd.h"
#include "fips202.h"
#include "poly.h"
void PQCLEAN_FIRESABER_CLEAN_GenSecret(uint16_t r[SABER_K][SABER_N], const unsigned char *seed) {
uint8_t buf[SABER_MU * SABER_N * SABER_K / 8];
shake128(buf, sizeof(buf), seed, SABER_NOISESEEDBYTES);
for (size_t i = 0; i < SABER_K; i++) {
PQCLEAN_FIRESABER_CLEAN_cbd(r[i], buf + i * SABER_MU * SABER_N / 8);
}
}

View File

@ -0,0 +1,26 @@
#ifndef POLY_H
#define POLY_H
/*---------------------------------------------------------------------
This file has been adapted from the implementation
(available at, Public Domain https://github.com/pq-crystals/kyber)
of "CRYSTALS Kyber: a CCA-secure module-lattice-based KEM"
by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint,
Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle
----------------------------------------------------------------------*/
#include "SABER_params.h"
#include <stdint.h>
typedef struct {
uint16_t coeffs[SABER_N];
} poly;
typedef struct {
poly vec[SABER_K];
} polyvec;
void PQCLEAN_FIRESABER_CLEAN_GenSecret(uint16_t r[SABER_K][SABER_N], const unsigned char *seed);
#endif

View File

@ -0,0 +1,237 @@
#include "poly_mul.h"
#include <stdint.h>
#include <string.h>
#define SCHB_N 16
#define N_RES (SABER_N << 1)
#define N_SB (SABER_N >> 2)
#define N_SB_RES (2*N_SB-1)
#define KARATSUBA_N 64
static void karatsuba_simple(const uint16_t *a_1, const uint16_t *b_1, uint16_t *result_final) {
uint16_t d01[KARATSUBA_N / 2 - 1];
uint16_t d0123[KARATSUBA_N / 2 - 1];
uint16_t d23[KARATSUBA_N / 2 - 1];
uint16_t result_d01[KARATSUBA_N - 1];
int32_t i, j;
memset(result_d01, 0, (KARATSUBA_N - 1)*sizeof(uint16_t));
memset(d01, 0, (KARATSUBA_N / 2 - 1)*sizeof(uint16_t));
memset(d0123, 0, (KARATSUBA_N / 2 - 1)*sizeof(uint16_t));
memset(d23, 0, (KARATSUBA_N / 2 - 1)*sizeof(uint16_t));
memset(result_final, 0, (2 * KARATSUBA_N - 1)*sizeof(uint16_t));
uint16_t acc1, acc2, acc3, acc4, acc5, acc6, acc7, acc8, acc9, acc10;
for (i = 0; i < KARATSUBA_N / 4; i++) {
acc1 = a_1[i]; //a0
acc2 = a_1[i + KARATSUBA_N / 4]; //a1
acc3 = a_1[i + 2 * KARATSUBA_N / 4]; //a2
acc4 = a_1[i + 3 * KARATSUBA_N / 4]; //a3
for (j = 0; j < KARATSUBA_N / 4; j++) {
acc5 = b_1[j]; //b0
acc6 = b_1[j + KARATSUBA_N / 4]; //b1
result_final[i + j + 0 * KARATSUBA_N / 4] = result_final[i + j + 0 * KARATSUBA_N / 4] + acc1 * acc5;
result_final[i + j + 2 * KARATSUBA_N / 4] = result_final[i + j + 2 * KARATSUBA_N / 4] + acc2 * acc6;
acc7 = acc5 + acc6; //b01
acc8 = acc1 + acc2; //a01
d01[i + j] = d01[i + j] + acc7 * acc8;
//--------------------------------------------------------
acc7 = b_1[j + 2 * KARATSUBA_N / 4]; //b2
acc8 = b_1[j + 3 * KARATSUBA_N / 4]; //b3
result_final[i + j + 4 * KARATSUBA_N / 4] = result_final[i + j + 4 * KARATSUBA_N / 4] + acc7 * acc3;
result_final[i + j + 6 * KARATSUBA_N / 4] = result_final[i + j + 6 * KARATSUBA_N / 4] + acc8 * acc4;
acc9 = acc3 + acc4;
acc10 = acc7 + acc8;
d23[i + j] = d23[i + j] + acc9 * acc10;
//--------------------------------------------------------
acc5 = acc5 + acc7; //b02
acc7 = acc1 + acc3; //a02
result_d01[i + j + 0 * KARATSUBA_N / 4] = result_d01[i + j + 0 * KARATSUBA_N / 4] + acc5 * acc7;
acc6 = acc6 + acc8; //b13
acc8 = acc2 + acc4;
result_d01[i + j + 2 * KARATSUBA_N / 4] = result_d01[i + j + 2 * KARATSUBA_N / 4] + acc6 * acc8;
acc5 = acc5 + acc6;
acc7 = acc7 + acc8;
d0123[i + j] = d0123[i + j] + acc5 * acc7;
}
}
// 2nd last stage
for (i = 0; i < KARATSUBA_N / 2 - 1; i++) {
d0123[i] = d0123[i] - result_d01[i + 0 * KARATSUBA_N / 4] - result_d01[i + 2 * KARATSUBA_N / 4];
d01[i] = d01[i] - result_final[i + 0 * KARATSUBA_N / 4] - result_final[i + 2 * KARATSUBA_N / 4];
d23[i] = d23[i] - result_final[i + 4 * KARATSUBA_N / 4] - result_final[i + 6 * KARATSUBA_N / 4];
}
for (i = 0; i < KARATSUBA_N / 2 - 1; i++) {
result_d01[i + 1 * KARATSUBA_N / 4] = result_d01[i + 1 * KARATSUBA_N / 4] + d0123[i];
result_final[i + 1 * KARATSUBA_N / 4] = result_final[i + 1 * KARATSUBA_N / 4] + d01[i];
result_final[i + 5 * KARATSUBA_N / 4] = result_final[i + 5 * KARATSUBA_N / 4] + d23[i];
}
// Last stage
for (i = 0; i < KARATSUBA_N - 1; i++) {
result_d01[i] = result_d01[i] - result_final[i] - result_final[i + KARATSUBA_N];
}
for (i = 0; i < KARATSUBA_N - 1; i++) {
result_final[i + 1 * KARATSUBA_N / 2] = result_final[i + 1 * KARATSUBA_N / 2] + result_d01[i];
}
}
static void toom_cook_4way (const uint16_t *a1, const uint16_t *b1, uint16_t *result) {
uint16_t inv3 = 43691, inv9 = 36409, inv15 = 61167;
uint16_t aw1[N_SB], aw2[N_SB], aw3[N_SB], aw4[N_SB], aw5[N_SB], aw6[N_SB], aw7[N_SB];
uint16_t bw1[N_SB], bw2[N_SB], bw3[N_SB], bw4[N_SB], bw5[N_SB], bw6[N_SB], bw7[N_SB];
uint16_t w1[N_SB_RES] = {0}, w2[N_SB_RES] = {0}, w3[N_SB_RES] = {0}, w4[N_SB_RES] = {0},
w5[N_SB_RES] = {0}, w6[N_SB_RES] = {0}, w7[N_SB_RES] = {0};
uint16_t r0, r1, r2, r3, r4, r5, r6, r7;
uint16_t *A0, *A1, *A2, *A3, *B0, *B1, *B2, *B3;
A0 = (uint16_t *)a1;
A1 = (uint16_t *)&a1[N_SB];
A2 = (uint16_t *)&a1[2 * N_SB];
A3 = (uint16_t *)&a1[3 * N_SB];
B0 = (uint16_t *)b1;
B1 = (uint16_t *)&b1[N_SB];
B2 = (uint16_t *)&b1[2 * N_SB];
B3 = (uint16_t *)&b1[3 * N_SB];
uint16_t *C;
C = result;
int i, j;
// EVALUATION
for (j = 0; j < N_SB; ++j) {
r0 = A0[j];
r1 = A1[j];
r2 = A2[j];
r3 = A3[j];
r4 = r0 + r2;
r5 = r1 + r3;
r6 = r4 + r5;
r7 = r4 - r5;
aw3[j] = r6;
aw4[j] = r7;
r4 = ((r0 << 2) + r2) << 1;
r5 = (r1 << 2) + r3;
r6 = r4 + r5;
r7 = r4 - r5;
aw5[j] = r6;
aw6[j] = r7;
r4 = (r3 << 3) + (r2 << 2) + (r1 << 1) + r0;
aw2[j] = r4;
aw7[j] = r0;
aw1[j] = r3;
}
for (j = 0; j < N_SB; ++j) {
r0 = B0[j];
r1 = B1[j];
r2 = B2[j];
r3 = B3[j];
r4 = r0 + r2;
r5 = r1 + r3;
r6 = r4 + r5;
r7 = r4 - r5;
bw3[j] = r6;
bw4[j] = r7;
r4 = ((r0 << 2) + r2) << 1;
r5 = (r1 << 2) + r3;
r6 = r4 + r5;
r7 = r4 - r5;
bw5[j] = r6;
bw6[j] = r7;
r4 = (r3 << 3) + (r2 << 2) + (r1 << 1) + r0;
bw2[j] = r4;
bw7[j] = r0;
bw1[j] = r3;
}
// MULTIPLICATION
karatsuba_simple(aw1, bw1, w1);
karatsuba_simple(aw2, bw2, w2);
karatsuba_simple(aw3, bw3, w3);
karatsuba_simple(aw4, bw4, w4);
karatsuba_simple(aw5, bw5, w5);
karatsuba_simple(aw6, bw6, w6);
karatsuba_simple(aw7, bw7, w7);
// INTERPOLATION
for (i = 0; i < N_SB_RES; ++i) {
r0 = w1[i];
r1 = w2[i];
r2 = w3[i];
r3 = w4[i];
r4 = w5[i];
r5 = w6[i];
r6 = w7[i];
r1 = r1 + r4;
r5 = r5 - r4;
r3 = ((r3 - r2) >> 1);
r4 = r4 - r0;
r4 = r4 - (r6 << 6);
r4 = (r4 << 1) + r5;
r2 = r2 + r3;
r1 = r1 - (r2 << 6) - r2;
r2 = r2 - r6;
r2 = r2 - r0;
r1 = r1 + 45 * r2;
r4 = (((r4 - (r2 << 3)) * inv3) >> 3);
r5 = r5 + r1;
r1 = (((r1 + (r3 << 4)) * inv9) >> 1);
r3 = -(r3 + r1);
r5 = (((30 * r1 - r5) * inv15) >> 2);
r2 = r2 - r4;
r1 = r1 - r5;
C[i] += r6;
C[i + 64] += r5;
C[i + 128] += r4;
C[i + 192] += r3;
C[i + 256] += r2;
C[i + 320] += r1;
C[i + 384] += r0;
}
}
void PQCLEAN_FIRESABER_CLEAN_pol_mul(uint16_t *a, uint16_t *b, uint16_t *res, uint16_t p, uint32_t n)
{
uint32_t i;
// normal multiplication
uint16_t c[512];
for (i = 0; i < 512; i++) {
c[i] = 0;
}
toom_cook_4way(a, b, c);
// reduction
for (i = n; i < 2 * n; i++) {
res[i - n] = (c[i - n] - c[i]) & (p - 1);
}
}

View File

@ -0,0 +1,9 @@
#ifndef POLYMUL_H
#define POLYMUL_H
#include "SABER_params.h"
#include <stdint.h>
void PQCLEAN_FIRESABER_CLEAN_pol_mul(uint16_t *a, uint16_t *b, uint16_t *res, uint16_t p, uint32_t n);
#endif

View File

@ -0,0 +1,34 @@
/*-------------------------------------------------
This file has been adapted from the implementation
(available at https://github.com/pq-crystals/kyber) of
"CRYSTALS Kyber: a CCA-secure module-lattice-based KEM"
by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint,
Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle
----------------------------------------------------*/
#include "verify.h"
#include <stdint.h>
/* returns 0 for equal strings, 1 for non-equal strings */
unsigned char PQCLEAN_FIRESABER_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len) {
uint64_t r;
size_t i;
r = 0;
for (i = 0; i < len; i++) {
r |= a[i] ^ b[i];
}
r = (~r + 1); // Two's complement
r >>= 63;
return (unsigned char)r;
}
/* b = 1 means mov, b = 0 means don't mov*/
void PQCLEAN_FIRESABER_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b) {
size_t i;
b = -b;
for (i = 0; i < len; i++) {
r[i] ^= b & (x[i] ^ r[i]);
}
}

View File

@ -0,0 +1,21 @@
#ifndef VERIFY_H
#define VERIFY_H
/*-------------------------------------------------
This file has been adapted from the implementation
(available at https://github.com/pq-crystals/kyber) of
"CRYSTALS Kyber: a CCA-secure module-lattice-based KEM"
by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint,
Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle
----------------------------------------------------*/
#include <stddef.h>
#include <stdint.h>
/* returns 0 for equal strings, 1 for non-equal strings */
unsigned char PQCLEAN_FIRESABER_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len);
/* b = 1 means mov, b = 0 means don't mov*/
void PQCLEAN_FIRESABER_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b);
#endif

View File

@ -0,0 +1,8 @@
----------------------------------------------------------------------------------------
SABER_v1.1
Public domain
Authors: Jan-Pieter D'Anvers, Angshuman Karmakar, Sujoy Sinha Roy,
Frederik Vercauteren
----------------------------------------------------------------------------------------

View File

@ -0,0 +1,298 @@
#include "SABER_indcpa.h"
#include "SABER_params.h"
#include "fips202.h"
#include "pack_unpack.h"
#include "poly.h"
#include "poly_mul.h"
#include "randombytes.h"
#include <stdint.h>
#include <string.h>
/*-----------------------------------------------------------------------------------
This routine generates a=[Matrix K x K] of 256-coefficient polynomials
-------------------------------------------------------------------------------------*/
#define h1 4 //2^(EQ-EP-1)
#define h2 ( (1<<(SABER_EP-2)) - (1<<(SABER_EP-SABER_ET-1)) + (1<<(SABER_EQ-SABER_EP-1)) )
static void InnerProd(uint16_t pkcl[SABER_K][SABER_N], uint16_t skpv[SABER_K][SABER_N], uint16_t mod, uint16_t res[SABER_N]);
static void MatrixVectorMul(polyvec *a, uint16_t skpv[SABER_K][SABER_N], uint16_t res[SABER_K][SABER_N], uint16_t mod, int16_t transpose);
static void POL2MSG(const uint16_t *message_dec_unpacked, unsigned char *message_dec);
static void GenMatrix(polyvec *a, const unsigned char *seed) {
unsigned char buf[SABER_K * SABER_K * (13 * SABER_N / 8)];
uint16_t temp_ar[SABER_N];
int i, j, k;
uint16_t mod = (SABER_Q - 1);
shake128(buf, sizeof(buf), seed, SABER_SEEDBYTES);
for (i = 0; i < SABER_K; i++) {
for (j = 0; j < SABER_K; j++) {
PQCLEAN_LIGHTSABER_CLEAN_BS2POL(buf + (i * SABER_K + j) * (13 * SABER_N / 8), temp_ar);
for (k = 0; k < SABER_N; k++) {
a[i].vec[j].coeffs[k] = (temp_ar[k])& mod ;
}
}
}
}
void PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_keypair(unsigned char *pk, unsigned char *sk) {
polyvec a[SABER_K];
uint16_t skpv[SABER_K][SABER_N];
unsigned char seed[SABER_SEEDBYTES];
unsigned char noiseseed[SABER_COINBYTES];
int32_t i, j;
uint16_t mod_q = SABER_Q - 1;
uint16_t res[SABER_K][SABER_N];
randombytes(seed, SABER_SEEDBYTES);
// for not revealing system RNG state
shake128(seed, SABER_SEEDBYTES, seed, SABER_SEEDBYTES);
randombytes(noiseseed, SABER_COINBYTES);
GenMatrix(a, seed); //sample matrix A
// generate secret from constant-time binomial distribution
PQCLEAN_LIGHTSABER_CLEAN_GenSecret(skpv, noiseseed);
// do the matrix vector multiplication and rounding
for (i = 0; i < SABER_K; i++) {
for (j = 0; j < SABER_N; j++) {
res[i][j] = 0;
}
}
MatrixVectorMul(a, skpv, res, SABER_Q - 1, 1);
// now rounding
for (i = 0; i < SABER_K; i++) {
for (j = 0; j < SABER_N; j++) {
// shift right 3 bits
res[i][j] = (res[i][j] + h1) & (mod_q);
res[i][j] = (res[i][j] >> (SABER_EQ - SABER_EP));
}
}
// unload and pack sk=3 x (256 coefficients of 14 bits)
PQCLEAN_LIGHTSABER_CLEAN_POLVEC2BS(sk, skpv, SABER_Q);
// unload and pack pk=256 bits seed and 3 x (256 coefficients of 11 bits)
// load the public-key coefficients
PQCLEAN_LIGHTSABER_CLEAN_POLVEC2BS(pk, res, SABER_P);
// now load the seedbytes in PK. Easy since seed bytes are kept in byte format.
for (i = 0; i < SABER_SEEDBYTES; i++) {
pk[SABER_POLYVECCOMPRESSEDBYTES + i] = seed[i];
}
}
void PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_enc(const unsigned char *message_received, unsigned char *noiseseed, const unsigned char *pk, unsigned char *ciphertext) {
uint32_t i, j, k;
polyvec a[SABER_K];
unsigned char seed[SABER_SEEDBYTES];
// public key of received by the client
uint16_t pkcl[SABER_K][SABER_N];
uint16_t skpv1[SABER_K][SABER_N];
uint16_t message[SABER_KEYBYTES * 8];
uint16_t res[SABER_K][SABER_N];
uint16_t mod_p = SABER_P - 1;
uint16_t mod_q = SABER_Q - 1;
uint16_t vprime[SABER_N];
unsigned char msk_c[SABER_SCALEBYTES_KEM];
// extract the seedbytes from Public Key.
for (i = 0; i < SABER_SEEDBYTES; i++) {
seed[i] = pk[ SABER_POLYVECCOMPRESSEDBYTES + i];
}
GenMatrix(a, seed);
// generate secret from constant-time binomial distribution
PQCLEAN_LIGHTSABER_CLEAN_GenSecret(skpv1, noiseseed);
// matrix-vector multiplication and rounding
for (i = 0; i < SABER_K; i++) {
for (j = 0; j < SABER_N; j++) {
res[i][j] = 0;
}
}
MatrixVectorMul(a, skpv1, res, SABER_Q - 1, 0);
// now rounding
//shift right 3 bits
for (i = 0; i < SABER_K; i++) {
for (j = 0; j < SABER_N; j++) {
res[i][j] = ( res[i][j] + h1 ) & mod_q;
res[i][j] = (res[i][j] >> (SABER_EQ - SABER_EP) );
}
}
PQCLEAN_LIGHTSABER_CLEAN_POLVEC2BS(ciphertext, res, SABER_P);
// ************client matrix-vector multiplication ends************
// now calculate the v'
// unpack the public_key
// pkcl is the b in the protocol
PQCLEAN_LIGHTSABER_CLEAN_BS2POLVEC(pk, pkcl, SABER_P);
for (i = 0; i < SABER_N; i++) {
vprime[i] = 0;
}
for (i = 0; i < SABER_K; i++) {
for (j = 0; j < SABER_N; j++) {
skpv1[i][j] = skpv1[i][j] & (mod_p);
}
}
// vector-vector scalar multiplication with mod p
InnerProd(pkcl, skpv1, mod_p, vprime);
// addition of h1 to vprime
for (i = 0; i < SABER_N; i++) {
vprime[i] = vprime[i] + h1;
}
// unpack message_received;
for (j = 0; j < SABER_KEYBYTES; j++) {
for (i = 0; i < 8; i++) {
message[8 * j + i] = ((message_received[j] >> i) & 0x01);
}
}
// message encoding
for (i = 0; i < SABER_N; i++) {
message[i] = (message[i] << (SABER_EP - 1));
}
for (k = 0; k < SABER_N; k++) {
vprime[k] = ( (vprime[k] - message[k]) & (mod_p) ) >> (SABER_EP - SABER_ET);
}
PQCLEAN_LIGHTSABER_CLEAN_pack_3bit(msk_c, vprime);
for (j = 0; j < SABER_SCALEBYTES_KEM; j++) {
ciphertext[SABER_POLYVECCOMPRESSEDBYTES + j] = msk_c[j];
}
}
void PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_dec(const unsigned char *sk, const unsigned char *ciphertext, unsigned char message_dec[]) {
uint32_t i, j;
// secret key of the server
uint16_t sksv[SABER_K][SABER_N];
uint16_t pksv[SABER_K][SABER_N];
uint8_t scale_ar[SABER_SCALEBYTES_KEM];
uint16_t mod_p = SABER_P - 1;
uint16_t v[SABER_N];
uint16_t op[SABER_N];
// sksv is the secret-key
PQCLEAN_LIGHTSABER_CLEAN_BS2POLVEC(sk, sksv, SABER_Q);
// pksv is the ciphertext
PQCLEAN_LIGHTSABER_CLEAN_BS2POLVEC(ciphertext, pksv, SABER_P);
// vector-vector scalar multiplication with mod p
for (i = 0; i < SABER_N; i++) {
v[i] = 0;
}
for (i = 0; i < SABER_K; i++) {
for (j = 0; j < SABER_N; j++) {
sksv[i][j] = sksv[i][j] & (mod_p);
}
}
InnerProd(pksv, sksv, mod_p, v);
//Extraction
for (i = 0; i < SABER_SCALEBYTES_KEM; i++) {
scale_ar[i] = ciphertext[SABER_POLYVECCOMPRESSEDBYTES + i];
}
PQCLEAN_LIGHTSABER_CLEAN_un_pack3bit(scale_ar, op);
//addition of h1
for (i = 0; i < SABER_N; i++) {
v[i] = ( ( v[i] + h2 - (op[i] << (SABER_EP - SABER_ET)) ) & (mod_p) ) >> (SABER_EP - 1);
}
// pack decrypted message
POL2MSG(v, message_dec);
}
static void MatrixVectorMul(polyvec *a, uint16_t skpv[SABER_K][SABER_N], uint16_t res[SABER_K][SABER_N], uint16_t mod, int16_t transpose) {
uint16_t acc[SABER_N];
int32_t i, j, k;
if (transpose == 1) {
for (i = 0; i < SABER_K; i++) {
for (j = 0; j < SABER_K; j++) {
PQCLEAN_LIGHTSABER_CLEAN_pol_mul((uint16_t *)&a[j].vec[i], skpv[j], acc, SABER_Q, SABER_N);
for (k = 0; k < SABER_N; k++) {
res[i][k] = res[i][k] + acc[k];
//reduction mod p
res[i][k] = (res[i][k] & mod);
//clear the accumulator
acc[k] = 0;
}
}
}
} else {
for (i = 0; i < SABER_K; i++) {
for (j = 0; j < SABER_K; j++) {
PQCLEAN_LIGHTSABER_CLEAN_pol_mul((uint16_t *)&a[i].vec[j], skpv[j], acc, SABER_Q, SABER_N);
for (k = 0; k < SABER_N; k++) {
res[i][k] = res[i][k] + acc[k];
// reduction
res[i][k] = res[i][k] & mod;
// clear the accumulator
acc[k] = 0;
}
}
}
}
}
static void POL2MSG(const uint16_t *message_dec_unpacked, unsigned char *message_dec) {
int32_t i, j;
for (j = 0; j < SABER_KEYBYTES; j++) {
message_dec[j] = 0;
for (i = 0; i < 8; i++) {
message_dec[j] = message_dec[j] | (uint8_t) (message_dec_unpacked[j * 8 + i] << i);
}
}
}
static void InnerProd(uint16_t pkcl[SABER_K][SABER_N], uint16_t skpv[SABER_K][SABER_N], uint16_t mod, uint16_t res[SABER_N]) {
uint32_t j, k;
uint16_t acc[SABER_N];
// vector-vector scalar multiplication with mod p
for (j = 0; j < SABER_K; j++) {
PQCLEAN_LIGHTSABER_CLEAN_pol_mul(pkcl[j], skpv[j], acc, SABER_P, SABER_N);
for (k = 0; k < SABER_N; k++) {
res[k] = res[k] + acc[k];
// reduction
res[k] = res[k] & mod;
// clear the accumulator
acc[k] = 0;
}
}
}

View File

@ -0,0 +1,9 @@
#ifndef INDCPA_H
#define INDCPA_H
void PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_keypair(unsigned char *pk, unsigned char *sk);
void PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_enc(const unsigned char *message, unsigned char *noiseseed, const unsigned char *pk, unsigned char *ciphertext);
void PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_dec(const unsigned char *sk, const unsigned char *ciphertext, unsigned char *message_dec);
#endif

View File

@ -0,0 +1,50 @@
#ifndef PARAMS_H
#define PARAMS_H
#include "api.h"
#define SABER_K 2
#define SABER_MU 10
#define SABER_ET 3
#define SABER_EQ 13
#define SABER_EP 10
#define SABER_N 256
#define SABER_Q 8192
#define SABER_P 1024
#define SABER_SEEDBYTES 32
#define SABER_NOISESEEDBYTES 32
#define SABER_COINBYTES 32
#define SABER_KEYBYTES 32
#define SABER_HASHBYTES 32
#define SABER_POLYBYTES 416 //13*256/8
#define SABER_POLYVECBYTES (SABER_K * SABER_POLYBYTES)
#define SABER_POLYVECCOMPRESSEDBYTES (SABER_K * 320) //10*256/8 NOTE : changed till here due to parameter adaptation
#define SABER_CIPHERTEXTBYTES (SABER_POLYVECCOMPRESSEDBYTES)
#define SABER_SCALEBYTES (SABER_DELTA*SABER_N/8)
#define SABER_SCALEBYTES_KEM ((SABER_ET)*SABER_N/8)
#define SABER_INDCPA_PUBLICKEYBYTES (SABER_POLYVECCOMPRESSEDBYTES + SABER_SEEDBYTES)
#define SABER_INDCPA_SECRETKEYBYTES (SABER_POLYVECBYTES)
#define SABER_PUBLICKEYBYTES (SABER_INDCPA_PUBLICKEYBYTES)
#define SABER_SECRETKEYBYTES (SABER_INDCPA_SECRETKEYBYTES + SABER_INDCPA_PUBLICKEYBYTES + SABER_HASHBYTES + SABER_KEYBYTES)
#define SABER_BYTES_CCA_DEC (SABER_POLYVECCOMPRESSEDBYTES + SABER_SCALEBYTES_KEM) /* Second part is for Targhi-Unruh */
#endif

View File

@ -0,0 +1,14 @@
#ifndef PQCLEAN_LIGHTSABER_CLEAN_API_H
#define PQCLEAN_LIGHTSABER_CLEAN_API_H
#define PQCLEAN_LIGHTSABER_CLEAN_CRYPTO_ALGNAME "LightSaber"
#define PQCLEAN_LIGHTSABER_CLEAN_CRYPTO_SECRETKEYBYTES 1568
#define PQCLEAN_LIGHTSABER_CLEAN_CRYPTO_PUBLICKEYBYTES (2*320+32)
#define PQCLEAN_LIGHTSABER_CLEAN_CRYPTO_BYTES 32
#define PQCLEAN_LIGHTSABER_CLEAN_CRYPTO_CIPHERTEXTBYTES 736
int PQCLEAN_LIGHTSABER_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk);
int PQCLEAN_LIGHTSABER_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk);
int PQCLEAN_LIGHTSABER_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk);
#endif /* api_h */

View File

@ -0,0 +1,51 @@
/*---------------------------------------------------------------------
This file has been adapted from the implementation
(available at, Public Domain https://github.com/pq-crystals/kyber)
of "CRYSTALS Kyber: a CCA-secure module-lattice-based KEM"
by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint,
Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle
----------------------------------------------------------------------*/
#include "SABER_params.h"
#include "api.h"
#include "cbd.h"
#include <stdint.h>
static uint64_t load_littleendian(const unsigned char *x, int bytes) {
int i;
uint64_t r = x[0];
for (i = 1; i < bytes; i++) {
r |= (uint64_t)x[i] << (8 * i);
}
return r;
}
void PQCLEAN_LIGHTSABER_CLEAN_cbd(uint16_t *r, const unsigned char *buf) {
uint16_t Qmod_minus1 = SABER_Q - 1;
uint64_t t, d, a[4], b[4];
int i, j;
for (i = 0; i < SABER_N / 4; i++) {
t = load_littleendian(buf + 5 * i, 5);
d = 0;
for (j = 0; j < 5; j++) {
d += (t >> j) & 0x0842108421UL;
}
a[0] = d & 0x1f;
b[0] = (d >> 5) & 0x1f;
a[1] = (d >> 10) & 0x1f;
b[1] = (d >> 15) & 0x1f;
a[2] = (d >> 20) & 0x1f;
b[2] = (d >> 25) & 0x1f;
a[3] = (d >> 30) & 0x1f;
b[3] = (d >> 35);
r[4 * i + 0] = (uint16_t)(a[0] - b[0]) & Qmod_minus1;
r[4 * i + 1] = (uint16_t)(a[1] - b[1]) & Qmod_minus1;
r[4 * i + 2] = (uint16_t)(a[2] - b[2]) & Qmod_minus1;
r[4 * i + 3] = (uint16_t)(a[3] - b[3]) & Qmod_minus1;
}
}

View File

@ -0,0 +1,17 @@
#ifndef CBD_H
#define CBD_H
/*---------------------------------------------------------------------
This file has been adapted from the implementation
(available at, Public Domain https://github.com/pq-crystals/kyber)
of "CRYSTALS Kyber: a CCA-secure module-lattice-based KEM"
by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint,
Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle
----------------------------------------------------------------------*/
#include "poly.h"
#include <stdint.h>
void PQCLEAN_LIGHTSABER_CLEAN_cbd(uint16_t *r, const unsigned char *buf);
#endif

View File

@ -0,0 +1,96 @@
#include "SABER_indcpa.h"
#include "SABER_params.h"
#include "fips202.h"
#include "randombytes.h"
#include "verify.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
int PQCLEAN_LIGHTSABER_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk) {
int i;
// sk[0:SABER_INDCPA_SECRETKEYBYTES-1] <-- sk
PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_keypair(pk, sk);
// sk[SABER_INDCPA_SECRETKEYBYTES:SABER_INDCPA_SECRETKEYBYTES+SABER_INDCPA_SECRETKEYBYTES-1] <-- pk
for (i = 0; i < SABER_INDCPA_PUBLICKEYBYTES; i++) {
sk[i + SABER_INDCPA_SECRETKEYBYTES] = pk[i];
}
// Then hash(pk) is appended.
sha3_256(sk + SABER_SECRETKEYBYTES - 64, pk, SABER_INDCPA_PUBLICKEYBYTES);
// Remaining part of sk contains a pseudo-random number.
// This is output when check in crypto_kem_dec() fails.
randombytes(sk + SABER_SECRETKEYBYTES - SABER_KEYBYTES, SABER_KEYBYTES );
return (0);
}
int PQCLEAN_LIGHTSABER_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) {
// Will contain key, coins
unsigned char kr[64];
unsigned char buf[64];
randombytes(buf, 32);
// BUF[0:31] <-- random message (will be used as the key for client) Note: hash doesnot release system RNG output
sha3_256(buf, buf, 32);
// BUF[32:63] <-- Hash(public key); Multitarget countermeasure for coins + contributory KEM
sha3_256(buf + 32, pk, SABER_INDCPA_PUBLICKEYBYTES);
// kr[0:63] <-- Hash(buf[0:63]);
sha3_512(kr, buf, 64);
// K^ <-- kr[0:31]
// noiseseed (r) <-- kr[32:63];
// buf[0:31] contains message; kr[32:63] contains randomness r;
PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_enc(buf, kr + 32, pk, ct);
sha3_256(kr + 32, ct, SABER_BYTES_CCA_DEC);
// hash concatenation of pre-k and h(c) to k
sha3_256(ss, kr, 64);
return (0);
}
int PQCLEAN_LIGHTSABER_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) {
int i;
unsigned char fail;
unsigned char cmp[SABER_BYTES_CCA_DEC];
unsigned char buf[64];
// Will contain key, coins
unsigned char kr[64];
const unsigned char *pk = sk + SABER_INDCPA_SECRETKEYBYTES;
// buf[0:31] <-- message
PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_dec(sk, ct, buf);
// Multitarget countermeasure for coins + contributory KEM
// Save hash by storing h(pk) in sk
for (i = 0; i < 32; i++) {
buf[32 + i] = sk[SABER_SECRETKEYBYTES - 64 + i];
}
sha3_512(kr, buf, 64);
PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_enc(buf, kr + 32, pk, cmp);
fail = PQCLEAN_LIGHTSABER_CLEAN_verify(ct, cmp, SABER_BYTES_CCA_DEC);
// overwrite coins in kr with h(c)
sha3_256(kr + 32, ct, SABER_BYTES_CCA_DEC);
PQCLEAN_LIGHTSABER_CLEAN_cmov(kr, sk + SABER_SECRETKEYBYTES - SABER_KEYBYTES, SABER_KEYBYTES, fail);
// hash concatenation of pre-k and h(c) to k
sha3_256(ss, kr, 64);
return (0);
}

View File

@ -0,0 +1,254 @@
#include "pack_unpack.h"
void PQCLEAN_LIGHTSABER_CLEAN_pack_3bit(uint8_t *bytes, const uint16_t *data) {
uint32_t j;
uint32_t offset_data, offset_byte;
for (j = 0; j < SABER_N / 8; j++) {
offset_byte = 3 * j;
offset_data = 8 * j;
bytes[offset_byte + 0] = (data[offset_data + 0] & 0x7) |
((data[offset_data + 1] & 0x7) << 3) |
((data[offset_data + 2] & 0x3) << 6);
bytes[offset_byte + 1] = ((data[offset_data + 2] >> 2 ) & 0x01) |
((data[offset_data + 3] & 0x7) << 1) |
((data[offset_data + 4] & 0x7) << 4) |
(((data[offset_data + 5]) & 0x01) << 7);
bytes[offset_byte + 2] = ((data[offset_data + 5] >> 1 ) & 0x03) |
((data[offset_data + 6] & 0x7) << 2) |
((data[offset_data + 7] & 0x7) << 5);
}
}
void PQCLEAN_LIGHTSABER_CLEAN_un_pack3bit(const uint8_t *bytes, uint16_t *data) {
uint32_t j;
uint32_t offset_data, offset_byte;
for (j = 0; j < SABER_N / 8; j++) {
offset_byte = 3 * j;
offset_data = 8 * j;
data[offset_data + 0] = (bytes[offset_byte + 0]) & 0x07;
data[offset_data + 1] = ((bytes[offset_byte + 0]) >> 3 ) & 0x07;
data[offset_data + 2] = (((bytes[offset_byte + 0]) >> 6 ) & 0x03) |
(((bytes[offset_byte + 1]) & 0x01) << 2);
data[offset_data + 3] = ((bytes[offset_byte + 1]) >> 1 ) & 0x07;
data[offset_data + 4] = ((bytes[offset_byte + 1]) >> 4 ) & 0x07;
data[offset_data + 5] = (((bytes[offset_byte + 1]) >> 7 ) & 0x01) |
(((bytes[offset_byte + 2]) & 0x03) << 1);
data[offset_data + 6] = ((bytes[offset_byte + 2] >> 2) & 0x07);
data[offset_data + 7] = ((bytes[offset_byte + 2] >> 5) & 0x07);
}
}
void PQCLEAN_LIGHTSABER_CLEAN_pack_4bit(uint8_t *bytes, const uint16_t *data) {
uint32_t j;
uint32_t offset_data;
for (j = 0; j < SABER_N / 2; j++) {
offset_data = 2 * j;
bytes[j] = (data[offset_data] & 0x0f) |
((data[offset_data + 1] & 0x0f) << 4);
}
}
void PQCLEAN_LIGHTSABER_CLEAN_un_pack4bit(const unsigned char *bytes, uint16_t *ar) {
uint32_t j;
uint32_t offset_data;
for (j = 0; j < SABER_N / 2; j++) {
offset_data = 2 * j;
ar[offset_data] = bytes[j] & 0x0f;
ar[offset_data + 1] = (bytes[j] >> 4) & 0x0f;
}
}
void PQCLEAN_LIGHTSABER_CLEAN_pack_6bit(uint8_t *bytes, const uint16_t *data) {
uint32_t j;
uint32_t offset_data, offset_byte;
for (j = 0; j < SABER_N / 4; j++) {
offset_byte = 3 * j;
offset_data = 4 * j;
bytes[offset_byte + 0] = (data[offset_data + 0] & 0x3f) |
((data[offset_data + 1] & 0x03) << 6);
bytes[offset_byte + 1] = ((data[offset_data + 1] >> 2) & 0x0f) |
((data[offset_data + 2] & 0x0f) << 4);
bytes[offset_byte + 2] = ((data[offset_data + 2] >> 4) & 0x03) |
((data[offset_data + 3] & 0x3f) << 2);
}
}
void PQCLEAN_LIGHTSABER_CLEAN_un_pack6bit(const unsigned char *bytes, uint16_t *data) {
uint32_t j;
uint32_t offset_data, offset_byte;
for (j = 0; j < SABER_N / 4; j++) {
offset_byte = 3 * j;
offset_data = 4 * j;
data[offset_data + 0] = bytes[offset_byte + 0] & 0x3f;
data[offset_data + 1] = ((bytes[offset_byte + 0] >> 6) & 0x03) |
((bytes[offset_byte + 1] & 0x0f) << 2);
data[offset_data + 2] = ((bytes[offset_byte + 1] & 0xff) >> 4) |
((bytes[offset_byte + 2] & 0x03) << 4);
data[offset_data + 3] = ((bytes[offset_byte + 2] & 0xff) >> 2);
}
}
static void POLVECp2BS(uint8_t *bytes, uint16_t data[SABER_K][SABER_N]) {
uint32_t i, j;
uint32_t offset_data, offset_byte, offset_byte1;
for (i = 0; i < SABER_K; i++) {
offset_byte1 = i * (SABER_N * 10) / 8;
for (j = 0; j < SABER_N / 4; j++) {
offset_byte = offset_byte1 + 5 * j;
offset_data = 4 * j;
bytes[offset_byte + 0] = (data[i][offset_data + 0] & (0xff));
bytes[offset_byte + 1] = ((data[i][offset_data + 0] >> 8) & 0x03) |
((data[i][offset_data + 1] & 0x3f) << 2);
bytes[offset_byte + 2] = ((data[i][offset_data + 1] >> 6) & 0x0f) |
((data[i][offset_data + 2] & 0x0f) << 4);
bytes[offset_byte + 3] = ((data[i][offset_data + 2] >> 4) & 0x3f) |
((data[i][offset_data + 3] & 0x03) << 6);
bytes[offset_byte + 4] = ((data[i][offset_data + 3] >> 2) & 0xff);
}
}
}
static void BS2POLVECp(const unsigned char *bytes, uint16_t data[SABER_K][SABER_N]) {
uint32_t i, j;
uint32_t offset_data, offset_byte, offset_byte1;
for (i = 0; i < SABER_K; i++) {
offset_byte1 = i * (SABER_N * 10) / 8;
for (j = 0; j < SABER_N / 4; j++) {
offset_byte = offset_byte1 + 5 * j;
offset_data = 4 * j;
data[i][offset_data + 0] = (bytes[offset_byte + 0] & (0xff)) |
((bytes[offset_byte + 1] & 0x03) << 8);
data[i][offset_data + 1] = ((bytes[offset_byte + 1] >> 2) & (0x3f)) |
((bytes[offset_byte + 2] & 0x0f) << 6);
data[i][offset_data + 2] = ((bytes[offset_byte + 2] >> 4) & (0x0f)) |
((bytes[offset_byte + 3] & 0x3f) << 4);
data[i][offset_data + 3] = ((bytes[offset_byte + 3] >> 6) & (0x03)) |
((bytes[offset_byte + 4] & 0xff) << 2);
}
}
}
static void POLVECq2BS(uint8_t *bytes, uint16_t data[SABER_K][SABER_N]) {
uint32_t i, j;
uint32_t offset_data, offset_byte, offset_byte1;
for (i = 0; i < SABER_K; i++) {
offset_byte1 = i * (SABER_N * 13) / 8;
for (j = 0; j < SABER_N / 8; j++) {
offset_byte = offset_byte1 + 13 * j;
offset_data = 8 * j;
bytes[offset_byte + 0] = (data[i][offset_data + 0] & (0xff));
bytes[offset_byte + 1] = ((data[i][offset_data + 0] >> 8) & 0x1f) |
((data[i][offset_data + 1] & 0x07) << 5);
bytes[offset_byte + 2] = ((data[i][offset_data + 1] >> 3) & 0xff);
bytes[offset_byte + 3] = ((data[i][offset_data + 1] >> 11) & 0x03) |
((data[i][offset_data + 2] & 0x3f) << 2);
bytes[offset_byte + 4] = ((data[i][offset_data + 2] >> 6) & 0x7f) |
((data[i][offset_data + 3] & 0x01) << 7);
bytes[offset_byte + 5] = ((data[i][offset_data + 3] >> 1) & 0xff);
bytes[offset_byte + 6] = ((data[i][offset_data + 3] >> 9) & 0x0f) |
((data[i][offset_data + 4] & 0x0f) << 4);
bytes[offset_byte + 7] = ((data[i][offset_data + 4] >> 4) & 0xff);
bytes[offset_byte + 8] = ((data[i][offset_data + 4] >> 12) & 0x01) |
((data[i][offset_data + 5] & 0x7f) << 1);
bytes[offset_byte + 9] = ((data[i][offset_data + 5] >> 7) & 0x3f) |
((data[i][offset_data + 6] & 0x03) << 6);
bytes[offset_byte + 10] = ((data[i][offset_data + 6] >> 2) & 0xff);
bytes[offset_byte + 11] = ((data[i][offset_data + 6] >> 10) & 0x07) |
((data[i][offset_data + 7] & 0x1f) << 3);
bytes[offset_byte + 12] = ((data[i][offset_data + 7] >> 5) & 0xff);
}
}
}
static void BS2POLVECq(const unsigned char *bytes, uint16_t data[SABER_K][SABER_N]) {
uint32_t i, j;
uint32_t offset_data, offset_byte, offset_byte1;
for (i = 0; i < SABER_K; i++) {
offset_byte1 = i * (SABER_N * 13) / 8;
for (j = 0; j < SABER_N / 8; j++) {
offset_byte = offset_byte1 + 13 * j;
offset_data = 8 * j;
data[i][offset_data + 0] = (bytes[offset_byte + 0] & (0xff)) |
((bytes[offset_byte + 1] & 0x1f) << 8);
data[i][offset_data + 1] = (bytes[offset_byte + 1] >> 5 & (0x07)) |
((bytes[offset_byte + 2] & 0xff) << 3) |
((bytes[offset_byte + 3] & 0x03) << 11);
data[i][offset_data + 2] = (bytes[offset_byte + 3] >> 2 & (0x3f)) |
((bytes[offset_byte + 4] & 0x7f) << 6);
data[i][offset_data + 3] = (bytes[offset_byte + 4] >> 7 & (0x01)) |
((bytes[offset_byte + 5] & 0xff) << 1) |
((bytes[offset_byte + 6] & 0x0f) << 9);
data[i][offset_data + 4] = (bytes[offset_byte + 6] >> 4 & (0x0f)) |
((bytes[offset_byte + 7] & 0xff) << 4) |
((bytes[offset_byte + 8] & 0x01) << 12);
data[i][offset_data + 5] = (bytes[offset_byte + 8] >> 1 & (0x7f)) |
((bytes[offset_byte + 9] & 0x3f) << 7);
data[i][offset_data + 6] = (bytes[offset_byte + 9] >> 6 & (0x03)) |
((bytes[offset_byte + 10] & 0xff) << 2) |
((bytes[offset_byte + 11] & 0x07) << 10);
data[i][offset_data + 7] = (bytes[offset_byte + 11] >> 3 & (0x1f)) |
((bytes[offset_byte + 12] & 0xff) << 5);
}
}
}
//only BS2POLq no BS2POLp
void PQCLEAN_LIGHTSABER_CLEAN_BS2POL(const unsigned char *bytes, uint16_t data[SABER_N]) {
uint32_t j;
uint32_t offset_data, offset_byte;
for (j = 0; j < SABER_N / 8; j++) {
offset_byte = 13 * j;
offset_data = 8 * j;
data[offset_data + 0] = (bytes[offset_byte + 0] & (0xff)) |
((bytes[offset_byte + 1] & 0x1f) << 8);
data[offset_data + 1] = (bytes[offset_byte + 1] >> 5 & (0x07)) |
((bytes[offset_byte + 2] & 0xff) << 3) |
((bytes[offset_byte + 3] & 0x03) << 11);
data[offset_data + 2] = (bytes[offset_byte + 3] >> 2 & (0x3f)) |
((bytes[offset_byte + 4] & 0x7f) << 6);
data[offset_data + 3] = (bytes[offset_byte + 4] >> 7 & (0x01)) |
((bytes[offset_byte + 5] & 0xff) << 1) |
((bytes[offset_byte + 6] & 0x0f) << 9);
data[offset_data + 4] = (bytes[offset_byte + 6] >> 4 & (0x0f)) |
((bytes[offset_byte + 7] & 0xff) << 4) |
((bytes[offset_byte + 8] & 0x01) << 12);
data[offset_data + 5] = (bytes[offset_byte + 8] >> 1 & (0x7f)) |
((bytes[offset_byte + 9] & 0x3f) << 7);
data[offset_data + 6] = (bytes[offset_byte + 9] >> 6 & (0x03)) |
((bytes[offset_byte + 10] & 0xff) << 2) |
((bytes[offset_byte + 11] & 0x07) << 10);
data[offset_data + 7] = (bytes[offset_byte + 11] >> 3 & (0x1f)) |
((bytes[offset_byte + 12] & 0xff) << 5);
}
}
void PQCLEAN_LIGHTSABER_CLEAN_POLVEC2BS(uint8_t *bytes, uint16_t data[SABER_K][SABER_N], uint16_t modulus) {
if (modulus == 1024) {
POLVECp2BS(bytes, data);
} else if (modulus == 8192) {
POLVECq2BS(bytes, data);
}
}
void PQCLEAN_LIGHTSABER_CLEAN_BS2POLVEC(const unsigned char *bytes, uint16_t data[SABER_K][SABER_N], uint16_t modulus) {
if (modulus == 1024) {
BS2POLVECp(bytes, data);
} else if (modulus == 8192) {
BS2POLVECq(bytes, data);
}
}

View File

@ -0,0 +1,28 @@
#ifndef PACK_UNPACK_H
#define PACK_UNPACK_H
#include "SABER_params.h"
#include <stdint.h>
#include <stdio.h>
void PQCLEAN_LIGHTSABER_CLEAN_pack_3bit(uint8_t *bytes, const uint16_t *data);
void PQCLEAN_LIGHTSABER_CLEAN_un_pack3bit(const uint8_t *bytes, uint16_t *data);
void PQCLEAN_LIGHTSABER_CLEAN_pack_4bit(uint8_t *bytes, const uint16_t *data);
void PQCLEAN_LIGHTSABER_CLEAN_un_pack4bit(const unsigned char *bytes, uint16_t *ar);
void PQCLEAN_LIGHTSABER_CLEAN_pack_6bit(uint8_t *bytes, const uint16_t *data);
void PQCLEAN_LIGHTSABER_CLEAN_un_pack6bit(const unsigned char *bytes, uint16_t *data);
void PQCLEAN_LIGHTSABER_CLEAN_BS2POL(const unsigned char *bytes, uint16_t data[SABER_N]);
void PQCLEAN_LIGHTSABER_CLEAN_POLVEC2BS(uint8_t *bytes, uint16_t data[SABER_K][SABER_N], uint16_t modulus);
void PQCLEAN_LIGHTSABER_CLEAN_BS2POLVEC(const unsigned char *bytes, uint16_t data[SABER_K][SABER_N], uint16_t modulus);
#endif

View File

@ -0,0 +1,21 @@
/*---------------------------------------------------------------------
This file has been adapted from the implementation
(available at, Public Domain https://github.com/pq-crystals/kyber)
of "CRYSTALS Kyber: a CCA-secure module-lattice-based KEM"
by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint,
Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle
----------------------------------------------------------------------*/
#include "SABER_params.h"
#include "cbd.h"
#include "fips202.h"
#include "poly.h"
void PQCLEAN_LIGHTSABER_CLEAN_GenSecret(uint16_t r[SABER_K][SABER_N], const unsigned char *seed) {
uint8_t buf[SABER_MU * SABER_N * SABER_K / 8];
shake128(buf, sizeof(buf), seed, SABER_NOISESEEDBYTES);
for (size_t i = 0; i < SABER_K; i++) {
PQCLEAN_LIGHTSABER_CLEAN_cbd(r[i], buf + i * SABER_MU * SABER_N / 8);
}
}

View File

@ -0,0 +1,26 @@
#ifndef POLY_H
#define POLY_H
/*---------------------------------------------------------------------
This file has been adapted from the implementation
(available at, Public Domain https://github.com/pq-crystals/kyber)
of "CRYSTALS Kyber: a CCA-secure module-lattice-based KEM"
by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint,
Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle
----------------------------------------------------------------------*/
#include "SABER_params.h"
#include <stdint.h>
typedef struct {
uint16_t coeffs[SABER_N];
} poly;
typedef struct {
poly vec[SABER_K];
} polyvec;
void PQCLEAN_LIGHTSABER_CLEAN_GenSecret(uint16_t r[SABER_K][SABER_N], const unsigned char *seed);
#endif

View File

@ -0,0 +1,237 @@
#include "poly_mul.h"
#include <stdint.h>
#include <string.h>
#define SCHB_N 16
#define N_RES (SABER_N << 1)
#define N_SB (SABER_N >> 2)
#define N_SB_RES (2*N_SB-1)
#define KARATSUBA_N 64
static void karatsuba_simple(const uint16_t *a_1, const uint16_t *b_1, uint16_t *result_final) {
uint16_t d01[KARATSUBA_N / 2 - 1];
uint16_t d0123[KARATSUBA_N / 2 - 1];
uint16_t d23[KARATSUBA_N / 2 - 1];
uint16_t result_d01[KARATSUBA_N - 1];
int32_t i, j;
memset(result_d01, 0, (KARATSUBA_N - 1)*sizeof(uint16_t));
memset(d01, 0, (KARATSUBA_N / 2 - 1)*sizeof(uint16_t));
memset(d0123, 0, (KARATSUBA_N / 2 - 1)*sizeof(uint16_t));
memset(d23, 0, (KARATSUBA_N / 2 - 1)*sizeof(uint16_t));
memset(result_final, 0, (2 * KARATSUBA_N - 1)*sizeof(uint16_t));
uint16_t acc1, acc2, acc3, acc4, acc5, acc6, acc7, acc8, acc9, acc10;
for (i = 0; i < KARATSUBA_N / 4; i++) {
acc1 = a_1[i]; //a0
acc2 = a_1[i + KARATSUBA_N / 4]; //a1
acc3 = a_1[i + 2 * KARATSUBA_N / 4]; //a2
acc4 = a_1[i + 3 * KARATSUBA_N / 4]; //a3
for (j = 0; j < KARATSUBA_N / 4; j++) {
acc5 = b_1[j]; //b0
acc6 = b_1[j + KARATSUBA_N / 4]; //b1
result_final[i + j + 0 * KARATSUBA_N / 4] = result_final[i + j + 0 * KARATSUBA_N / 4] + acc1 * acc5;
result_final[i + j + 2 * KARATSUBA_N / 4] = result_final[i + j + 2 * KARATSUBA_N / 4] + acc2 * acc6;
acc7 = acc5 + acc6; //b01
acc8 = acc1 + acc2; //a01
d01[i + j] = d01[i + j] + acc7 * acc8;
//--------------------------------------------------------
acc7 = b_1[j + 2 * KARATSUBA_N / 4]; //b2
acc8 = b_1[j + 3 * KARATSUBA_N / 4]; //b3
result_final[i + j + 4 * KARATSUBA_N / 4] = result_final[i + j + 4 * KARATSUBA_N / 4] + acc7 * acc3;
result_final[i + j + 6 * KARATSUBA_N / 4] = result_final[i + j + 6 * KARATSUBA_N / 4] + acc8 * acc4;
acc9 = acc3 + acc4;
acc10 = acc7 + acc8;
d23[i + j] = d23[i + j] + acc9 * acc10;
//--------------------------------------------------------
acc5 = acc5 + acc7; //b02
acc7 = acc1 + acc3; //a02
result_d01[i + j + 0 * KARATSUBA_N / 4] = result_d01[i + j + 0 * KARATSUBA_N / 4] + acc5 * acc7;
acc6 = acc6 + acc8; //b13
acc8 = acc2 + acc4;
result_d01[i + j + 2 * KARATSUBA_N / 4] = result_d01[i + j + 2 * KARATSUBA_N / 4] + acc6 * acc8;
acc5 = acc5 + acc6;
acc7 = acc7 + acc8;
d0123[i + j] = d0123[i + j] + acc5 * acc7;
}
}
// 2nd last stage
for (i = 0; i < KARATSUBA_N / 2 - 1; i++) {
d0123[i] = d0123[i] - result_d01[i + 0 * KARATSUBA_N / 4] - result_d01[i + 2 * KARATSUBA_N / 4];
d01[i] = d01[i] - result_final[i + 0 * KARATSUBA_N / 4] - result_final[i + 2 * KARATSUBA_N / 4];
d23[i] = d23[i] - result_final[i + 4 * KARATSUBA_N / 4] - result_final[i + 6 * KARATSUBA_N / 4];
}
for (i = 0; i < KARATSUBA_N / 2 - 1; i++) {
result_d01[i + 1 * KARATSUBA_N / 4] = result_d01[i + 1 * KARATSUBA_N / 4] + d0123[i];
result_final[i + 1 * KARATSUBA_N / 4] = result_final[i + 1 * KARATSUBA_N / 4] + d01[i];
result_final[i + 5 * KARATSUBA_N / 4] = result_final[i + 5 * KARATSUBA_N / 4] + d23[i];
}
// Last stage
for (i = 0; i < KARATSUBA_N - 1; i++) {
result_d01[i] = result_d01[i] - result_final[i] - result_final[i + KARATSUBA_N];
}
for (i = 0; i < KARATSUBA_N - 1; i++) {
result_final[i + 1 * KARATSUBA_N / 2] = result_final[i + 1 * KARATSUBA_N / 2] + result_d01[i];
}
}
static void toom_cook_4way (const uint16_t *a1, const uint16_t *b1, uint16_t *result) {
uint16_t inv3 = 43691, inv9 = 36409, inv15 = 61167;
uint16_t aw1[N_SB], aw2[N_SB], aw3[N_SB], aw4[N_SB], aw5[N_SB], aw6[N_SB], aw7[N_SB];
uint16_t bw1[N_SB], bw2[N_SB], bw3[N_SB], bw4[N_SB], bw5[N_SB], bw6[N_SB], bw7[N_SB];
uint16_t w1[N_SB_RES] = {0}, w2[N_SB_RES] = {0}, w3[N_SB_RES] = {0}, w4[N_SB_RES] = {0},
w5[N_SB_RES] = {0}, w6[N_SB_RES] = {0}, w7[N_SB_RES] = {0};
uint16_t r0, r1, r2, r3, r4, r5, r6, r7;
uint16_t *A0, *A1, *A2, *A3, *B0, *B1, *B2, *B3;
A0 = (uint16_t *)a1;
A1 = (uint16_t *)&a1[N_SB];
A2 = (uint16_t *)&a1[2 * N_SB];
A3 = (uint16_t *)&a1[3 * N_SB];
B0 = (uint16_t *)b1;
B1 = (uint16_t *)&b1[N_SB];
B2 = (uint16_t *)&b1[2 * N_SB];
B3 = (uint16_t *)&b1[3 * N_SB];
uint16_t *C;
C = result;
int i, j;
// EVALUATION
for (j = 0; j < N_SB; ++j) {
r0 = A0[j];
r1 = A1[j];
r2 = A2[j];
r3 = A3[j];
r4 = r0 + r2;
r5 = r1 + r3;
r6 = r4 + r5;
r7 = r4 - r5;
aw3[j] = r6;
aw4[j] = r7;
r4 = ((r0 << 2) + r2) << 1;
r5 = (r1 << 2) + r3;
r6 = r4 + r5;
r7 = r4 - r5;
aw5[j] = r6;
aw6[j] = r7;
r4 = (r3 << 3) + (r2 << 2) + (r1 << 1) + r0;
aw2[j] = r4;
aw7[j] = r0;
aw1[j] = r3;
}
for (j = 0; j < N_SB; ++j) {
r0 = B0[j];
r1 = B1[j];
r2 = B2[j];
r3 = B3[j];
r4 = r0 + r2;
r5 = r1 + r3;
r6 = r4 + r5;
r7 = r4 - r5;
bw3[j] = r6;
bw4[j] = r7;
r4 = ((r0 << 2) + r2) << 1;
r5 = (r1 << 2) + r3;
r6 = r4 + r5;
r7 = r4 - r5;
bw5[j] = r6;
bw6[j] = r7;
r4 = (r3 << 3) + (r2 << 2) + (r1 << 1) + r0;
bw2[j] = r4;
bw7[j] = r0;
bw1[j] = r3;
}
// MULTIPLICATION
karatsuba_simple(aw1, bw1, w1);
karatsuba_simple(aw2, bw2, w2);
karatsuba_simple(aw3, bw3, w3);
karatsuba_simple(aw4, bw4, w4);
karatsuba_simple(aw5, bw5, w5);
karatsuba_simple(aw6, bw6, w6);
karatsuba_simple(aw7, bw7, w7);
// INTERPOLATION
for (i = 0; i < N_SB_RES; ++i) {
r0 = w1[i];
r1 = w2[i];
r2 = w3[i];
r3 = w4[i];
r4 = w5[i];
r5 = w6[i];
r6 = w7[i];
r1 = r1 + r4;
r5 = r5 - r4;
r3 = ((r3 - r2) >> 1);
r4 = r4 - r0;
r4 = r4 - (r6 << 6);
r4 = (r4 << 1) + r5;
r2 = r2 + r3;
r1 = r1 - (r2 << 6) - r2;
r2 = r2 - r6;
r2 = r2 - r0;
r1 = r1 + 45 * r2;
r4 = (((r4 - (r2 << 3)) * inv3) >> 3);
r5 = r5 + r1;
r1 = (((r1 + (r3 << 4)) * inv9) >> 1);
r3 = -(r3 + r1);
r5 = (((30 * r1 - r5) * inv15) >> 2);
r2 = r2 - r4;
r1 = r1 - r5;
C[i] += r6;
C[i + 64] += r5;
C[i + 128] += r4;
C[i + 192] += r3;
C[i + 256] += r2;
C[i + 320] += r1;
C[i + 384] += r0;
}
}
void PQCLEAN_LIGHTSABER_CLEAN_pol_mul(uint16_t *a, uint16_t *b, uint16_t *res, uint16_t p, uint32_t n)
{
uint32_t i;
// normal multiplication
uint16_t c[512];
for (i = 0; i < 512; i++) {
c[i] = 0;
}
toom_cook_4way(a, b, c);
// reduction
for (i = n; i < 2 * n; i++) {
res[i - n] = (c[i - n] - c[i]) & (p - 1);
}
}

View File

@ -0,0 +1,9 @@
#ifndef POLYMUL_H
#define POLYMUL_H
#include "SABER_params.h"
#include <stdint.h>
void PQCLEAN_LIGHTSABER_CLEAN_pol_mul(uint16_t *a, uint16_t *b, uint16_t *res, uint16_t p, uint32_t n);
#endif

View File

@ -0,0 +1,34 @@
/*-------------------------------------------------
This file has been adapted from the implementation
(available at https://github.com/pq-crystals/kyber) of
"CRYSTALS Kyber: a CCA-secure module-lattice-based KEM"
by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint,
Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle
----------------------------------------------------*/
#include "verify.h"
#include <stdint.h>
/* returns 0 for equal strings, 1 for non-equal strings */
unsigned char PQCLEAN_LIGHTSABER_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len) {
uint64_t r;
size_t i;
r = 0;
for (i = 0; i < len; i++) {
r |= a[i] ^ b[i];
}
r = (~r + 1); // Two's complement
r >>= 63;
return (unsigned char)r;
}
/* b = 1 means mov, b = 0 means don't mov*/
void PQCLEAN_LIGHTSABER_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b) {
size_t i;
b = -b;
for (i = 0; i < len; i++) {
r[i] ^= b & (x[i] ^ r[i]);
}
}

View File

@ -0,0 +1,21 @@
#ifndef VERIFY_H
#define VERIFY_H
/*-------------------------------------------------
This file has been adapted from the implementation
(available at https://github.com/pq-crystals/kyber) of
"CRYSTALS Kyber: a CCA-secure module-lattice-based KEM"
by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint,
Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle
----------------------------------------------------*/
#include <stddef.h>
#include <stdint.h>
/* returns 0 for equal strings, 1 for non-equal strings */
unsigned char PQCLEAN_LIGHTSABER_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len);
/* b = 1 means mov, b = 0 means don't mov*/
void PQCLEAN_LIGHTSABER_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b);
#endif

View File

@ -0,0 +1,8 @@
----------------------------------------------------------------------------------------
SABER_v1.1
Public domain
Authors: Jan-Pieter D'Anvers, Angshuman Karmakar, Sujoy Sinha Roy,
Frederik Vercauteren
----------------------------------------------------------------------------------------

View File

@ -0,0 +1,298 @@
#include "SABER_indcpa.h"
#include "SABER_params.h"
#include "fips202.h"
#include "pack_unpack.h"
#include "poly.h"
#include "poly_mul.h"
#include "randombytes.h"
#include <stdint.h>
#include <string.h>
/*-----------------------------------------------------------------------------------
This routine generates a=[Matrix K x K] of 256-coefficient polynomials
-------------------------------------------------------------------------------------*/
#define h1 4 //2^(EQ-EP-1)
#define h2 ( (1<<(SABER_EP-2)) - (1<<(SABER_EP-SABER_ET-1)) + (1<<(SABER_EQ-SABER_EP-1)) )
static void InnerProd(uint16_t pkcl[SABER_K][SABER_N], uint16_t skpv[SABER_K][SABER_N], uint16_t mod, uint16_t res[SABER_N]);
static void MatrixVectorMul(polyvec *a, uint16_t skpv[SABER_K][SABER_N], uint16_t res[SABER_K][SABER_N], uint16_t mod, int16_t transpose);
static void POL2MSG(const uint16_t *message_dec_unpacked, unsigned char *message_dec);
static void GenMatrix(polyvec *a, const unsigned char *seed) {
unsigned char buf[SABER_K * SABER_K * (13 * SABER_N / 8)];
uint16_t temp_ar[SABER_N];
int i, j, k;
uint16_t mod = (SABER_Q - 1);
shake128(buf, sizeof(buf), seed, SABER_SEEDBYTES);
for (i = 0; i < SABER_K; i++) {
for (j = 0; j < SABER_K; j++) {
PQCLEAN_SABER_CLEAN_BS2POL(buf + (i * SABER_K + j) * (13 * SABER_N / 8), temp_ar);
for (k = 0; k < SABER_N; k++) {
a[i].vec[j].coeffs[k] = (temp_ar[k])& mod ;
}
}
}
}
void PQCLEAN_SABER_CLEAN_indcpa_kem_keypair(unsigned char *pk, unsigned char *sk) {
polyvec a[SABER_K];
uint16_t skpv[SABER_K][SABER_N];
unsigned char seed[SABER_SEEDBYTES];
unsigned char noiseseed[SABER_COINBYTES];
int32_t i, j;
uint16_t mod_q = SABER_Q - 1;
uint16_t res[SABER_K][SABER_N];
randombytes(seed, SABER_SEEDBYTES);
// for not revealing system RNG state
shake128(seed, SABER_SEEDBYTES, seed, SABER_SEEDBYTES);
randombytes(noiseseed, SABER_COINBYTES);
GenMatrix(a, seed); //sample matrix A
// generate secret from constant-time binomial distribution
PQCLEAN_SABER_CLEAN_GenSecret(skpv, noiseseed);
// do the matrix vector multiplication and rounding
for (i = 0; i < SABER_K; i++) {
for (j = 0; j < SABER_N; j++) {
res[i][j] = 0;
}
}
MatrixVectorMul(a, skpv, res, SABER_Q - 1, 1);
// now rounding
for (i = 0; i < SABER_K; i++) {
for (j = 0; j < SABER_N; j++) {
// shift right 3 bits
res[i][j] = (res[i][j] + h1) & (mod_q);
res[i][j] = (res[i][j] >> (SABER_EQ - SABER_EP));
}
}
// unload and pack sk=3 x (256 coefficients of 14 bits)
PQCLEAN_SABER_CLEAN_POLVEC2BS(sk, skpv, SABER_Q);
// unload and pack pk=256 bits seed and 3 x (256 coefficients of 11 bits)
// load the public-key coefficients
PQCLEAN_SABER_CLEAN_POLVEC2BS(pk, res, SABER_P);
// now load the seedbytes in PK. Easy since seed bytes are kept in byte format.
for (i = 0; i < SABER_SEEDBYTES; i++) {
pk[SABER_POLYVECCOMPRESSEDBYTES + i] = seed[i];
}
}
void PQCLEAN_SABER_CLEAN_indcpa_kem_enc(const unsigned char *message_received, unsigned char *noiseseed, const unsigned char *pk, unsigned char *ciphertext) {
uint32_t i, j, k;
polyvec a[SABER_K];
unsigned char seed[SABER_SEEDBYTES];
// public key of received by the client
uint16_t pkcl[SABER_K][SABER_N];
uint16_t skpv1[SABER_K][SABER_N];
uint16_t message[SABER_KEYBYTES * 8];
uint16_t res[SABER_K][SABER_N];
uint16_t mod_p = SABER_P - 1;
uint16_t mod_q = SABER_Q - 1;
uint16_t vprime[SABER_N];
unsigned char msk_c[SABER_SCALEBYTES_KEM];
// extract the seedbytes from Public Key.
for (i = 0; i < SABER_SEEDBYTES; i++) {
seed[i] = pk[ SABER_POLYVECCOMPRESSEDBYTES + i];
}
GenMatrix(a, seed);
// generate secret from constant-time binomial distribution
PQCLEAN_SABER_CLEAN_GenSecret(skpv1, noiseseed);
// matrix-vector multiplication and rounding
for (i = 0; i < SABER_K; i++) {
for (j = 0; j < SABER_N; j++) {
res[i][j] = 0;
}
}
MatrixVectorMul(a, skpv1, res, SABER_Q - 1, 0);
// now rounding
//shift right 3 bits
for (i = 0; i < SABER_K; i++) {
for (j = 0; j < SABER_N; j++) {
res[i][j] = ( res[i][j] + h1 ) & mod_q;
res[i][j] = (res[i][j] >> (SABER_EQ - SABER_EP) );
}
}
PQCLEAN_SABER_CLEAN_POLVEC2BS(ciphertext, res, SABER_P);
// ************client matrix-vector multiplication ends************
// now calculate the v'
// unpack the public_key
// pkcl is the b in the protocol
PQCLEAN_SABER_CLEAN_BS2POLVEC(pk, pkcl, SABER_P);
for (i = 0; i < SABER_N; i++) {
vprime[i] = 0;
}
for (i = 0; i < SABER_K; i++) {
for (j = 0; j < SABER_N; j++) {
skpv1[i][j] = skpv1[i][j] & (mod_p);
}
}
// vector-vector scalar multiplication with mod p
InnerProd(pkcl, skpv1, mod_p, vprime);
// addition of h1 to vprime
for (i = 0; i < SABER_N; i++) {
vprime[i] = vprime[i] + h1;
}
// unpack message_received;
for (j = 0; j < SABER_KEYBYTES; j++) {
for (i = 0; i < 8; i++) {
message[8 * j + i] = ((message_received[j] >> i) & 0x01);
}
}
// message encoding
for (i = 0; i < SABER_N; i++) {
message[i] = (message[i] << (SABER_EP - 1));
}
for (k = 0; k < SABER_N; k++) {
vprime[k] = ( (vprime[k] - message[k]) & (mod_p) ) >> (SABER_EP - SABER_ET);
}
PQCLEAN_SABER_CLEAN_pack_4bit(msk_c, vprime);
for (j = 0; j < SABER_SCALEBYTES_KEM; j++) {
ciphertext[SABER_POLYVECCOMPRESSEDBYTES + j] = msk_c[j];
}
}
void PQCLEAN_SABER_CLEAN_indcpa_kem_dec(const unsigned char *sk, const unsigned char *ciphertext, unsigned char message_dec[]) {
uint32_t i, j;
// secret key of the server
uint16_t sksv[SABER_K][SABER_N];
uint16_t pksv[SABER_K][SABER_N];
uint8_t scale_ar[SABER_SCALEBYTES_KEM];
uint16_t mod_p = SABER_P - 1;
uint16_t v[SABER_N];
uint16_t op[SABER_N];
// sksv is the secret-key
PQCLEAN_SABER_CLEAN_BS2POLVEC(sk, sksv, SABER_Q);
// pksv is the ciphertext
PQCLEAN_SABER_CLEAN_BS2POLVEC(ciphertext, pksv, SABER_P);
// vector-vector scalar multiplication with mod p
for (i = 0; i < SABER_N; i++) {
v[i] = 0;
}
for (i = 0; i < SABER_K; i++) {
for (j = 0; j < SABER_N; j++) {
sksv[i][j] = sksv[i][j] & (mod_p);
}
}
InnerProd(pksv, sksv, mod_p, v);
//Extraction
for (i = 0; i < SABER_SCALEBYTES_KEM; i++) {
scale_ar[i] = ciphertext[SABER_POLYVECCOMPRESSEDBYTES + i];
}
PQCLEAN_SABER_CLEAN_un_pack4bit(scale_ar, op);
//addition of h1
for (i = 0; i < SABER_N; i++) {
v[i] = ( ( v[i] + h2 - (op[i] << (SABER_EP - SABER_ET)) ) & (mod_p) ) >> (SABER_EP - 1);
}
// pack decrypted message
POL2MSG(v, message_dec);
}
static void MatrixVectorMul(polyvec *a, uint16_t skpv[SABER_K][SABER_N], uint16_t res[SABER_K][SABER_N], uint16_t mod, int16_t transpose) {
uint16_t acc[SABER_N];
int32_t i, j, k;
if (transpose == 1) {
for (i = 0; i < SABER_K; i++) {
for (j = 0; j < SABER_K; j++) {
PQCLEAN_SABER_CLEAN_pol_mul((uint16_t *)&a[j].vec[i], skpv[j], acc, SABER_Q, SABER_N);
for (k = 0; k < SABER_N; k++) {
res[i][k] = res[i][k] + acc[k];
//reduction mod p
res[i][k] = (res[i][k] & mod);
//clear the accumulator
acc[k] = 0;
}
}
}
} else {
for (i = 0; i < SABER_K; i++) {
for (j = 0; j < SABER_K; j++) {
PQCLEAN_SABER_CLEAN_pol_mul((uint16_t *)&a[i].vec[j], skpv[j], acc, SABER_Q, SABER_N);
for (k = 0; k < SABER_N; k++) {
res[i][k] = res[i][k] + acc[k];
// reduction
res[i][k] = res[i][k] & mod;
// clear the accumulator
acc[k] = 0;
}
}
}
}
}
static void POL2MSG(const uint16_t *message_dec_unpacked, unsigned char *message_dec) {
int32_t i, j;
for (j = 0; j < SABER_KEYBYTES; j++) {
message_dec[j] = 0;
for (i = 0; i < 8; i++) {
message_dec[j] = message_dec[j] | (uint8_t) (message_dec_unpacked[j * 8 + i] << i);
}
}
}
static void InnerProd(uint16_t pkcl[SABER_K][SABER_N], uint16_t skpv[SABER_K][SABER_N], uint16_t mod, uint16_t res[SABER_N]) {
uint32_t j, k;
uint16_t acc[SABER_N];
// vector-vector scalar multiplication with mod p
for (j = 0; j < SABER_K; j++) {
PQCLEAN_SABER_CLEAN_pol_mul(pkcl[j], skpv[j], acc, SABER_P, SABER_N);
for (k = 0; k < SABER_N; k++) {
res[k] = res[k] + acc[k];
// reduction
res[k] = res[k] & mod;
// clear the accumulator
acc[k] = 0;
}
}
}

View File

@ -0,0 +1,9 @@
#ifndef INDCPA_H
#define INDCPA_H
void PQCLEAN_SABER_CLEAN_indcpa_kem_keypair(unsigned char *pk, unsigned char *sk);
void PQCLEAN_SABER_CLEAN_indcpa_kem_enc(const unsigned char *message, unsigned char *noiseseed, const unsigned char *pk, unsigned char *ciphertext);
void PQCLEAN_SABER_CLEAN_indcpa_kem_dec(const unsigned char *sk, const unsigned char *ciphertext, unsigned char *message_dec);
#endif

View File

@ -0,0 +1,50 @@
#ifndef PARAMS_H
#define PARAMS_H
#include "api.h"
#define SABER_K 3
#define SABER_MU 8
#define SABER_ET 4
#define SABER_EQ 13
#define SABER_EP 10
#define SABER_N 256
#define SABER_Q 8192
#define SABER_P 1024
#define SABER_SEEDBYTES 32
#define SABER_NOISESEEDBYTES 32
#define SABER_COINBYTES 32
#define SABER_KEYBYTES 32
#define SABER_HASHBYTES 32
#define SABER_POLYBYTES 416 //13*256/8
#define SABER_POLYVECBYTES (SABER_K * SABER_POLYBYTES)
#define SABER_POLYVECCOMPRESSEDBYTES (SABER_K * 320) //10*256/8 NOTE : changed till here due to parameter adaptation
#define SABER_CIPHERTEXTBYTES (SABER_POLYVECCOMPRESSEDBYTES)
#define SABER_SCALEBYTES (SABER_DELTA*SABER_N/8)
#define SABER_SCALEBYTES_KEM ((SABER_ET)*SABER_N/8)
#define SABER_INDCPA_PUBLICKEYBYTES (SABER_POLYVECCOMPRESSEDBYTES + SABER_SEEDBYTES)
#define SABER_INDCPA_SECRETKEYBYTES (SABER_POLYVECBYTES)
#define SABER_PUBLICKEYBYTES (SABER_INDCPA_PUBLICKEYBYTES)
#define SABER_SECRETKEYBYTES (SABER_INDCPA_SECRETKEYBYTES + SABER_INDCPA_PUBLICKEYBYTES + SABER_HASHBYTES + SABER_KEYBYTES)
#define SABER_BYTES_CCA_DEC (SABER_POLYVECCOMPRESSEDBYTES + SABER_SCALEBYTES_KEM) /* Second part is for Targhi-Unruh */
#endif

View File

@ -0,0 +1,14 @@
#ifndef PQCLEAN_SABER_CLEAN_API_H
#define PQCLEAN_SABER_CLEAN_API_H
#define PQCLEAN_SABER_CLEAN_CRYPTO_ALGNAME "Saber"
#define PQCLEAN_SABER_CLEAN_CRYPTO_SECRETKEYBYTES 2304
#define PQCLEAN_SABER_CLEAN_CRYPTO_PUBLICKEYBYTES (3*320+32)
#define PQCLEAN_SABER_CLEAN_CRYPTO_BYTES 32
#define PQCLEAN_SABER_CLEAN_CRYPTO_CIPHERTEXTBYTES 1088
int PQCLEAN_SABER_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk);
int PQCLEAN_SABER_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk);
int PQCLEAN_SABER_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk);
#endif /* api_h */

View File

@ -0,0 +1,51 @@
/*---------------------------------------------------------------------
This file has been adapted from the implementation
(available at, Public Domain https://github.com/pq-crystals/kyber)
of "CRYSTALS Kyber: a CCA-secure module-lattice-based KEM"
by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint,
Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle
----------------------------------------------------------------------*/
#include "SABER_params.h"
#include "api.h"
#include "cbd.h"
#include <stdint.h>
static uint64_t load_littleendian(const unsigned char *x, int bytes) {
int i;
uint64_t r = x[0];
for (i = 1; i < bytes; i++) {
r |= (uint64_t)x[i] << (8 * i);
}
return r;
}
void PQCLEAN_SABER_CLEAN_cbd(uint16_t *r, const unsigned char *buf) {
uint16_t Qmod_minus1 = SABER_Q - 1;
uint32_t t, d, a[4], b[4];
int i, j;
for (i = 0; i < SABER_N / 4; i++) {
t = (uint32_t) load_littleendian(buf + 4 * i, 4);
d = 0;
for (j = 0; j < 4; j++) {
d += (t >> j) & 0x11111111;
}
a[0] = d & 0xf;
b[0] = (d >> 4) & 0xf;
a[1] = (d >> 8) & 0xf;
b[1] = (d >> 12) & 0xf;
a[2] = (d >> 16) & 0xf;
b[2] = (d >> 20) & 0xf;
a[3] = (d >> 24) & 0xf;
b[3] = (d >> 28);
r[4 * i + 0] = (uint16_t)(a[0] - b[0]) & Qmod_minus1;
r[4 * i + 1] = (uint16_t)(a[1] - b[1]) & Qmod_minus1;
r[4 * i + 2] = (uint16_t)(a[2] - b[2]) & Qmod_minus1;
r[4 * i + 3] = (uint16_t)(a[3] - b[3]) & Qmod_minus1;
}
}

View File

@ -0,0 +1,17 @@
#ifndef CBD_H
#define CBD_H
/*---------------------------------------------------------------------
This file has been adapted from the implementation
(available at, Public Domain https://github.com/pq-crystals/kyber)
of "CRYSTALS Kyber: a CCA-secure module-lattice-based KEM"
by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint,
Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle
----------------------------------------------------------------------*/
#include "poly.h"
#include <stdint.h>
void PQCLEAN_SABER_CLEAN_cbd(uint16_t *r, const unsigned char *buf);
#endif

View File

@ -0,0 +1,96 @@
#include "SABER_indcpa.h"
#include "SABER_params.h"
#include "fips202.h"
#include "randombytes.h"
#include "verify.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
int PQCLEAN_SABER_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk) {
int i;
// sk[0:SABER_INDCPA_SECRETKEYBYTES-1] <-- sk
PQCLEAN_SABER_CLEAN_indcpa_kem_keypair(pk, sk);
// sk[SABER_INDCPA_SECRETKEYBYTES:SABER_INDCPA_SECRETKEYBYTES+SABER_INDCPA_SECRETKEYBYTES-1] <-- pk
for (i = 0; i < SABER_INDCPA_PUBLICKEYBYTES; i++) {
sk[i + SABER_INDCPA_SECRETKEYBYTES] = pk[i];
}
// Then hash(pk) is appended.
sha3_256(sk + SABER_SECRETKEYBYTES - 64, pk, SABER_INDCPA_PUBLICKEYBYTES);
// Remaining part of sk contains a pseudo-random number.
// This is output when check in crypto_kem_dec() fails.
randombytes(sk + SABER_SECRETKEYBYTES - SABER_KEYBYTES, SABER_KEYBYTES );
return (0);
}
int PQCLEAN_SABER_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) {
// Will contain key, coins
unsigned char kr[64];
unsigned char buf[64];
randombytes(buf, 32);
// BUF[0:31] <-- random message (will be used as the key for client) Note: hash doesnot release system RNG output
sha3_256(buf, buf, 32);
// BUF[32:63] <-- Hash(public key); Multitarget countermeasure for coins + contributory KEM
sha3_256(buf + 32, pk, SABER_INDCPA_PUBLICKEYBYTES);
// kr[0:63] <-- Hash(buf[0:63]);
sha3_512(kr, buf, 64);
// K^ <-- kr[0:31]
// noiseseed (r) <-- kr[32:63];
// buf[0:31] contains message; kr[32:63] contains randomness r;
PQCLEAN_SABER_CLEAN_indcpa_kem_enc(buf, kr + 32, pk, ct);
sha3_256(kr + 32, ct, SABER_BYTES_CCA_DEC);
// hash concatenation of pre-k and h(c) to k
sha3_256(ss, kr, 64);
return (0);
}
int PQCLEAN_SABER_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) {
int i;
unsigned char fail;
unsigned char cmp[SABER_BYTES_CCA_DEC];
unsigned char buf[64];
// Will contain key, coins
unsigned char kr[64];
const unsigned char *pk = sk + SABER_INDCPA_SECRETKEYBYTES;
// buf[0:31] <-- message
PQCLEAN_SABER_CLEAN_indcpa_kem_dec(sk, ct, buf);
// Multitarget countermeasure for coins + contributory KEM
// Save hash by storing h(pk) in sk
for (i = 0; i < 32; i++) {
buf[32 + i] = sk[SABER_SECRETKEYBYTES - 64 + i];
}
sha3_512(kr, buf, 64);
PQCLEAN_SABER_CLEAN_indcpa_kem_enc(buf, kr + 32, pk, cmp);
fail = PQCLEAN_SABER_CLEAN_verify(ct, cmp, SABER_BYTES_CCA_DEC);
// overwrite coins in kr with h(c)
sha3_256(kr + 32, ct, SABER_BYTES_CCA_DEC);
PQCLEAN_SABER_CLEAN_cmov(kr, sk + SABER_SECRETKEYBYTES - SABER_KEYBYTES, SABER_KEYBYTES, fail);
// hash concatenation of pre-k and h(c) to k
sha3_256(ss, kr, 64);
return (0);
}

View File

@ -0,0 +1,254 @@
#include "pack_unpack.h"
void PQCLEAN_SABER_CLEAN_pack_3bit(uint8_t *bytes, const uint16_t *data) {
uint32_t j;
uint32_t offset_data, offset_byte;
for (j = 0; j < SABER_N / 8; j++) {
offset_byte = 3 * j;
offset_data = 8 * j;
bytes[offset_byte + 0] = (data[offset_data + 0] & 0x7) |
((data[offset_data + 1] & 0x7) << 3) |
((data[offset_data + 2] & 0x3) << 6);
bytes[offset_byte + 1] = ((data[offset_data + 2] >> 2 ) & 0x01) |
((data[offset_data + 3] & 0x7) << 1) |
((data[offset_data + 4] & 0x7) << 4) |
(((data[offset_data + 5]) & 0x01) << 7);
bytes[offset_byte + 2] = ((data[offset_data + 5] >> 1 ) & 0x03) |
((data[offset_data + 6] & 0x7) << 2) |
((data[offset_data + 7] & 0x7) << 5);
}
}
void PQCLEAN_SABER_CLEAN_un_pack3bit(const uint8_t *bytes, uint16_t *data) {
uint32_t j;
uint32_t offset_data, offset_byte;
for (j = 0; j < SABER_N / 8; j++) {
offset_byte = 3 * j;
offset_data = 8 * j;
data[offset_data + 0] = (bytes[offset_byte + 0]) & 0x07;
data[offset_data + 1] = ((bytes[offset_byte + 0]) >> 3 ) & 0x07;
data[offset_data + 2] = (((bytes[offset_byte + 0]) >> 6 ) & 0x03) |
(((bytes[offset_byte + 1]) & 0x01) << 2);
data[offset_data + 3] = ((bytes[offset_byte + 1]) >> 1 ) & 0x07;
data[offset_data + 4] = ((bytes[offset_byte + 1]) >> 4 ) & 0x07;
data[offset_data + 5] = (((bytes[offset_byte + 1]) >> 7 ) & 0x01) |
(((bytes[offset_byte + 2]) & 0x03) << 1);
data[offset_data + 6] = ((bytes[offset_byte + 2] >> 2) & 0x07);
data[offset_data + 7] = ((bytes[offset_byte + 2] >> 5) & 0x07);
}
}
void PQCLEAN_SABER_CLEAN_pack_4bit(uint8_t *bytes, const uint16_t *data) {
uint32_t j;
uint32_t offset_data;
for (j = 0; j < SABER_N / 2; j++) {
offset_data = 2 * j;
bytes[j] = (data[offset_data] & 0x0f) |
((data[offset_data + 1] & 0x0f) << 4);
}
}
void PQCLEAN_SABER_CLEAN_un_pack4bit(const unsigned char *bytes, uint16_t *ar) {
uint32_t j;
uint32_t offset_data;
for (j = 0; j < SABER_N / 2; j++) {
offset_data = 2 * j;
ar[offset_data] = bytes[j] & 0x0f;
ar[offset_data + 1] = (bytes[j] >> 4) & 0x0f;
}
}
void PQCLEAN_SABER_CLEAN_pack_6bit(uint8_t *bytes, const uint16_t *data) {
uint32_t j;
uint32_t offset_data, offset_byte;
for (j = 0; j < SABER_N / 4; j++) {
offset_byte = 3 * j;
offset_data = 4 * j;
bytes[offset_byte + 0] = (data[offset_data + 0] & 0x3f) |
((data[offset_data + 1] & 0x03) << 6);
bytes[offset_byte + 1] = ((data[offset_data + 1] >> 2) & 0x0f) |
((data[offset_data + 2] & 0x0f) << 4);
bytes[offset_byte + 2] = ((data[offset_data + 2] >> 4) & 0x03) |
((data[offset_data + 3] & 0x3f) << 2);
}
}
void PQCLEAN_SABER_CLEAN_un_pack6bit(const unsigned char *bytes, uint16_t *data) {
uint32_t j;
uint32_t offset_data, offset_byte;
for (j = 0; j < SABER_N / 4; j++) {
offset_byte = 3 * j;
offset_data = 4 * j;
data[offset_data + 0] = bytes[offset_byte + 0] & 0x3f;
data[offset_data + 1] = ((bytes[offset_byte + 0] >> 6) & 0x03) |
((bytes[offset_byte + 1] & 0x0f) << 2);
data[offset_data + 2] = ((bytes[offset_byte + 1] & 0xff) >> 4) |
((bytes[offset_byte + 2] & 0x03) << 4);
data[offset_data + 3] = ((bytes[offset_byte + 2] & 0xff) >> 2);
}
}
static void POLVECp2BS(uint8_t *bytes, uint16_t data[SABER_K][SABER_N]) {
uint32_t i, j;
uint32_t offset_data, offset_byte, offset_byte1;
for (i = 0; i < SABER_K; i++) {
offset_byte1 = i * (SABER_N * 10) / 8;
for (j = 0; j < SABER_N / 4; j++) {
offset_byte = offset_byte1 + 5 * j;
offset_data = 4 * j;
bytes[offset_byte + 0] = (data[i][offset_data + 0] & (0xff));
bytes[offset_byte + 1] = ((data[i][offset_data + 0] >> 8) & 0x03) |
((data[i][offset_data + 1] & 0x3f) << 2);
bytes[offset_byte + 2] = ((data[i][offset_data + 1] >> 6) & 0x0f) |
((data[i][offset_data + 2] & 0x0f) << 4);
bytes[offset_byte + 3] = ((data[i][offset_data + 2] >> 4) & 0x3f) |
((data[i][offset_data + 3] & 0x03) << 6);
bytes[offset_byte + 4] = ((data[i][offset_data + 3] >> 2) & 0xff);
}
}
}
static void BS2POLVECp(const unsigned char *bytes, uint16_t data[SABER_K][SABER_N]) {
uint32_t i, j;
uint32_t offset_data, offset_byte, offset_byte1;
for (i = 0; i < SABER_K; i++) {
offset_byte1 = i * (SABER_N * 10) / 8;
for (j = 0; j < SABER_N / 4; j++) {
offset_byte = offset_byte1 + 5 * j;
offset_data = 4 * j;
data[i][offset_data + 0] = (bytes[offset_byte + 0] & (0xff)) |
((bytes[offset_byte + 1] & 0x03) << 8);
data[i][offset_data + 1] = ((bytes[offset_byte + 1] >> 2) & (0x3f)) |
((bytes[offset_byte + 2] & 0x0f) << 6);
data[i][offset_data + 2] = ((bytes[offset_byte + 2] >> 4) & (0x0f)) |
((bytes[offset_byte + 3] & 0x3f) << 4);
data[i][offset_data + 3] = ((bytes[offset_byte + 3] >> 6) & (0x03)) |
((bytes[offset_byte + 4] & 0xff) << 2);
}
}
}
static void POLVECq2BS(uint8_t *bytes, uint16_t data[SABER_K][SABER_N]) {
uint32_t i, j;
uint32_t offset_data, offset_byte, offset_byte1;
for (i = 0; i < SABER_K; i++) {
offset_byte1 = i * (SABER_N * 13) / 8;
for (j = 0; j < SABER_N / 8; j++) {
offset_byte = offset_byte1 + 13 * j;
offset_data = 8 * j;
bytes[offset_byte + 0] = (data[i][offset_data + 0] & (0xff));
bytes[offset_byte + 1] = ((data[i][offset_data + 0] >> 8) & 0x1f) |
((data[i][offset_data + 1] & 0x07) << 5);
bytes[offset_byte + 2] = ((data[i][offset_data + 1] >> 3) & 0xff);
bytes[offset_byte + 3] = ((data[i][offset_data + 1] >> 11) & 0x03) |
((data[i][offset_data + 2] & 0x3f) << 2);
bytes[offset_byte + 4] = ((data[i][offset_data + 2] >> 6) & 0x7f) |
((data[i][offset_data + 3] & 0x01) << 7);
bytes[offset_byte + 5] = ((data[i][offset_data + 3] >> 1) & 0xff);
bytes[offset_byte + 6] = ((data[i][offset_data + 3] >> 9) & 0x0f) |
((data[i][offset_data + 4] & 0x0f) << 4);
bytes[offset_byte + 7] = ((data[i][offset_data + 4] >> 4) & 0xff);
bytes[offset_byte + 8] = ((data[i][offset_data + 4] >> 12) & 0x01) |
((data[i][offset_data + 5] & 0x7f) << 1);
bytes[offset_byte + 9] = ((data[i][offset_data + 5] >> 7) & 0x3f) |
((data[i][offset_data + 6] & 0x03) << 6);
bytes[offset_byte + 10] = ((data[i][offset_data + 6] >> 2) & 0xff);
bytes[offset_byte + 11] = ((data[i][offset_data + 6] >> 10) & 0x07) |
((data[i][offset_data + 7] & 0x1f) << 3);
bytes[offset_byte + 12] = ((data[i][offset_data + 7] >> 5) & 0xff);
}
}
}
static void BS2POLVECq(const unsigned char *bytes, uint16_t data[SABER_K][SABER_N]) {
uint32_t i, j;
uint32_t offset_data, offset_byte, offset_byte1;
for (i = 0; i < SABER_K; i++) {
offset_byte1 = i * (SABER_N * 13) / 8;
for (j = 0; j < SABER_N / 8; j++) {
offset_byte = offset_byte1 + 13 * j;
offset_data = 8 * j;
data[i][offset_data + 0] = (bytes[offset_byte + 0] & (0xff)) |
((bytes[offset_byte + 1] & 0x1f) << 8);
data[i][offset_data + 1] = (bytes[offset_byte + 1] >> 5 & (0x07)) |
((bytes[offset_byte + 2] & 0xff) << 3) |
((bytes[offset_byte + 3] & 0x03) << 11);
data[i][offset_data + 2] = (bytes[offset_byte + 3] >> 2 & (0x3f)) |
((bytes[offset_byte + 4] & 0x7f) << 6);
data[i][offset_data + 3] = (bytes[offset_byte + 4] >> 7 & (0x01)) |
((bytes[offset_byte + 5] & 0xff) << 1) |
((bytes[offset_byte + 6] & 0x0f) << 9);
data[i][offset_data + 4] = (bytes[offset_byte + 6] >> 4 & (0x0f)) |
((bytes[offset_byte + 7] & 0xff) << 4) |
((bytes[offset_byte + 8] & 0x01) << 12);
data[i][offset_data + 5] = (bytes[offset_byte + 8] >> 1 & (0x7f)) |
((bytes[offset_byte + 9] & 0x3f) << 7);
data[i][offset_data + 6] = (bytes[offset_byte + 9] >> 6 & (0x03)) |
((bytes[offset_byte + 10] & 0xff) << 2) |
((bytes[offset_byte + 11] & 0x07) << 10);
data[i][offset_data + 7] = (bytes[offset_byte + 11] >> 3 & (0x1f)) |
((bytes[offset_byte + 12] & 0xff) << 5);
}
}
}
//only BS2POLq no BS2POLp
void PQCLEAN_SABER_CLEAN_BS2POL(const unsigned char *bytes, uint16_t data[SABER_N]) {
uint32_t j;
uint32_t offset_data, offset_byte;
for (j = 0; j < SABER_N / 8; j++) {
offset_byte = 13 * j;
offset_data = 8 * j;
data[offset_data + 0] = (bytes[offset_byte + 0] & (0xff)) |
((bytes[offset_byte + 1] & 0x1f) << 8);
data[offset_data + 1] = (bytes[offset_byte + 1] >> 5 & (0x07)) |
((bytes[offset_byte + 2] & 0xff) << 3) |
((bytes[offset_byte + 3] & 0x03) << 11);
data[offset_data + 2] = (bytes[offset_byte + 3] >> 2 & (0x3f)) |
((bytes[offset_byte + 4] & 0x7f) << 6);
data[offset_data + 3] = (bytes[offset_byte + 4] >> 7 & (0x01)) |
((bytes[offset_byte + 5] & 0xff) << 1) |
((bytes[offset_byte + 6] & 0x0f) << 9);
data[offset_data + 4] = (bytes[offset_byte + 6] >> 4 & (0x0f)) |
((bytes[offset_byte + 7] & 0xff) << 4) |
((bytes[offset_byte + 8] & 0x01) << 12);
data[offset_data + 5] = (bytes[offset_byte + 8] >> 1 & (0x7f)) |
((bytes[offset_byte + 9] & 0x3f) << 7);
data[offset_data + 6] = (bytes[offset_byte + 9] >> 6 & (0x03)) |
((bytes[offset_byte + 10] & 0xff) << 2) |
((bytes[offset_byte + 11] & 0x07) << 10);
data[offset_data + 7] = (bytes[offset_byte + 11] >> 3 & (0x1f)) |
((bytes[offset_byte + 12] & 0xff) << 5);
}
}
void PQCLEAN_SABER_CLEAN_POLVEC2BS(uint8_t *bytes, uint16_t data[SABER_K][SABER_N], uint16_t modulus) {
if (modulus == 1024) {
POLVECp2BS(bytes, data);
} else if (modulus == 8192) {
POLVECq2BS(bytes, data);
}
}
void PQCLEAN_SABER_CLEAN_BS2POLVEC(const unsigned char *bytes, uint16_t data[SABER_K][SABER_N], uint16_t modulus) {
if (modulus == 1024) {
BS2POLVECp(bytes, data);
} else if (modulus == 8192) {
BS2POLVECq(bytes, data);
}
}

View File

@ -0,0 +1,28 @@
#ifndef PACK_UNPACK_H
#define PACK_UNPACK_H
#include "SABER_params.h"
#include <stdint.h>
#include <stdio.h>
void PQCLEAN_SABER_CLEAN_pack_3bit(uint8_t *bytes, const uint16_t *data);
void PQCLEAN_SABER_CLEAN_un_pack3bit(const uint8_t *bytes, uint16_t *data);
void PQCLEAN_SABER_CLEAN_pack_4bit(uint8_t *bytes, const uint16_t *data);
void PQCLEAN_SABER_CLEAN_un_pack4bit(const unsigned char *bytes, uint16_t *ar);
void PQCLEAN_SABER_CLEAN_pack_6bit(uint8_t *bytes, const uint16_t *data);
void PQCLEAN_SABER_CLEAN_un_pack6bit(const unsigned char *bytes, uint16_t *data);
void PQCLEAN_SABER_CLEAN_BS2POL(const unsigned char *bytes, uint16_t data[SABER_N]);
void PQCLEAN_SABER_CLEAN_POLVEC2BS(uint8_t *bytes, uint16_t data[SABER_K][SABER_N], uint16_t modulus);
void PQCLEAN_SABER_CLEAN_BS2POLVEC(const unsigned char *bytes, uint16_t data[SABER_K][SABER_N], uint16_t modulus);
#endif

View File

@ -0,0 +1,21 @@
/*---------------------------------------------------------------------
This file has been adapted from the implementation
(available at, Public Domain https://github.com/pq-crystals/kyber)
of "CRYSTALS Kyber: a CCA-secure module-lattice-based KEM"
by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint,
Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle
----------------------------------------------------------------------*/
#include "SABER_params.h"
#include "cbd.h"
#include "fips202.h"
#include "poly.h"
void PQCLEAN_SABER_CLEAN_GenSecret(uint16_t r[SABER_K][SABER_N], const unsigned char *seed) {
uint8_t buf[SABER_MU * SABER_N * SABER_K / 8];
shake128(buf, sizeof(buf), seed, SABER_NOISESEEDBYTES);
for (size_t i = 0; i < SABER_K; i++) {
PQCLEAN_SABER_CLEAN_cbd(r[i], buf + i * SABER_MU * SABER_N / 8);
}
}

View File

@ -0,0 +1,26 @@
#ifndef POLY_H
#define POLY_H
/*---------------------------------------------------------------------
This file has been adapted from the implementation
(available at, Public Domain https://github.com/pq-crystals/kyber)
of "CRYSTALS Kyber: a CCA-secure module-lattice-based KEM"
by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint,
Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle
----------------------------------------------------------------------*/
#include "SABER_params.h"
#include <stdint.h>
typedef struct {
uint16_t coeffs[SABER_N];
} poly;
typedef struct {
poly vec[SABER_K];
} polyvec;
void PQCLEAN_SABER_CLEAN_GenSecret(uint16_t r[SABER_K][SABER_N], const unsigned char *seed);
#endif

View File

@ -0,0 +1,237 @@
#include "poly_mul.h"
#include <stdint.h>
#include <string.h>
#define SCHB_N 16
#define N_RES (SABER_N << 1)
#define N_SB (SABER_N >> 2)
#define N_SB_RES (2*N_SB-1)
#define KARATSUBA_N 64
static void karatsuba_simple(const uint16_t *a_1, const uint16_t *b_1, uint16_t *result_final) {
uint16_t d01[KARATSUBA_N / 2 - 1];
uint16_t d0123[KARATSUBA_N / 2 - 1];
uint16_t d23[KARATSUBA_N / 2 - 1];
uint16_t result_d01[KARATSUBA_N - 1];
int32_t i, j;
memset(result_d01, 0, (KARATSUBA_N - 1)*sizeof(uint16_t));
memset(d01, 0, (KARATSUBA_N / 2 - 1)*sizeof(uint16_t));
memset(d0123, 0, (KARATSUBA_N / 2 - 1)*sizeof(uint16_t));
memset(d23, 0, (KARATSUBA_N / 2 - 1)*sizeof(uint16_t));
memset(result_final, 0, (2 * KARATSUBA_N - 1)*sizeof(uint16_t));
uint16_t acc1, acc2, acc3, acc4, acc5, acc6, acc7, acc8, acc9, acc10;
for (i = 0; i < KARATSUBA_N / 4; i++) {
acc1 = a_1[i]; //a0
acc2 = a_1[i + KARATSUBA_N / 4]; //a1
acc3 = a_1[i + 2 * KARATSUBA_N / 4]; //a2
acc4 = a_1[i + 3 * KARATSUBA_N / 4]; //a3
for (j = 0; j < KARATSUBA_N / 4; j++) {
acc5 = b_1[j]; //b0
acc6 = b_1[j + KARATSUBA_N / 4]; //b1
result_final[i + j + 0 * KARATSUBA_N / 4] = result_final[i + j + 0 * KARATSUBA_N / 4] + acc1 * acc5;
result_final[i + j + 2 * KARATSUBA_N / 4] = result_final[i + j + 2 * KARATSUBA_N / 4] + acc2 * acc6;
acc7 = acc5 + acc6; //b01
acc8 = acc1 + acc2; //a01
d01[i + j] = d01[i + j] + acc7 * acc8;
//--------------------------------------------------------
acc7 = b_1[j + 2 * KARATSUBA_N / 4]; //b2
acc8 = b_1[j + 3 * KARATSUBA_N / 4]; //b3
result_final[i + j + 4 * KARATSUBA_N / 4] = result_final[i + j + 4 * KARATSUBA_N / 4] + acc7 * acc3;
result_final[i + j + 6 * KARATSUBA_N / 4] = result_final[i + j + 6 * KARATSUBA_N / 4] + acc8 * acc4;
acc9 = acc3 + acc4;
acc10 = acc7 + acc8;
d23[i + j] = d23[i + j] + acc9 * acc10;
//--------------------------------------------------------
acc5 = acc5 + acc7; //b02
acc7 = acc1 + acc3; //a02
result_d01[i + j + 0 * KARATSUBA_N / 4] = result_d01[i + j + 0 * KARATSUBA_N / 4] + acc5 * acc7;
acc6 = acc6 + acc8; //b13
acc8 = acc2 + acc4;
result_d01[i + j + 2 * KARATSUBA_N / 4] = result_d01[i + j + 2 * KARATSUBA_N / 4] + acc6 * acc8;
acc5 = acc5 + acc6;
acc7 = acc7 + acc8;
d0123[i + j] = d0123[i + j] + acc5 * acc7;
}
}
// 2nd last stage
for (i = 0; i < KARATSUBA_N / 2 - 1; i++) {
d0123[i] = d0123[i] - result_d01[i + 0 * KARATSUBA_N / 4] - result_d01[i + 2 * KARATSUBA_N / 4];
d01[i] = d01[i] - result_final[i + 0 * KARATSUBA_N / 4] - result_final[i + 2 * KARATSUBA_N / 4];
d23[i] = d23[i] - result_final[i + 4 * KARATSUBA_N / 4] - result_final[i + 6 * KARATSUBA_N / 4];
}
for (i = 0; i < KARATSUBA_N / 2 - 1; i++) {
result_d01[i + 1 * KARATSUBA_N / 4] = result_d01[i + 1 * KARATSUBA_N / 4] + d0123[i];
result_final[i + 1 * KARATSUBA_N / 4] = result_final[i + 1 * KARATSUBA_N / 4] + d01[i];
result_final[i + 5 * KARATSUBA_N / 4] = result_final[i + 5 * KARATSUBA_N / 4] + d23[i];
}
// Last stage
for (i = 0; i < KARATSUBA_N - 1; i++) {
result_d01[i] = result_d01[i] - result_final[i] - result_final[i + KARATSUBA_N];
}
for (i = 0; i < KARATSUBA_N - 1; i++) {
result_final[i + 1 * KARATSUBA_N / 2] = result_final[i + 1 * KARATSUBA_N / 2] + result_d01[i];
}
}
static void toom_cook_4way (const uint16_t *a1, const uint16_t *b1, uint16_t *result) {
uint16_t inv3 = 43691, inv9 = 36409, inv15 = 61167;
uint16_t aw1[N_SB], aw2[N_SB], aw3[N_SB], aw4[N_SB], aw5[N_SB], aw6[N_SB], aw7[N_SB];
uint16_t bw1[N_SB], bw2[N_SB], bw3[N_SB], bw4[N_SB], bw5[N_SB], bw6[N_SB], bw7[N_SB];
uint16_t w1[N_SB_RES] = {0}, w2[N_SB_RES] = {0}, w3[N_SB_RES] = {0}, w4[N_SB_RES] = {0},
w5[N_SB_RES] = {0}, w6[N_SB_RES] = {0}, w7[N_SB_RES] = {0};
uint16_t r0, r1, r2, r3, r4, r5, r6, r7;
uint16_t *A0, *A1, *A2, *A3, *B0, *B1, *B2, *B3;
A0 = (uint16_t *)a1;
A1 = (uint16_t *)&a1[N_SB];
A2 = (uint16_t *)&a1[2 * N_SB];
A3 = (uint16_t *)&a1[3 * N_SB];
B0 = (uint16_t *)b1;
B1 = (uint16_t *)&b1[N_SB];
B2 = (uint16_t *)&b1[2 * N_SB];
B3 = (uint16_t *)&b1[3 * N_SB];
uint16_t *C;
C = result;
int i, j;
// EVALUATION
for (j = 0; j < N_SB; ++j) {
r0 = A0[j];
r1 = A1[j];
r2 = A2[j];
r3 = A3[j];
r4 = r0 + r2;
r5 = r1 + r3;
r6 = r4 + r5;
r7 = r4 - r5;
aw3[j] = r6;
aw4[j] = r7;
r4 = ((r0 << 2) + r2) << 1;
r5 = (r1 << 2) + r3;
r6 = r4 + r5;
r7 = r4 - r5;
aw5[j] = r6;
aw6[j] = r7;
r4 = (r3 << 3) + (r2 << 2) + (r1 << 1) + r0;
aw2[j] = r4;
aw7[j] = r0;
aw1[j] = r3;
}
for (j = 0; j < N_SB; ++j) {
r0 = B0[j];
r1 = B1[j];
r2 = B2[j];
r3 = B3[j];
r4 = r0 + r2;
r5 = r1 + r3;
r6 = r4 + r5;
r7 = r4 - r5;
bw3[j] = r6;
bw4[j] = r7;
r4 = ((r0 << 2) + r2) << 1;
r5 = (r1 << 2) + r3;
r6 = r4 + r5;
r7 = r4 - r5;
bw5[j] = r6;
bw6[j] = r7;
r4 = (r3 << 3) + (r2 << 2) + (r1 << 1) + r0;
bw2[j] = r4;
bw7[j] = r0;
bw1[j] = r3;
}
// MULTIPLICATION
karatsuba_simple(aw1, bw1, w1);
karatsuba_simple(aw2, bw2, w2);
karatsuba_simple(aw3, bw3, w3);
karatsuba_simple(aw4, bw4, w4);
karatsuba_simple(aw5, bw5, w5);
karatsuba_simple(aw6, bw6, w6);
karatsuba_simple(aw7, bw7, w7);
// INTERPOLATION
for (i = 0; i < N_SB_RES; ++i) {
r0 = w1[i];
r1 = w2[i];
r2 = w3[i];
r3 = w4[i];
r4 = w5[i];
r5 = w6[i];
r6 = w7[i];
r1 = r1 + r4;
r5 = r5 - r4;
r3 = ((r3 - r2) >> 1);
r4 = r4 - r0;
r4 = r4 - (r6 << 6);
r4 = (r4 << 1) + r5;
r2 = r2 + r3;
r1 = r1 - (r2 << 6) - r2;
r2 = r2 - r6;
r2 = r2 - r0;
r1 = r1 + 45 * r2;
r4 = (((r4 - (r2 << 3)) * inv3) >> 3);
r5 = r5 + r1;
r1 = (((r1 + (r3 << 4)) * inv9) >> 1);
r3 = -(r3 + r1);
r5 = (((30 * r1 - r5) * inv15) >> 2);
r2 = r2 - r4;
r1 = r1 - r5;
C[i] += r6;
C[i + 64] += r5;
C[i + 128] += r4;
C[i + 192] += r3;
C[i + 256] += r2;
C[i + 320] += r1;
C[i + 384] += r0;
}
}
void PQCLEAN_SABER_CLEAN_pol_mul(uint16_t *a, uint16_t *b, uint16_t *res, uint16_t p, uint32_t n)
{
uint32_t i;
// normal multiplication
uint16_t c[512];
for (i = 0; i < 512; i++) {
c[i] = 0;
}
toom_cook_4way(a, b, c);
// reduction
for (i = n; i < 2 * n; i++) {
res[i - n] = (c[i - n] - c[i]) & (p - 1);
}
}

View File

@ -0,0 +1,9 @@
#ifndef POLYMUL_H
#define POLYMUL_H
#include "SABER_params.h"
#include <stdint.h>
void PQCLEAN_SABER_CLEAN_pol_mul(uint16_t *a, uint16_t *b, uint16_t *res, uint16_t p, uint32_t n);
#endif

View File

@ -0,0 +1,34 @@
/*-------------------------------------------------
This file has been adapted from the implementation
(available at https://github.com/pq-crystals/kyber) of
"CRYSTALS Kyber: a CCA-secure module-lattice-based KEM"
by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint,
Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle
----------------------------------------------------*/
#include "verify.h"
#include <stdint.h>
/* returns 0 for equal strings, 1 for non-equal strings */
unsigned char PQCLEAN_SABER_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len) {
uint64_t r;
size_t i;
r = 0;
for (i = 0; i < len; i++) {
r |= a[i] ^ b[i];
}
r = (~r + 1); // Two's complement
r >>= 63;
return (unsigned char)r;
}
/* b = 1 means mov, b = 0 means don't mov*/
void PQCLEAN_SABER_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b) {
size_t i;
b = -b;
for (i = 0; i < len; i++) {
r[i] ^= b & (x[i] ^ r[i]);
}
}

View File

@ -0,0 +1,21 @@
#ifndef VERIFY_H
#define VERIFY_H
/*-------------------------------------------------
This file has been adapted from the implementation
(available at https://github.com/pq-crystals/kyber) of
"CRYSTALS Kyber: a CCA-secure module-lattice-based KEM"
by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint,
Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle
----------------------------------------------------*/
#include <stddef.h>
#include <stdint.h>
/* returns 0 for equal strings, 1 for non-equal strings */
unsigned char PQCLEAN_SABER_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len);
/* b = 1 means mov, b = 0 means don't mov*/
void PQCLEAN_SABER_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b);
#endif