diff --git a/Makefile.am b/Makefile.am index c6b3e39fb..e0d7e5a0c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 diff --git a/VisualStudio/oqs/dll.def b/VisualStudio/oqs/dll.def index ed62a387f..fc476419b 100644 --- a/VisualStudio/oqs/dll.def +++ b/VisualStudio/oqs/dll.def @@ -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 diff --git a/VisualStudio/oqs/oqs.vcxproj b/VisualStudio/oqs/oqs.vcxproj index bf06656d2..100090727 100644 --- a/VisualStudio/oqs/oqs.vcxproj +++ b/VisualStudio/oqs/oqs.vcxproj @@ -40,6 +40,7 @@ + @@ -188,6 +189,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -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\" diff --git a/VisualStudio/oqs/oqs.vcxproj.filters b/VisualStudio/oqs/oqs.vcxproj.filters index 467c5d969..0e4f0e3cd 100644 --- a/VisualStudio/oqs/oqs.vcxproj.filters +++ b/VisualStudio/oqs/oqs.vcxproj.filters @@ -269,6 +269,78 @@ ntru\hrss701 + + saber\lightsaber + + + saber\lightsaber + + + saber\lightsaber + + + saber\lightsaber + + + saber\lightsaber + + + saber\lightsaber + + + saber\lightsaber + + + saber\lightsaber + + + saber\saber + + + saber\saber + + + saber\saber + + + saber\saber + + + saber\saber + + + saber\saber + + + saber\saber + + + saber\saber + + + saber\firesaber + + + saber\firesaber + + + saber\firesaber + + + saber\firesaber + + + saber\firesaber + + + saber\firesaber + + + saber\firesaber + + + saber\firesaber + dilithium\2 @@ -533,6 +605,9 @@ ntru + + saber + dilithium @@ -741,6 +816,18 @@ {96485f85-7dd5-4df3-a1cd-769da06d3ada} + + {281a0a06-959f-43bb-afc3-d72cf9816fc5} + + + {64918521-b019-48f6-89c3-ad2ce40a8c72} + + + {3cbb7630-a3ce-4d70-a37d-8fd780a20aba} + + + {f7014d1d-26fc-4fa6-87b2-0c4552cdc0d2} + {2a035f7e-7c7e-4ca3-94ac-140aac970a73} diff --git a/VisualStudio/winconfig.h b/VisualStudio/winconfig.h index f170050c4..70dd6a14f 100644 --- a/VisualStudio/winconfig.h +++ b/VisualStudio/winconfig.h @@ -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 diff --git a/config/features.m4 b/config/features.m4 index 47f377ae5..e78f18192 100644 --- a/config/features.m4 +++ b/config/features.m4 @@ -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") diff --git a/configure.ac b/configure.ac index b0b8c7f83..a1725e360 100644 --- a/configure.ac +++ b/configure.ac @@ -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 diff --git a/docs/algorithms/kem_saber.md b/docs/algorithms/kem_saber.md new file mode 100644 index 000000000..cd6cc4600 --- /dev/null +++ b/docs/algorithms/kem_saber.md @@ -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 diff --git a/scripts/copy_from_pqclean/copy_from_pqclean.yml b/scripts/copy_from_pqclean/copy_from_pqclean.yml index 3ed0d30f2..5c3fed7b5 100644 --- a/scripts/copy_from_pqclean/copy_from_pqclean.yml +++ b/scripts/copy_from_pqclean/copy_from_pqclean.yml @@ -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 diff --git a/scripts/copy_from_pqclean/src/kem/kem.h/algs_length.fragment b/scripts/copy_from_pqclean/src/kem/kem.h/algs_length.fragment index e2fcb8a47..79550743e 100644 --- a/scripts/copy_from_pqclean/src/kem/kem.h/algs_length.fragment +++ b/scripts/copy_from_pqclean/src/kem/kem.h/algs_length.fragment @@ -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 }} diff --git a/src/kem/kem.c b/src/kem/kem.c index c2ffd7335..0fbb381bf 100644 --- a/src/kem/kem.c +++ b/src/kem/kem.c @@ -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)) { diff --git a/src/kem/kem.h b/src/kem/kem.h index 0ee71692e..6bd8ba913 100644 --- a/src/kem/kem.h +++ b/src/kem/kem.h @@ -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 #include #include +#include ///// OQS_COPY_FROM_PQCLEAN_FRAGMENT_INCLUDE_END #include #include diff --git a/src/kem/saber/FireSaber-KEM.kat b/src/kem/saber/FireSaber-KEM.kat new file mode 100755 index 000000000..6a703794e --- /dev/null +++ b/src/kem/saber/FireSaber-KEM.kat @@ -0,0 +1,6 @@ +count = 0 +seed = 061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA1 +pk = 7AEF892E4EE8DA1B65A5CBCA85954AEB68A007A7FD13BF443946D0DA1BE74453BACE8CF007551DC4A29ADC923528934037EEE6A327556BC121B4732FF962C4F6E3CE656C457F4E939676F15E8F23EE1716E4E19A52B5E1CAF48767F9548E9EF2A15533FA32D713F19CCF62392DF9C093CC1A5C145B994FB27DF46771963EB4956FDFEE90598B4AECE99A83156C39C74F0C330BCB4151F06C017F63D6DF963AB07B1FCFECBD49E8A740433136B0088B1A534B539ACD83DA63D5C56CED05453FE92FE088BE56CF0D4CCD95368FE61F66140E61F39F2FF7B3A31A5C9872286F9007B1197E5DFD495C7C101D73C092BCBB393EC3F0C9346694ACF524A15DC000CB604F24F08C6EA4A7D60BC46DA9490FFAA427D9EEE944E4E5E03371A46BABAFEC7D94BE7AB0085A95C11C311406D1B3DE42AB20FCAE2C0E950E0140E9B1278F880C00FD819F1B4DD55D199B09D8A849637754CC695E676D426B758B2DA7373B40C15B66B411B30C54A5F4FF5B78DE52F0BC6F7E08BD94DF092BCC0992B7D5E107E121A1220E691F35778374CF8E08E32078DAB749A79B1FD715D03F0A96055583CE6536598711F783EC8D90272DC0C3E8540149F9BF186FD1A9D85FD4EEDCB19EF0909238E447A76C259DC62B9F9590E112D08CE121F42BF6A30CD5D16AB3A3B0715A816EB92691B71A676B9C32E2A1F0ECEA221FA68C89C79B79B32E12A8266A053ECD9F004C26E61C6E24D1864BA2C727C69C03D8BC2DAE1C0E03BB7FDC714AFDA244D99D94EC9E67A78E9AE34C2135D778A8A4F35CA39FA93384EA8D403D2DDEC9A252901BA02BF9F430259402626DE67BC924764C0AAE731B7CBB0ACECD6F44B2F0BB84AAE5C78455DA2A9817354A98EF48CC2493B561C5E75CD062E94FD857F922574DA8CDEFFFB69DCD487BBB2A62327A8EB6B112AE0F499761DE19B501251934C4DCDBEF0416994EABCCA20BA1F905D5BD7489C719677D3FA4DCBD22982B649D752D54839605CB2AA16AF1D3617CADC5EF211E1B5B440E7A58E9269F78CE98DADE49B82871576CA1F37356B30A4D2909975E0FC96CF3102B0C6339FB9BD727DF4DAAC60E99058ACE061A5E51193A87F66586C1AD63B00D7494CD395D6C53EE84CD154DA586CC4CDFD7B8AC31EF8F90DB77A0A507851479435E6B2D109F4963DDAC19D443F4B3E4ECC40F43E6CA4C395CDB873D4304D372FBFCAB2D292AADD7F2D92D62BD4A0317269DEA85FF1425A609300F37184A1B8950CF64DC12C9C0D45CE3DB1F4B25D0B6E87EF7BA55E48512E9D5D79E5ED9D453548309328634E5F8919858AB509AC41BA09694E4DEBCCB3CE6BE531ACDD9D17644BDAEB27C3205C3784BEF8C3A5E32C2EAF84B63F88C173F0EFF587EDF55A8315ECB755790628242ECEEBEE4EDC0159BAEE86C5C2B7CCCBD1FA9A01B6B73D0A7E9C135C03B2703405E85C2268812CAF28E70A25D2DF9039444206CF5D1CA768B0AC9BB2BF0960047E68A0D3904AD5882690E3C6B55EAA0597A9E8FFC3045A661EE5B4336DE14E6C7E2B958BCACD2DA14A830E204F793DF999B8C4906D9139F44D8FE56DE68AC64D5311BE0E06D0884705BA1400983AC3122389F2ADD4EC51847EFCB3F0CD08B51808611F7B85ABB5879BC77AE52D50A1A83DC6A004FB086D390FA0A17E17893695630D8D1B4FF8CD3F946884A816079C1FDA1D1556914550239093559D212872F62EA1EB1491DDA99E249BD1245C01968BDF5450E55903295EC92E95CC59CCE9A99011BB2C8B3C1C491202B13E89CAE3461074EA051036B2B6F0C17791E1DF3DBE9F2AC32935489C7EDD064BBA9A78CEAB09D29E020C0EA8F1C70D33A813889C3 +sk = 004000F8FFFF2F00004000F8FF03C0FF070000200000C0FF0700FF1F00FCFF0000000280FF0700FFFFFFFFFFFFFFFF0340000000010000F87F000000FEFFFFFFFFFEFFFF030000E0FF0140000800012000FC7F000000FEFFFF0F0001E0FFFFFFFFEFFF0100000000026000FC7F01E0FF0300000000FFDFFFFF7F000000000000F8FFFD1F00040000000000400000000120000480FF0F00020000F8FF00E0FFFF7F000000FEBFFF0F0000E0FF030000F0FFFD3F001000FF5F000080000000FCFFFF0F00002000FC7F00F0FF03000008000140000000001000008000100000E0FFFF7F011000FEFFFF0F0000E0FF0380FF1F0004C0FFFFFF004000FCFFFEFFFFFF7F00E8FFFF1F000400FF1F00FE7F000000FF1F000400FF1F000280FFF7FF0200000080FFFFFF018000080000E0FF030000F0FFFFFFFF0F00FFFFFF0300FFEFFFFD3F001000FFDFFF0380FF0F000200000000010000F47FFF0F000000000000FEDFFF0380FF0F00FCFFFFF7FF01C0FF0B80FE1F0002C0FF0F00FF3F00F87F00000000C0FFFFFFFEFFFFFF7FFFFFFFFFFFFFFFFFFFFFFF0380FF1F00FC7F00100000C0FFFF7F00000002C0FFF7FF004000FCFFFF1F000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFD3F000400002000000000F8FFFF1F000400FF2F00020000F8FF010000FCFF0000000280000800FE5F00FCFFFFFFFF014000F8FF00E0FF0300FF0F00064000000001C0FF0380FF0F0000C0FFFFFF0020000080001000FE3F0000000220000400FF1F0000C0FF0F00000000008000F0FF014000F0FF03E0FFFFFF00100000000008000020000000002000FEFFFFFFFF0100000080FF1F000040000000FE3F00FC7F00E0FF0140000000FF1F000400FF1F00000000F8FF002000F87F00F0FF03C0FF0F0000C0FFFF7F000000FCFFFF070002E0FFFFFFFF1F000080000000FE7F000080001000FEFFFF0700010000FC7F00F0FF03C0FF0700FFBFFFFBFF00000000C0FFFFFF01C0FFFF7F002000040000F0FFFEFFFF03000000000040001000FFFFFF078000200002C0FF070003C0FF07000010000000000800FFDFFF038000100002C0FF07000300000080FF1F0002C0FF1700FFFFFF0780001000004000F8FF00C0FF0B00000000FCFFFF070000E0FFFFFF00F0FFFDBFFF170001E0FF07000000000000000000FE3F00FC7F001000000000F8FFFF5F000480FF1F000200000000FF1F00FCFF00E0FF0340000000FEFFFFFF7F00E0FF01400000000000000080002000FC3F0008000200000080FFFFFF0140000000002000FCFFFFFFFFFFFFFFF7FF01C0FF038000E0FFFD3F0008000020000080FF0F00FC3F001000010000040000F0FFFFFFFFFFFFFF3F00048000F0FF03C0FFFFFF000000FC7F00100000000010000100000000FF0F0004C0FF070002200000000010000200000800FEFFFF0F00FFFFFFFDFFFF07000020000000013000FC7F00F8FF0100000080FF2F00FEBFFF07000060000480FF1F0000000000000100000080FF1F000200001800010000F8FF00000000000008000000000000000000020000F8FFFEFFFF070000F0FFFF3F00F0FF000000FCFFFF1F000080000800FF1F00008000F0FF054000F0FFFF3F00FCFFFF1F00FCBF000000002000F47FFFFFFFFF7F000800FFFFFF0700012000000000F8FF010000FC7F010000000000F0FF0220000480FF0F00FC3F00F8FF000000F8FF000000FE3F00080002E0FF0B800010000280FF1F0000000008000010000080FFFFFFFF1F000480FF0F00FEBFFFFFFF022000008000200000C0FF0700FF1F000080FFFFFF0300000000FF5F000C0000000004C0FF070000E0FF0B0000000000C0FFF7FF020000000000E0FFFF7F000800FF5F00FC7FFF1F00FE7F00E8FF0120000000000000FE3F00000000E0FF03800000000240000000FF1F00FC7F0100000040000000FE3F000400FF0F000200001000002000048000F0FF014000000002C0FF0380000000FE3F0008000000000000000000FE7F00F0FF012000FC7FFFFFFF010000F8FFFFFFFFFBFFFF1F00FEBF00F8FFFF1F000000FF1F00008000F0FF0100000880FF0F00FEBFFF0700FE1F00000000100002000000000140000800FF0F00FE3F00000000C0FF0300FF0F00020000F0FFFEFFFFFFFFFF1F00024000E8FFFE3F00FCFF00F0FFFF3F00080001200004000000000080000800002000FC7F00100002C0FFFFFF01E0FFFB7F01F0FF0300000800002000FC7F001000FC3F001000022000FCFFFFFFFF0500000000FF3F000000FF0F000040FF0700FF3F000000FFEFFF0140000000FE1F00F8FFFF2F0002400008007AEF892E4EE8DA1B65A5CBCA85954AEB68A007A7FD13BF443946D0DA1BE74453BACE8CF007551DC4A29ADC923528934037EEE6A327556BC121B4732FF962C4F6E3CE656C457F4E939676F15E8F23EE1716E4E19A52B5E1CAF48767F9548E9EF2A15533FA32D713F19CCF62392DF9C093CC1A5C145B994FB27DF46771963EB4956FDFEE90598B4AECE99A83156C39C74F0C330BCB4151F06C017F63D6DF963AB07B1FCFECBD49E8A740433136B0088B1A534B539ACD83DA63D5C56CED05453FE92FE088BE56CF0D4CCD95368FE61F66140E61F39F2FF7B3A31A5C9872286F9007B1197E5DFD495C7C101D73C092BCBB393EC3F0C9346694ACF524A15DC000CB604F24F08C6EA4A7D60BC46DA9490FFAA427D9EEE944E4E5E03371A46BABAFEC7D94BE7AB0085A95C11C311406D1B3DE42AB20FCAE2C0E950E0140E9B1278F880C00FD819F1B4DD55D199B09D8A849637754CC695E676D426B758B2DA7373B40C15B66B411B30C54A5F4FF5B78DE52F0BC6F7E08BD94DF092BCC0992B7D5E107E121A1220E691F35778374CF8E08E32078DAB749A79B1FD715D03F0A96055583CE6536598711F783EC8D90272DC0C3E8540149F9BF186FD1A9D85FD4EEDCB19EF0909238E447A76C259DC62B9F9590E112D08CE121F42BF6A30CD5D16AB3A3B0715A816EB92691B71A676B9C32E2A1F0ECEA221FA68C89C79B79B32E12A8266A053ECD9F004C26E61C6E24D1864BA2C727C69C03D8BC2DAE1C0E03BB7FDC714AFDA244D99D94EC9E67A78E9AE34C2135D778A8A4F35CA39FA93384EA8D403D2DDEC9A252901BA02BF9F430259402626DE67BC924764C0AAE731B7CBB0ACECD6F44B2F0BB84AAE5C78455DA2A9817354A98EF48CC2493B561C5E75CD062E94FD857F922574DA8CDEFFFB69DCD487BBB2A62327A8EB6B112AE0F499761DE19B501251934C4DCDBEF0416994EABCCA20BA1F905D5BD7489C719677D3FA4DCBD22982B649D752D54839605CB2AA16AF1D3617CADC5EF211E1B5B440E7A58E9269F78CE98DADE49B82871576CA1F37356B30A4D2909975E0FC96CF3102B0C6339FB9BD727DF4DAAC60E99058ACE061A5E51193A87F66586C1AD63B00D7494CD395D6C53EE84CD154DA586CC4CDFD7B8AC31EF8F90DB77A0A507851479435E6B2D109F4963DDAC19D443F4B3E4ECC40F43E6CA4C395CDB873D4304D372FBFCAB2D292AADD7F2D92D62BD4A0317269DEA85FF1425A609300F37184A1B8950CF64DC12C9C0D45CE3DB1F4B25D0B6E87EF7BA55E48512E9D5D79E5ED9D453548309328634E5F8919858AB509AC41BA09694E4DEBCCB3CE6BE531ACDD9D17644BDAEB27C3205C3784BEF8C3A5E32C2EAF84B63F88C173F0EFF587EDF55A8315ECB755790628242ECEEBEE4EDC0159BAEE86C5C2B7CCCBD1FA9A01B6B73D0A7E9C135C03B2703405E85C2268812CAF28E70A25D2DF9039444206CF5D1CA768B0AC9BB2BF0960047E68A0D3904AD5882690E3C6B55EAA0597A9E8FFC3045A661EE5B4336DE14E6C7E2B958BCACD2DA14A830E204F793DF999B8C4906D9139F44D8FE56DE68AC64D5311BE0E06D0884705BA1400983AC3122389F2ADD4EC51847EFCB3F0CD08B51808611F7B85ABB5879BC77AE52D50A1A83DC6A004FB086D390FA0A17E17893695630D8D1B4FF8CD3F946884A816079C1FDA1D1556914550239093559D212872F62EA1EB1491DDA99E249BD1245C01968BDF5450E55903295EC92E95CC59CCE9A99011BB2C8B3C1C491202B13E89CAE3461074EA051036B2B6F0C17791E1DF3DBE9F2AC32935489C7EDD064BBA9A78CEAB09D29E020C0EA8F1C70D33A813889C349AAC773CF8141C4336E93EB70E48DF500E9A9853DC7D556E474E8133D034992147C03F7A5BEBBA406C8FAE1874D7F13C80EFE79A3A9A874CC09FE76F6997615 +ct = AD37F00BCD85C03843FF8955D53FBA02F050000807F6EBCA8127E0AF21C8C572A296ADC7E423DA2361E1C834833C0FE3B443270856CA4E2DEA2501D6F1ACED409991EEB482ACF8690684F006AF9CD65F8AA32F7F8E97BAE4381BF0F6F06B5C1C0AD01AE49C0463FA4D5FDC10E62C23C6D0BAB034BFF5ABEA03D177D505870042405C59C6FA477175A2DBDDBE068A9CEFCFD603746BCF3F1938DF6EEC08210FFFB9DFB6F371EBFB55098530692F8026C49AB8E791913D56C20F1E4DD81C433EA927270F2E456BEC7E70CFBBE866032D8A7BFC53CB2F9670E74A7099A458816903750ED480DFD44CCFA69750F4C965E8AC5D920228E214AD3388381235CBEEF09710E31D51AEADD84C634F2C7B7DEBF05E973782D3A4F3863E1AE93B784AA72283B07F1EB6D1349298CC49D0B1131126862BE7BA811D069ACA76FA4F68755DFFCEBC0C8E59BCA3C3D67CAE7B27368BBB44ABA61EC8066BC6DDC82709A97F0D8481359FE03CBAA2DFE521677361C9726A91810CFDF66426D23A841C776D69D8B8456803DC789FB8BA8B2CBB8C9E8982DB505D770D0DC06EDBCBA658AF043005FB4DF49ACB1047E5400D8689FB2A64CE9B0C90450AD9359CEBBB0151D72313D34838CD512D58BFEEC52A8DB712D8A983402E7712FF2DC463DE961416C51FCF32D8D3A80B03F401B95899AFA35E8B8F0D81A9F4FA50696B454288AAD5AE84B24CAD52D71A75B900363C42889FE9FA84FFC917C7B3AF73ED9BCD2985822B22CC9479734284D2A1D0179196005B460B996DF8C1E8BC95B6D43BF98AFB9E449AEFD537E1373801903FB4240D71EDF7EFDAC592C7445034752EE12E09FCC78EB88D88133498BE710837B2AD5E425CC63E9FC24FDEA133067B6AF5D84E49B9FF70A893828E6D0D17D5B40A002920643A585EF03FF2C7C0BE9AAEFBFCC754894C31B04FF468E7893557888DC847443BDEE9241F9649A590F0EB86DFD5969A10AF1361805ED28010DC7B0416DB6EA551C0D25B8C02E2D426000731D6873CCB9819BA624E2ABFBA3C26AEBE21F488BC316C8ECB0285E47D0D922D052FCBB79CD0BAE0CC31349A7F651B2D78452EB9A17ACBEE7E6FEB8060BDC49A8ACA59376E899082AC79AD6C3B7EAEBF1D9854F4FA5C92E0D8006161F1F68DBAFDC0473836B7249B41F2708F85CCE3442301859349BA1600B2F41B8571795109AF09DC73024021B1990EDE0E2DFDBD6860B390A47B4B394C01555F50D7E611F36BD45458D2DE504F370EC2B4806C36DBE6220BC5394BAAE7D60604A7F66C84B3CD2B961FDAF6EE41B8584DB71FC9EE2785ED695F22CAF86F198E3362905801FFE752BC8007D66044F6033119B8AF5F6F953ED283D0C9035FF588DA2907633142507A40C50F55E6982F52CF3024F3136099B9A30D85368F2AEC629890FF003AC2C2E605A7CEA58C9B9ED2A6E26A5DCEA4D39E29B8F21C33D009F4A75E533B58FBA113F16A86D078AB8C4CDE006567697DF79896C6A345082C17512187A92CCE984DCD3A7A5F11F7C568762879E33BDCF4F1609A23A12D8ECA86FB175953FB3DD77E0F0F9DADC7AA6DF0A60E341F12A9EEED7FA1E4558CD2DA1974D0A1ED0CF548E6B0AF8805247735801FBFE39AA51ADE0E60D9B34C199C713B3443A66B7E348323B9DD0FC61B6420F3411C728B9657D9E8D64FFD50A8A590F5572076456C1A240EB8DCDF739B1B4DE3CBF3478D0EBC7A4799EE6F0AF7BEBDC533877B7A6BA112296B60F6D24AEFAE5B3017D688865C7BA82EA6281582D8AEF0975A9629BB6F8D4E83A6E100EA1CB739EA64C4D2FC6D1659C8A7830098FEA673FE251F9B79B439FCD75EC783946C5FD6D839ED80F790A7D153C8CFC2F253055E9299EC52BEF9098B8605A32835F9E6F4AD65FB564C354D2996D093F46B672219F20CBBEA67BC236942FF63B18FD890355E9B5B9EB37ED1A1268C8F25A0D50288179C3A17CB86D799D408E92D81A0579A50A57C8415A4FECEC8034911B6CAF6C90F0DF0B8C85946DA28BD38BC91D60935C6E005BC59DA9B2601B22C141376091480463C816146108B01F606827274AEE4ED0C62 +ss = B478BDF6D51F9F578E7D5134EEFD4F58D76618424E775CA4184635F925C185AD diff --git a/src/kem/saber/LightSaber-KEM.kat b/src/kem/saber/LightSaber-KEM.kat new file mode 100755 index 000000000..6c53e9a19 --- /dev/null +++ b/src/kem/saber/LightSaber-KEM.kat @@ -0,0 +1,6 @@ +count = 0 +seed = 061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA1 +pk = A92CBDB022F926BCE5679BB3EE3481209318011388EA10E68CD067C9E095775E5E9DB940B6D737646D87298B7984E4FE8EDA669A0584F12CF0EC6EFEB5C85AD69A2F57DCF5DC41CFF6FD7573C5FBFC977A672AC60583A791D618E69A5EE6B28370CC5BBBA22349A4ABF84641863B934655F27C8ADF25651B430FBC5C30CE52DC3160CC47C0CA21B0D11EC0A94449D62B41D362560AC88D2EF9384FBC3992F30038640509287F903DB46008D44C6B9AB07F8529C64485633E5CFE5E47375012DC943769CF58682B2090231B8C08B549C6E3242C7003C0C7CD9B62650ED28E5FA0732A6D4DFC69F024A47CD66B7A28B91790A7D0D590871B54FFA0FBF9763613FC02392A497C4B1F7FD9E9EC9E90117F1924CBD627CBAA35955728EFA441A7A4BA40D8A1BBAB53900B6EF179F037F3DA5C511473B0FC3493291D314698E8FE4733D7B39203E33129A457F72C7ACE27DC68C0C02F358F6ECCF912ADF69EC06271842BCCD45A4D9EC1351DF05C4A89C08DDCD00CE0EE8D4A37BF2BC35D5113B771173221DB0AD38EDE91E6199B6565BCAD4C769849A45AFD47D7D1B5D770A1DF7466AA7AD1DECC58FB667A0DCE98F5735A673AE29F5109039D815FC594C7E34759ED26C5CDC0BF469D60DE2AB30E2D61E9F8EB815BB36DFFD5F6E81550EB00DCECAA4E9C30CE1059592463A747C68AC4D522E59BD9E7CB7565E0F1F2ECDAD7F215EA1ED08AD05D871FF272D5C041226C9D14EF4A2CAA7ACFA7CCA3DA563D8A642F65CCF1CC417BB5EB3589C6AB160E301EBE6DB04D0E6E5BE1D54A27D77F2F540363562CE869ED3EF5B78C6632E7AB8EBBE8517DCEF42F181DFB7B859813F35F4BC7F1E7AF08E55E49D87F4A1D0DE3D295D97593529CC9F13FA80A8CDB7C760D7BDBE9F2AC32935489C7EDD064BBA9A78CEAB09D29E020C0EA8F1C70D33A813889C3 +sk = FEBFFF038000D0FFFFBFFF1F00012000048001E0FFFDBFFFEFFFFF3F00008000F0FF01C0FF1700002000F87F000000FC7F0000000000000080FFFFFFFF3F010800032000F8FFFFFFFF03000000000040000000010000FE7F000000006000F87F01E0FFFD3F001000000000F8FFFE0F0000C0FFF7FF00E0FF03000110000080FF1F00FE3F00FC7F001000FCFFFFFFFFFDFFFF0780FF1F00FEBFFFF7FFFE5F00040000F0FF0180000800FCFFFFFFFF003000004000F8FFFFFFFF0300FF0F0000C0FFFFFF022000FCFF00F0FF01C0FF0F00FF3F00F87F01100000C0FFF7FFFDDFFFF77FFFFFFF01C0FFFFFF0100000000FF1F00048000100003E0FFFFFF003000FEBFFF0700FF1F00FC7F000000020000F0FFFE5F000C80FFFFFF05C0FF1F00FEDFFF030000300000C0FF1700FFDFFFFF7F000000004001F8FF0200000080FFFFFFFFFFFF070000C0FF0300FFFFFF0180FFFFFF0100000000012000000000080001E0FF078000F0FFFDFFFF17000020000880FF1F000280001000FE1F00040000F0FF07C00000000000000400FFFFFFFF7F000800FF1F00148000200002C0FF1F00016000000000F0FF014000F0FFFF1F00FC7F01000002C0FF070000E0FF0380FF1F00FCBF000000FFFFFFFB7F0040000000000000010000F8FF01300000C0FF0F00000000F8FFFF0F000040000800010000F47F000000000000100000E0FF0300FFDFFF030000080003C0FF0380FFEFFF03C0FF0F00010000FC7F010000FCBFFF2700010000F4FF00F0FF050000000001E0FFF77F002000020000F0FF0080FFFB7F00000002C0FF0700FEFFFFFB7F0000000200000800034000040000F0FFFD3F002000FF1F000400FE2F0000C0FFEFFF00E0FF0780FFEFFF0180001800FD3F001000FE2F0002C0FFFFFFFFBFFFF77F001000FC3F00F0FFFE3F00040000F0FF0540FF0F0001000004800100000280FF070001E0FFFFFFFF0F00FEBFFFFFFFFFBFFF0780FF1F00FE3F001000FFFFFF0780013000004000F8FF000000FC7F00200008C0FF0700032000040001200004C0FF0F0001E0FF0380004000FC3F001000000000000000C0FF0300000000FE5F000000000000FC3F01F8FF02C0FFFFFFFFEFFF0340000800FEDFFF0B000100000600000000020000000001F0FF0580FF0700A92CBDB022F926BCE5679BB3EE3481209318011388EA10E68CD067C9E095775E5E9DB940B6D737646D87298B7984E4FE8EDA669A0584F12CF0EC6EFEB5C85AD69A2F57DCF5DC41CFF6FD7573C5FBFC977A672AC60583A791D618E69A5EE6B28370CC5BBBA22349A4ABF84641863B934655F27C8ADF25651B430FBC5C30CE52DC3160CC47C0CA21B0D11EC0A94449D62B41D362560AC88D2EF9384FBC3992F30038640509287F903DB46008D44C6B9AB07F8529C64485633E5CFE5E47375012DC943769CF58682B2090231B8C08B549C6E3242C7003C0C7CD9B62650ED28E5FA0732A6D4DFC69F024A47CD66B7A28B91790A7D0D590871B54FFA0FBF9763613FC02392A497C4B1F7FD9E9EC9E90117F1924CBD627CBAA35955728EFA441A7A4BA40D8A1BBAB53900B6EF179F037F3DA5C511473B0FC3493291D314698E8FE4733D7B39203E33129A457F72C7ACE27DC68C0C02F358F6ECCF912ADF69EC06271842BCCD45A4D9EC1351DF05C4A89C08DDCD00CE0EE8D4A37BF2BC35D5113B771173221DB0AD38EDE91E6199B6565BCAD4C769849A45AFD47D7D1B5D770A1DF7466AA7AD1DECC58FB667A0DCE98F5735A673AE29F5109039D815FC594C7E34759ED26C5CDC0BF469D60DE2AB30E2D61E9F8EB815BB36DFFD5F6E81550EB00DCECAA4E9C30CE1059592463A747C68AC4D522E59BD9E7CB7565E0F1F2ECDAD7F215EA1ED08AD05D871FF272D5C041226C9D14EF4A2CAA7ACFA7CCA3DA563D8A642F65CCF1CC417BB5EB3589C6AB160E301EBE6DB04D0E6E5BE1D54A27D77F2F540363562CE869ED3EF5B78C6632E7AB8EBBE8517DCEF42F181DFB7B859813F35F4BC7F1E7AF08E55E49D87F4A1D0DE3D295D97593529CC9F13FA80A8CDB7C760D7BDBE9F2AC32935489C7EDD064BBA9A78CEAB09D29E020C0EA8F1C70D33A813889C396138744DF873BB04D151F98662646DD8E5565AFB6E1214B8D445130455C1988147C03F7A5BEBBA406C8FAE1874D7F13C80EFE79A3A9A874CC09FE76F6997615 +ct = 10AE4CDAE6B0917BA5F624EC788D243B52CAFE591DBAB1E224A216015E9CC65F925443C687C89BA4F44A6EC9FCF51F2F80FE7B00C152D2AE4A18F756D1D2A09E0E0F4C5619972892F2FFC3EF19940B45D38B02F2AA3D2A877070598AFD57689B66EE429D55E155C8D3F0FB8C32547304F45BB2C1EF6D49BBE0390B25293D54870B9FF2A9CC1AC079DC05F18EEADC1468065FB06777BBF828D8D92B661148EDA354DA5721B842EA979FB122296BDEB383B32DF40C4F1C41A8A06572C2E86917A6AF3FB7CDFA83C33FEFB0F01C6507E1EF3FC22E7B0F184578C77C2B97755256593C1325D24AC9668F79D4ADB563539A6EA648E22CDDB8E5306A81871988C7761424C36E0EC670C852C7CBE2D4E15F0C944F893C68AD9C4E2C2A0913328C47FA67C26D6906D07CB406E0871CA6A51A2F0B90F27AD7EFFB56D01C0ECA0DD8022075EC466B7E76F93793305E1EC67876505810454B4E48F630D82149DD02D51665CC715142A89B58ECDB8612EA6398D0A1E6E7531738B13BB8992948EB0A1AEC624C94E2518ECAC77E810524E13B31013C36E4C5477CD36BC534C261C48C146397AC990889C13E957B12C8DE2DEF26DBE9BF4F33FA6822D229377450F7EAA91626C3B6ADB8E7E07A0C87D6404C6948E1EA760C9E39AA19C77BD68B58A1682415A963EBF67E7BB3F9DB1040B7ECA2905993A105CCF06D1EE180A9A91F8037147177AED298F30DA84AC860D48F93258BCC1DCC265EF7D86199E8F374EBC26AFCB2DA2234FD04812D0A2229B3FEA956AB0DB2D4C9CE64BAC75FB67CAD513891D9CF4A6238C7D03BEF767BDEE40FE4B66703BDC5D495BC9999E8940B985068687592E331C9482D95F5134711CE92A4247A4E8C7793E461B488758918B0EEBC42969280FFB50F7FED29F2AFD6F3EFE8E74C1D82B3D9E264EB675D974924B830BB9CA44EB66E1C10E85B61293941B658D4D9943AA973AE8BDBE23E193008DAF3CEC0810E568D41FDB8C8768A8EED17E1E3F46BCDB6F29D1A94F39A1AB266B3F6D8ECF7C80F +ss = BC9B4B82360B9079E6D26FDD12A58994A12EAF458A3DD5F310322A35A65752F5 diff --git a/src/kem/saber/Makefile.am b/src/kem/saber/Makefile.am new file mode 100644 index 000000000..b3c0d9cb5 --- /dev/null +++ b/src/kem/saber/Makefile.am @@ -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 + diff --git a/src/kem/saber/Saber-KEM.kat b/src/kem/saber/Saber-KEM.kat new file mode 100755 index 000000000..d1b479b77 --- /dev/null +++ b/src/kem/saber/Saber-KEM.kat @@ -0,0 +1,6 @@ +count = 0 +seed = 061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA1 +pk = 29157C69A067DD1C151115A9BBEB2D6E627F4E747716EFA1569C7B7858CB2E71FB52C9984C2B2F98EF255C008024C277F6A5803C6F225AFD169E0FB3E87DFA11457786CCB7D6CDCD472AD7BAB58A5F8F09F40A2718E9C415C2EA7113960ED0E642FE35D01BC639548F2841C0A97D057083DD86ACF474C63CB715EB815E75D738ADFB2106D4EC4BB2FCD419DE1DD8273FE4E18CEF3ECDC48E02875484CB59B561CEA994E1104D295EC6129EC6874D3871E5FF01EC53E86635D907A5A59432557B475AFB8158EC006FFB19ED7FA6B67E5F129B5195146E6BECA2F796C68D42335CB518A9455FDF72696C2C6352D91617DAB38C4855C504F7755D14225413E7E3EE062BE01A405D75D5A8EA2793EEEF962B193C1811EA8169E318363DD88C013B319053B4E7F2F930EC34E52C8131FC2D0F26FB1A08B7F49701F6EBCC67DC7ECF5B314214C7897136EDD0551CA6C828D3507D57521153DE39F2EC7C7935F07C20D5B30086CEE8964E9BE5BC74DE5B95AA2210E952EF5234222934AF1E1AB519D527CF8E3AA40AB34CF30229D2061F18BAA2429410B8FC7AAF949178F6473B0CE2EA094B2BFD4A338B80AB6B7F002B9AA56856C4132F32A001B341EBBA593A8BFE661B50CAB2CDFE80D867AB655C7B7423FA483B080FDB7E059F3CFC6528014D0F7D0DC5526FBA29208EA197493B8A92D66A0A047942264302E61A08A4DF3A91E8E94DDDF469D08EA54A2ECAFD8E64F28D3C40D5BA885D63134550430D205E7E5CAAFE854E494C483AC6CE455D8A1B35F9FD2252E2741E24747EBC052C0B3FE0046FA6FC9B0CCF038088B18EA5B7A3F77A7965640BF6C4FB89F33E30BBDD3C95889206DE51960FDD6A5AA41F80C537E3BAB1576214511CA21A4FD210B2A479E1D414B2A012F789F0D296E22E4A5941434400A3FFC7229068A605891FA15AF03C177D0736A6C2C4FE0D481F48C45568AD92FE1850215AEDED9F97B1219C2E250ECAECB99DFC01101F5D26F36B710E2DA088FD989A0DCE00BB18FB76903BFBD4BBE1CD66DAD049EA12540E81F619FA0478D7687207FFB4EDA6544192629A5BC5E51D927FC143DAC7CEA36B0C7C6D13969F383B0A3BD4C978D04C65E954F82EB883A62825445E2593F5CB23745684F66E5B69D6FCBEDF47507C7B942C1DDAA054F0CACF64EAA5FF31DC213E827D211D47AB0D1D6E2E507F56842D74FC2D94FBCAA9C4BF701ACE46DEC65A2CB9E0B69E75041C9EAED891199C95EC280201E63FC2BCEF11C6ED272FECEB7EA4C3C45785DE6CB4CED51182B25A149F7BC005D68074CD58D916BF48EB13D509714DF03954552B3F1FD2026987CCE4CEC86E09596A1BFCD81CE9F2AC32935489C7EDD064BBA9A78CEAB09D29E020C0EA8F1C70D33A813889C3 +sk = FF3F000480000000FEFF000800FE5F00088000F0FF018000F0FFFF5F00FCFFFFEFFF010000F8FF000000FC7F0100000200000800000000000000100000800010000100000080001000FE7F00000000E0FF0700FF0F0002C0FFFFFF00E0FF030000F0FF0380FF0F000120000000FFEFFFFF7F00F0FFFE3F000480FF0F000280001000012000000000D0FF01C00010000200000480FF2F00FC7F00100001E0FFFFFF00E0FF0140000000014000048000200002C0FF0700FF1F00F87F01E0FF0380FFEFFF002000FC7F00F0FF0180FFFFFFFF5F00F87F001000FE7F000800FD1F00FC7F00E0FFFF7F000000FEFFFFF77F003000024000F8FFFEDFFF0700001000020000F8FFFFDFFF030000100000C0FF070003C0FFF77F00200004C0FFFFFF002000088000F0FFFF3F00080000E0FF0700FFEFFF0380001800020000FCFF00F0FF014000F8FFFE3F00FCFFFF1F00020000F0FF01A0FFF7FF00F0FF0380FFF7FF00E0FFFFFF00D0FFFDBF001000FF3F00F8FF00C0FF0180FFFFFF020000048000F0FFFD3F000000032000000000F0FF0300001000024000000000000002C0FF07000020000400002000FA3F00F8FF0140000400002000048000F0FFFF3F0000000010000040000000FFFFFFFFFF000000FEBFFFF7FFFD5F00FC7F0010000280FF0F0000A0FF0B8000000008C0FF170000200004800010000040FF0700FE1F000880001000FE3F001000000000F8FFFF1F0002400000000200000000012000000000000000C0FFFFFF0000000000001800FF7F00FC7F00200002C0FF1700004000FC7F02F0FFFF3F00100002E0FF07800010000280FF0F00FF1F000080FE2F00000000F8FF01E0FF0380002000FEBF001000FFFFFFFFFFFF1F000480FFFFFF010000FCFFFEFFFF010000F8FF0220000400FF0F00FE3F000800FD1F00FCFFFE1F0002800000000140000400011000FC3F00F8FF01C0FFFB7FFFFFFF010000F8FF03E0FF030000F0FF014000E8FF00E0FF0700000000024000F8FF002000000000000000C0FF0F0001200004000030000000000800FE1F0004000100000440000000FF1F00F87F00C0FF038000F8FF00C0FF0780011000FAFFFF0700FF5F00FC7F01E0FF0140FF0700FEFFFF0B00000000FEFF0008000220000C8000200000C0FF070001C0FFFB7FFF0F000080FF0F0000E0FF0380FF1F000280FF0F0000E0FFFFFFFE0F00FEFFFF07000140000400FF1F0002000000000000000080FF0F00060000F0FF004000100001F0FFFF7F00F0FF0000000080FFEFFF054000F8FF0100001000FF0F000040001000012000000000300002C0FF1700004000FCFF0010000280000800FF3F000480FE0F00FCFFFF0F00FDFFFF0300FFEFFFFFFFFFFFFF0120000C80FF2F00FEFFFF0700010000F4FF000000024000F0FF002000FC7F000000028000000000E0FF070000F0FF0140000800FF3F00F8FFFFFFFFFF7F000800FFDFFF0300FFEFFF01800010000100000480FF2F00024000080001C0FF030000F0FFFD7F000800004000FC7F010000FEBFFF1700FF5F00FC7FFE2F00FC3F00F8FF000000FCFFFF0F00FEBFFF0F0002C0FFFFFF0020000400000000FCFFFFFFFFFF0F00004000100001A0FFFF7F00000002800000000200000400FF0F00FEFFFF0700FF1F000000000000040001F0FFFF1F00F87FFF0F00024000080004E0FFFBFFFE0F00FC7F00F0FFFD3F00000000E0FF0180FFF7FF010000F8FF00E0FF030000000029157C69A067DD1C151115A9BBEB2D6E627F4E747716EFA1569C7B7858CB2E71FB52C9984C2B2F98EF255C008024C277F6A5803C6F225AFD169E0FB3E87DFA11457786CCB7D6CDCD472AD7BAB58A5F8F09F40A2718E9C415C2EA7113960ED0E642FE35D01BC639548F2841C0A97D057083DD86ACF474C63CB715EB815E75D738ADFB2106D4EC4BB2FCD419DE1DD8273FE4E18CEF3ECDC48E02875484CB59B561CEA994E1104D295EC6129EC6874D3871E5FF01EC53E86635D907A5A59432557B475AFB8158EC006FFB19ED7FA6B67E5F129B5195146E6BECA2F796C68D42335CB518A9455FDF72696C2C6352D91617DAB38C4855C504F7755D14225413E7E3EE062BE01A405D75D5A8EA2793EEEF962B193C1811EA8169E318363DD88C013B319053B4E7F2F930EC34E52C8131FC2D0F26FB1A08B7F49701F6EBCC67DC7ECF5B314214C7897136EDD0551CA6C828D3507D57521153DE39F2EC7C7935F07C20D5B30086CEE8964E9BE5BC74DE5B95AA2210E952EF5234222934AF1E1AB519D527CF8E3AA40AB34CF30229D2061F18BAA2429410B8FC7AAF949178F6473B0CE2EA094B2BFD4A338B80AB6B7F002B9AA56856C4132F32A001B341EBBA593A8BFE661B50CAB2CDFE80D867AB655C7B7423FA483B080FDB7E059F3CFC6528014D0F7D0DC5526FBA29208EA197493B8A92D66A0A047942264302E61A08A4DF3A91E8E94DDDF469D08EA54A2ECAFD8E64F28D3C40D5BA885D63134550430D205E7E5CAAFE854E494C483AC6CE455D8A1B35F9FD2252E2741E24747EBC052C0B3FE0046FA6FC9B0CCF038088B18EA5B7A3F77A7965640BF6C4FB89F33E30BBDD3C95889206DE51960FDD6A5AA41F80C537E3BAB1576214511CA21A4FD210B2A479E1D414B2A012F789F0D296E22E4A5941434400A3FFC7229068A605891FA15AF03C177D0736A6C2C4FE0D481F48C45568AD92FE1850215AEDED9F97B1219C2E250ECAECB99DFC01101F5D26F36B710E2DA088FD989A0DCE00BB18FB76903BFBD4BBE1CD66DAD049EA12540E81F619FA0478D7687207FFB4EDA6544192629A5BC5E51D927FC143DAC7CEA36B0C7C6D13969F383B0A3BD4C978D04C65E954F82EB883A62825445E2593F5CB23745684F66E5B69D6FCBEDF47507C7B942C1DDAA054F0CACF64EAA5FF31DC213E827D211D47AB0D1D6E2E507F56842D74FC2D94FBCAA9C4BF701ACE46DEC65A2CB9E0B69E75041C9EAED891199C95EC280201E63FC2BCEF11C6ED272FECEB7EA4C3C45785DE6CB4CED51182B25A149F7BC005D68074CD58D916BF48EB13D509714DF03954552B3F1FD2026987CCE4CEC86E09596A1BFCD81CE9F2AC32935489C7EDD064BBA9A78CEAB09D29E020C0EA8F1C70D33A813889C315A7BA143FD2C97ED443A2383AA01C4A06A578AE152521F7AF6C64A51A8FAC17147C03F7A5BEBBA406C8FAE1874D7F13C80EFE79A3A9A874CC09FE76F6997615 +ct = 719FAC31AE90417F2DA1D37E47A065B860575D1DF2DE60814A39297B902AFA2F5A12A0D66ED34F3AFED294D40E8027102240798A9F3FB38E65BC93D0BE678AEB099CFF15D9D9D88239BC40E81FC74E5CC280E0495058F7AA36B333A0E8D801ECDBC94D5E12B80273A9B37F61E255AC8FCC54D8BCEEEC8829052FB820FA6F3F93C6B0D0D246A354602EE06294EE726DB763B290738D640682106A34DD44F238E33840BD7B01261E167D3ED6DF8FA0700642FA3016B38F29CDE00FA4615D97E62AE145C9003B54501636C8A2784F7F57ED0FD9CE128530F2272AF12137E1274256EAC34C0C901E64EDF50A484178B47C971ED4F021466AE7BAF8BB8CAA5B9978F05471D9DA472D383ED46C44656CDFBA6A03B974240DF6E10D6861293B71401DF58397BEB67BBE6B716BC196CE2D3E8B0A940F07C66FA947B08EA407C57499027015F52850C7BC680BEB3CA5953F90891C45B9894421A95F5A69ED66B00DBD4F9851AB8EE5F60923A61E984A3A632B41B0A1245976F1A8C9D0BB2FD61D4E9C41340BA47EEB595C20BFCB4B88FF0B19EEC0E934F8ED69394AF2042A84EE8CE170252D8DAEFE161132870B46DAE82F3A5F067F017C5FE47CFBD3845F94D8DADBDC6DB8BF72E96694FF624526EDAC214679721A4757E65F64BE73DDC8F81926D506719AA2FE5FC32FA45FFBE75EF6A758EACEB2C07506C4166462A0E6563D3853305B8804288F0D19D22EE96AADBB12086AF3E41CBC4B08D9190368F506630378E0AAC613F5DCB8A5C5BFB63A1AD837A6563478ABB6731E8ED660BCF0FBF38A85358451E4B188519E6D42C5E876617DC8C4F8D1DBD512032642F62DA3A3E7FE0133BD39EAA0996955C21B020446D0AD95F148AA6A36245510D998F1802A61438B30502604A666559FFD013EACAEF008382D7E586622E8C34AC866EADD99291E9B5F8E6C3675A55AFAA141B9ADC0947897555A80E2A5C3824C443954DEE5B77681695363B184B40FCF7824F58775DFB299B20CDDFA10A62E340D5B3B52D21B7C27FBFD79A8565E69838DCE5DE7560BB3D6ECE880D59722908F4931ECCEE163759C193FBC1D4E1F3B3496CE10705C8552D72EC1316940F0562C54C05D7CEFAA32630A7D3B08D9FDBE24A5DD0892DB51BEB4FC80729E0BCA84B9C22DBC56D48AEA6A116BF4965B432A895DAE2DB869B1FE648793984FA283FD96F35A5477A628E477DE7F00E7255D1D6B3F123486CF993726A53193AA9882E149EB35FE8E33D90A86FC6B4FCC68E4F514E3DFBC83771315D29D187C9FF7F95DA67F4F35B6DB697240ECAB1B92F5B89973AA8966DC8DD874FA8F76C9CEDE6A37657F7B7FFE14036B97BE0604E82C07A9280F206D8C1B52CFFA347C038E3946E72F5A526E27EB50AC351925BC5632A1464D0F41E3F57CAA3A426C2546F94F2A8DF9763FAF132B4F08AC06E9C8753B065D94AE275AA452588336B70183664D9C6D1B2070823226943FDA1D116CA2D766EE95B209ADD6BB64B9CEB9DD5EFF54E76EFDCB3F62773CA8F8AE7BF5 +ss = 156533536C8435F82CC36FC1EF9528DEDC49223DDA0091617DC1ACAF6058D1CA diff --git a/src/kem/saber/kem_saber.h b/src/kem/saber/kem_saber.h new file mode 100644 index 000000000..24a5ffd12 --- /dev/null +++ b/src/kem/saber/kem_saber.h @@ -0,0 +1,39 @@ +#ifndef __OQS_KEM_SABER_H +#define __OQS_KEM_SABER_H + +#include + +#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 diff --git a/src/kem/saber/kem_saber_firesaber.c b/src/kem/saber/kem_saber_firesaber.c new file mode 100644 index 000000000..0170bc433 --- /dev/null +++ b/src/kem/saber/kem_saber_firesaber.c @@ -0,0 +1,45 @@ +#include + +#include + +#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 diff --git a/src/kem/saber/kem_saber_lightsaber.c b/src/kem/saber/kem_saber_lightsaber.c new file mode 100644 index 000000000..92e31f597 --- /dev/null +++ b/src/kem/saber/kem_saber_lightsaber.c @@ -0,0 +1,45 @@ +#include + +#include + +#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 diff --git a/src/kem/saber/kem_saber_saber.c b/src/kem/saber/kem_saber_saber.c new file mode 100644 index 000000000..46561d19f --- /dev/null +++ b/src/kem/saber/kem_saber_saber.c @@ -0,0 +1,45 @@ +#include + +#include + +#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 diff --git a/src/kem/saber/pqclean_firesaber_clean/LICENSE b/src/kem/saber/pqclean_firesaber_clean/LICENSE new file mode 100644 index 000000000..08c799e33 --- /dev/null +++ b/src/kem/saber/pqclean_firesaber_clean/LICENSE @@ -0,0 +1,8 @@ +---------------------------------------------------------------------------------------- +SABER_v1.1 + +Public domain + +Authors: Jan-Pieter D'Anvers, Angshuman Karmakar, Sujoy Sinha Roy, +Frederik Vercauteren +---------------------------------------------------------------------------------------- diff --git a/src/kem/saber/pqclean_firesaber_clean/SABER_indcpa.c b/src/kem/saber/pqclean_firesaber_clean/SABER_indcpa.c new file mode 100644 index 000000000..da8aa6857 --- /dev/null +++ b/src/kem/saber/pqclean_firesaber_clean/SABER_indcpa.c @@ -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 +#include + + + +/*----------------------------------------------------------------------------------- + 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; + } + } +} diff --git a/src/kem/saber/pqclean_firesaber_clean/SABER_indcpa.h b/src/kem/saber/pqclean_firesaber_clean/SABER_indcpa.h new file mode 100644 index 000000000..6007352db --- /dev/null +++ b/src/kem/saber/pqclean_firesaber_clean/SABER_indcpa.h @@ -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 + diff --git a/src/kem/saber/pqclean_firesaber_clean/SABER_params.h b/src/kem/saber/pqclean_firesaber_clean/SABER_params.h new file mode 100644 index 000000000..b0d517f80 --- /dev/null +++ b/src/kem/saber/pqclean_firesaber_clean/SABER_params.h @@ -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 + diff --git a/src/kem/saber/pqclean_firesaber_clean/api.h b/src/kem/saber/pqclean_firesaber_clean/api.h new file mode 100644 index 000000000..56d170388 --- /dev/null +++ b/src/kem/saber/pqclean_firesaber_clean/api.h @@ -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 */ diff --git a/src/kem/saber/pqclean_firesaber_clean/cbd.c b/src/kem/saber/pqclean_firesaber_clean/cbd.c new file mode 100644 index 000000000..cca885a10 --- /dev/null +++ b/src/kem/saber/pqclean_firesaber_clean/cbd.c @@ -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 + +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; + + } +} diff --git a/src/kem/saber/pqclean_firesaber_clean/cbd.h b/src/kem/saber/pqclean_firesaber_clean/cbd.h new file mode 100644 index 000000000..b10e5202d --- /dev/null +++ b/src/kem/saber/pqclean_firesaber_clean/cbd.h @@ -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 + +void PQCLEAN_FIRESABER_CLEAN_cbd(uint16_t *r, const unsigned char *buf); + +#endif diff --git a/src/kem/saber/pqclean_firesaber_clean/kem.c b/src/kem/saber/pqclean_firesaber_clean/kem.c new file mode 100644 index 000000000..c66cfed93 --- /dev/null +++ b/src/kem/saber/pqclean_firesaber_clean/kem.c @@ -0,0 +1,96 @@ +#include "SABER_indcpa.h" +#include "SABER_params.h" +#include "fips202.h" +#include "randombytes.h" +#include "verify.h" +#include +#include +#include + +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); +} diff --git a/src/kem/saber/pqclean_firesaber_clean/pack_unpack.c b/src/kem/saber/pqclean_firesaber_clean/pack_unpack.c new file mode 100644 index 000000000..9e68ffc1a --- /dev/null +++ b/src/kem/saber/pqclean_firesaber_clean/pack_unpack.c @@ -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); + } +} diff --git a/src/kem/saber/pqclean_firesaber_clean/pack_unpack.h b/src/kem/saber/pqclean_firesaber_clean/pack_unpack.h new file mode 100644 index 000000000..6509f107c --- /dev/null +++ b/src/kem/saber/pqclean_firesaber_clean/pack_unpack.h @@ -0,0 +1,28 @@ +#ifndef PACK_UNPACK_H +#define PACK_UNPACK_H + +#include "SABER_params.h" +#include +#include + + +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 diff --git a/src/kem/saber/pqclean_firesaber_clean/poly.c b/src/kem/saber/pqclean_firesaber_clean/poly.c new file mode 100644 index 000000000..6fef45d51 --- /dev/null +++ b/src/kem/saber/pqclean_firesaber_clean/poly.c @@ -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); + } +} diff --git a/src/kem/saber/pqclean_firesaber_clean/poly.h b/src/kem/saber/pqclean_firesaber_clean/poly.h new file mode 100644 index 000000000..4f69a068c --- /dev/null +++ b/src/kem/saber/pqclean_firesaber_clean/poly.h @@ -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 + +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 diff --git a/src/kem/saber/pqclean_firesaber_clean/poly_mul.c b/src/kem/saber/pqclean_firesaber_clean/poly_mul.c new file mode 100644 index 000000000..c71d917c4 --- /dev/null +++ b/src/kem/saber/pqclean_firesaber_clean/poly_mul.c @@ -0,0 +1,237 @@ +#include "poly_mul.h" +#include +#include + +#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); + } + + +} diff --git a/src/kem/saber/pqclean_firesaber_clean/poly_mul.h b/src/kem/saber/pqclean_firesaber_clean/poly_mul.h new file mode 100644 index 000000000..4d9600423 --- /dev/null +++ b/src/kem/saber/pqclean_firesaber_clean/poly_mul.h @@ -0,0 +1,9 @@ +#ifndef POLYMUL_H +#define POLYMUL_H + +#include "SABER_params.h" +#include + +void PQCLEAN_FIRESABER_CLEAN_pol_mul(uint16_t *a, uint16_t *b, uint16_t *res, uint16_t p, uint32_t n); + +#endif diff --git a/src/kem/saber/pqclean_firesaber_clean/verify.c b/src/kem/saber/pqclean_firesaber_clean/verify.c new file mode 100644 index 000000000..3c571e92d --- /dev/null +++ b/src/kem/saber/pqclean_firesaber_clean/verify.c @@ -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 + +/* 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]); + } +} diff --git a/src/kem/saber/pqclean_firesaber_clean/verify.h b/src/kem/saber/pqclean_firesaber_clean/verify.h new file mode 100644 index 000000000..1b69b0715 --- /dev/null +++ b/src/kem/saber/pqclean_firesaber_clean/verify.h @@ -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 +#include + +/* 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 diff --git a/src/kem/saber/pqclean_lightsaber_clean/LICENSE b/src/kem/saber/pqclean_lightsaber_clean/LICENSE new file mode 100644 index 000000000..08c799e33 --- /dev/null +++ b/src/kem/saber/pqclean_lightsaber_clean/LICENSE @@ -0,0 +1,8 @@ +---------------------------------------------------------------------------------------- +SABER_v1.1 + +Public domain + +Authors: Jan-Pieter D'Anvers, Angshuman Karmakar, Sujoy Sinha Roy, +Frederik Vercauteren +---------------------------------------------------------------------------------------- diff --git a/src/kem/saber/pqclean_lightsaber_clean/SABER_indcpa.c b/src/kem/saber/pqclean_lightsaber_clean/SABER_indcpa.c new file mode 100644 index 000000000..20cf1de28 --- /dev/null +++ b/src/kem/saber/pqclean_lightsaber_clean/SABER_indcpa.c @@ -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 +#include + + + +/*----------------------------------------------------------------------------------- + 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; + } + } +} diff --git a/src/kem/saber/pqclean_lightsaber_clean/SABER_indcpa.h b/src/kem/saber/pqclean_lightsaber_clean/SABER_indcpa.h new file mode 100644 index 000000000..4f806c55f --- /dev/null +++ b/src/kem/saber/pqclean_lightsaber_clean/SABER_indcpa.h @@ -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 + diff --git a/src/kem/saber/pqclean_lightsaber_clean/SABER_params.h b/src/kem/saber/pqclean_lightsaber_clean/SABER_params.h new file mode 100644 index 000000000..eb3825f25 --- /dev/null +++ b/src/kem/saber/pqclean_lightsaber_clean/SABER_params.h @@ -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 + diff --git a/src/kem/saber/pqclean_lightsaber_clean/api.h b/src/kem/saber/pqclean_lightsaber_clean/api.h new file mode 100644 index 000000000..4f73c035c --- /dev/null +++ b/src/kem/saber/pqclean_lightsaber_clean/api.h @@ -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 */ diff --git a/src/kem/saber/pqclean_lightsaber_clean/cbd.c b/src/kem/saber/pqclean_lightsaber_clean/cbd.c new file mode 100644 index 000000000..f6ebe4d70 --- /dev/null +++ b/src/kem/saber/pqclean_lightsaber_clean/cbd.c @@ -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 + +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; + } +} diff --git a/src/kem/saber/pqclean_lightsaber_clean/cbd.h b/src/kem/saber/pqclean_lightsaber_clean/cbd.h new file mode 100644 index 000000000..37553425f --- /dev/null +++ b/src/kem/saber/pqclean_lightsaber_clean/cbd.h @@ -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 + +void PQCLEAN_LIGHTSABER_CLEAN_cbd(uint16_t *r, const unsigned char *buf); + +#endif diff --git a/src/kem/saber/pqclean_lightsaber_clean/kem.c b/src/kem/saber/pqclean_lightsaber_clean/kem.c new file mode 100644 index 000000000..8aad43025 --- /dev/null +++ b/src/kem/saber/pqclean_lightsaber_clean/kem.c @@ -0,0 +1,96 @@ +#include "SABER_indcpa.h" +#include "SABER_params.h" +#include "fips202.h" +#include "randombytes.h" +#include "verify.h" +#include +#include +#include + +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); +} diff --git a/src/kem/saber/pqclean_lightsaber_clean/pack_unpack.c b/src/kem/saber/pqclean_lightsaber_clean/pack_unpack.c new file mode 100644 index 000000000..4b1c409f0 --- /dev/null +++ b/src/kem/saber/pqclean_lightsaber_clean/pack_unpack.c @@ -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); + } +} diff --git a/src/kem/saber/pqclean_lightsaber_clean/pack_unpack.h b/src/kem/saber/pqclean_lightsaber_clean/pack_unpack.h new file mode 100644 index 000000000..86fd2fad2 --- /dev/null +++ b/src/kem/saber/pqclean_lightsaber_clean/pack_unpack.h @@ -0,0 +1,28 @@ +#ifndef PACK_UNPACK_H +#define PACK_UNPACK_H + +#include "SABER_params.h" +#include +#include + + +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 diff --git a/src/kem/saber/pqclean_lightsaber_clean/poly.c b/src/kem/saber/pqclean_lightsaber_clean/poly.c new file mode 100644 index 000000000..fc86ab3c5 --- /dev/null +++ b/src/kem/saber/pqclean_lightsaber_clean/poly.c @@ -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); + } +} diff --git a/src/kem/saber/pqclean_lightsaber_clean/poly.h b/src/kem/saber/pqclean_lightsaber_clean/poly.h new file mode 100644 index 000000000..47ceeebba --- /dev/null +++ b/src/kem/saber/pqclean_lightsaber_clean/poly.h @@ -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 + +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 diff --git a/src/kem/saber/pqclean_lightsaber_clean/poly_mul.c b/src/kem/saber/pqclean_lightsaber_clean/poly_mul.c new file mode 100644 index 000000000..5b029a78c --- /dev/null +++ b/src/kem/saber/pqclean_lightsaber_clean/poly_mul.c @@ -0,0 +1,237 @@ +#include "poly_mul.h" +#include +#include + +#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); + } + + +} diff --git a/src/kem/saber/pqclean_lightsaber_clean/poly_mul.h b/src/kem/saber/pqclean_lightsaber_clean/poly_mul.h new file mode 100644 index 000000000..8d634584f --- /dev/null +++ b/src/kem/saber/pqclean_lightsaber_clean/poly_mul.h @@ -0,0 +1,9 @@ +#ifndef POLYMUL_H +#define POLYMUL_H + +#include "SABER_params.h" +#include + +void PQCLEAN_LIGHTSABER_CLEAN_pol_mul(uint16_t *a, uint16_t *b, uint16_t *res, uint16_t p, uint32_t n); + +#endif diff --git a/src/kem/saber/pqclean_lightsaber_clean/verify.c b/src/kem/saber/pqclean_lightsaber_clean/verify.c new file mode 100644 index 000000000..52c6969b2 --- /dev/null +++ b/src/kem/saber/pqclean_lightsaber_clean/verify.c @@ -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 + +/* 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]); + } +} diff --git a/src/kem/saber/pqclean_lightsaber_clean/verify.h b/src/kem/saber/pqclean_lightsaber_clean/verify.h new file mode 100644 index 000000000..32c2adb5b --- /dev/null +++ b/src/kem/saber/pqclean_lightsaber_clean/verify.h @@ -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 +#include + +/* 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 diff --git a/src/kem/saber/pqclean_saber_clean/LICENSE b/src/kem/saber/pqclean_saber_clean/LICENSE new file mode 100644 index 000000000..08c799e33 --- /dev/null +++ b/src/kem/saber/pqclean_saber_clean/LICENSE @@ -0,0 +1,8 @@ +---------------------------------------------------------------------------------------- +SABER_v1.1 + +Public domain + +Authors: Jan-Pieter D'Anvers, Angshuman Karmakar, Sujoy Sinha Roy, +Frederik Vercauteren +---------------------------------------------------------------------------------------- diff --git a/src/kem/saber/pqclean_saber_clean/SABER_indcpa.c b/src/kem/saber/pqclean_saber_clean/SABER_indcpa.c new file mode 100644 index 000000000..d381194ce --- /dev/null +++ b/src/kem/saber/pqclean_saber_clean/SABER_indcpa.c @@ -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 +#include + + + +/*----------------------------------------------------------------------------------- + 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; + } + } +} diff --git a/src/kem/saber/pqclean_saber_clean/SABER_indcpa.h b/src/kem/saber/pqclean_saber_clean/SABER_indcpa.h new file mode 100644 index 000000000..f8503f66e --- /dev/null +++ b/src/kem/saber/pqclean_saber_clean/SABER_indcpa.h @@ -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 + diff --git a/src/kem/saber/pqclean_saber_clean/SABER_params.h b/src/kem/saber/pqclean_saber_clean/SABER_params.h new file mode 100644 index 000000000..faa9f6dbd --- /dev/null +++ b/src/kem/saber/pqclean_saber_clean/SABER_params.h @@ -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 + diff --git a/src/kem/saber/pqclean_saber_clean/api.h b/src/kem/saber/pqclean_saber_clean/api.h new file mode 100644 index 000000000..66c3b8bf8 --- /dev/null +++ b/src/kem/saber/pqclean_saber_clean/api.h @@ -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 */ diff --git a/src/kem/saber/pqclean_saber_clean/cbd.c b/src/kem/saber/pqclean_saber_clean/cbd.c new file mode 100644 index 000000000..a2d9fcdde --- /dev/null +++ b/src/kem/saber/pqclean_saber_clean/cbd.c @@ -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 + +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; + } +} diff --git a/src/kem/saber/pqclean_saber_clean/cbd.h b/src/kem/saber/pqclean_saber_clean/cbd.h new file mode 100644 index 000000000..b307921f3 --- /dev/null +++ b/src/kem/saber/pqclean_saber_clean/cbd.h @@ -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 + +void PQCLEAN_SABER_CLEAN_cbd(uint16_t *r, const unsigned char *buf); + +#endif diff --git a/src/kem/saber/pqclean_saber_clean/kem.c b/src/kem/saber/pqclean_saber_clean/kem.c new file mode 100644 index 000000000..9e5b01f4d --- /dev/null +++ b/src/kem/saber/pqclean_saber_clean/kem.c @@ -0,0 +1,96 @@ +#include "SABER_indcpa.h" +#include "SABER_params.h" +#include "fips202.h" +#include "randombytes.h" +#include "verify.h" +#include +#include +#include + +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); +} diff --git a/src/kem/saber/pqclean_saber_clean/pack_unpack.c b/src/kem/saber/pqclean_saber_clean/pack_unpack.c new file mode 100644 index 000000000..06a74778c --- /dev/null +++ b/src/kem/saber/pqclean_saber_clean/pack_unpack.c @@ -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); + } +} diff --git a/src/kem/saber/pqclean_saber_clean/pack_unpack.h b/src/kem/saber/pqclean_saber_clean/pack_unpack.h new file mode 100644 index 000000000..2431a217d --- /dev/null +++ b/src/kem/saber/pqclean_saber_clean/pack_unpack.h @@ -0,0 +1,28 @@ +#ifndef PACK_UNPACK_H +#define PACK_UNPACK_H + +#include "SABER_params.h" +#include +#include + + +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 diff --git a/src/kem/saber/pqclean_saber_clean/poly.c b/src/kem/saber/pqclean_saber_clean/poly.c new file mode 100644 index 000000000..93f55fde7 --- /dev/null +++ b/src/kem/saber/pqclean_saber_clean/poly.c @@ -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); + } +} diff --git a/src/kem/saber/pqclean_saber_clean/poly.h b/src/kem/saber/pqclean_saber_clean/poly.h new file mode 100644 index 000000000..9d216804f --- /dev/null +++ b/src/kem/saber/pqclean_saber_clean/poly.h @@ -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 + +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 diff --git a/src/kem/saber/pqclean_saber_clean/poly_mul.c b/src/kem/saber/pqclean_saber_clean/poly_mul.c new file mode 100644 index 000000000..eb0f38d52 --- /dev/null +++ b/src/kem/saber/pqclean_saber_clean/poly_mul.c @@ -0,0 +1,237 @@ +#include "poly_mul.h" +#include +#include + +#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); + } + + +} diff --git a/src/kem/saber/pqclean_saber_clean/poly_mul.h b/src/kem/saber/pqclean_saber_clean/poly_mul.h new file mode 100644 index 000000000..f813be10a --- /dev/null +++ b/src/kem/saber/pqclean_saber_clean/poly_mul.h @@ -0,0 +1,9 @@ +#ifndef POLYMUL_H +#define POLYMUL_H + +#include "SABER_params.h" +#include + +void PQCLEAN_SABER_CLEAN_pol_mul(uint16_t *a, uint16_t *b, uint16_t *res, uint16_t p, uint32_t n); + +#endif diff --git a/src/kem/saber/pqclean_saber_clean/verify.c b/src/kem/saber/pqclean_saber_clean/verify.c new file mode 100644 index 000000000..81f30604d --- /dev/null +++ b/src/kem/saber/pqclean_saber_clean/verify.c @@ -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 + +/* 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]); + } +} diff --git a/src/kem/saber/pqclean_saber_clean/verify.h b/src/kem/saber/pqclean_saber_clean/verify.h new file mode 100644 index 000000000..cacb2ee6f --- /dev/null +++ b/src/kem/saber/pqclean_saber_clean/verify.h @@ -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 +#include + +/* 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