diff --git a/.CMake/alg_support.cmake b/.CMake/alg_support.cmake index 31d1aff524..cd36f04d00 100644 --- a/.CMake/alg_support.cmake +++ b/.CMake/alg_support.cmake @@ -121,6 +121,17 @@ option(OQS_ENABLE_SIG_MQDSS "" ON) cmake_dependent_option(OQS_ENABLE_SIG_mqdss_31_48 "" ON "OQS_ENABLE_SIG_MQDSS" OFF) cmake_dependent_option(OQS_ENABLE_SIG_mqdss_31_64 "" ON "OQS_ENABLE_SIG_MQDSS" OFF) +option(OQS_ENABLE_SIG_RAINBOW "" ON) +cmake_dependent_option(OQS_ENABLE_SIG_rainbow_Ia_classic "" ON "OQS_ENABLE_SIG_RAINBOW" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_rainbow_Ia_cyclic "" ON "OQS_ENABLE_SIG_RAINBOW" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_rainbow_Ia_cyclic_compressed "" ON "OQS_ENABLE_SIG_RAINBOW" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_rainbow_IIIc_classic "" ON "OQS_ENABLE_SIG_RAINBOW" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_rainbow_IIIc_cyclic "" ON "OQS_ENABLE_SIG_RAINBOW" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_rainbow_IIIc_cyclic_compressed "" ON "OQS_ENABLE_SIG_RAINBOW" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_rainbow_Vc_classic "" ON "OQS_ENABLE_SIG_RAINBOW" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_rainbow_Vc_cyclic "" ON "OQS_ENABLE_SIG_RAINBOW" OFF) +cmake_dependent_option(OQS_ENABLE_SIG_rainbow_Vc_cyclic_compressed "" ON "OQS_ENABLE_SIG_RAINBOW" OFF) + option(OQS_ENABLE_SIG_SPHINCS "" ON) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_haraka_128f_robust "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) cmake_dependent_option(OQS_ENABLE_SIG_sphincs_haraka_128f_simple "" ON "OQS_ENABLE_SIG_SPHINCS" OFF) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2c79702fdd..3baa96e713 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,10 +1,20 @@ version: 2 +# CircleCI doesn't handle large file sets properly for local builds +# https://github.com/CircleCI-Public/circleci-cli/issues/281#issuecomment-472808051 +localCheckout: &localCheckout + run: |- + PROJECT_PATH=$(cd ${CIRCLE_WORKING_DIRECTORY}; pwd) + mkdir -p ${PROJECT_PATH} + cd /tmp/_circleci_local_build_repo + git ls-files -z | xargs -0 -s 2090860 tar -c | tar -x -C ${PROJECT_PATH} + cp -a /tmp/_circleci_local_build_repo/.git ${PROJECT_PATH} + .oqsjob: &oqsjob docker: - image: ${IMAGE} steps: - - checkout + - checkout # change this from "checkout" to "*localCheckout" when running CircleCI locally - run: name: Configure command: scripts/git_no_checkin_in_last_day.sh || (mkdir build && cd build && cmake -GNinja ${CONFIGURE_ARGS} ..) diff --git a/CMakeLists.txt b/CMakeLists.txt index f59af79fba..c2881481bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,6 +103,9 @@ endif() if(OQS_ENABLE_SIG_MQDSS) set(PUBLIC_HEADERS ${PUBLIC_HEADERS} ${PROJECT_SOURCE_DIR}/src/sig/mqdss/sig_mqdss.h) endif() +if(OQS_ENABLE_SIG_RAINBOW) + set(PUBLIC_HEADERS ${PUBLIC_HEADERS} ${PROJECT_SOURCE_DIR}/src/sig/rainbow/sig_rainbow.h) +endif() if(OQS_ENABLE_SIG_SPHINCS) set(PUBLIC_HEADERS ${PUBLIC_HEADERS} ${PROJECT_SOURCE_DIR}/src/sig/sphincs/sig_sphincs.h) endif() diff --git a/README.md b/README.md index 7c24b2775e..5c09f82737 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,7 @@ More information on OQS can be found [here](https://openquantumsafe.org/) and in - **MQDSS**: MQDSS-31-48, MQDSS-31-64 - **Picnic**: Picnic-L1-FS, Picnic-L1-UR, Picnic-L3-FS, Picnic-L3-UR, Picnic-L5-FS, Picnic-L5-UR, Picnic2-L1-FS, Picnic2-L3-FS, Picnic2-L5-FS - **qTesla**: qTesla-p-I, qTesla-p-III +- **Rainbow**: Rainbow-Ia-Classic, Rainbow-Ia-Cyclic, Rainbow-Ia-Cyclic-Compressed, Rainbow-IIIc-Classic, Rainbow-IIIc-Cyclic, Rainbow-IIIc-Cyclic-Compressed, Rainbow-Vc-Classic, Rainbow-Vc-Cyclic, Rainbow-Vc-Cyclic-Compressed - **SPHINCS+-Haraka**: SPHINCS+-Haraka-128f-robust, SPHINCS+-Haraka-128f-simple, SPHINCS+-Haraka-128s-robust, SPHINCS+-Haraka-128s-simple, SPHINCS+-Haraka-192f-robust, SPHINCS+-Haraka-192f-simple, SPHINCS+-Haraka-192s-robust, SPHINCS+-Haraka-192s-simple, SPHINCS+-Haraka-256f-robust, SPHINCS+-Haraka-256f-simple, SPHINCS+-Haraka-256s-robust, SPHINCS+-Haraka-256s-simple - **SPHINCS+-SHA256**: SPHINCS+-SHA256-128f-robust, SPHINCS+-SHA256-128f-simple, SPHINCS+-SHA256-128s-robust, SPHINCS+-SHA256-128s-simple, SPHINCS+-SHA256-192f-robust, SPHINCS+-SHA256-192f-simple, SPHINCS+-SHA256-192s-robust, SPHINCS+-SHA256-192s-simple, SPHINCS+-SHA256-256f-robust, SPHINCS+-SHA256-256f-simple, SPHINCS+-SHA256-256s-robust, SPHINCS+-SHA256-256s-simple - **SPHINCS+-SHAKE256**: SPHINCS+-SHAKE256-128f-robust, SPHINCS+-SHAKE256-128f-simple, SPHINCS+-SHAKE256-128s-robust, SPHINCS+-SHAKE256-128s-simple, SPHINCS+-SHAKE256-192f-robust, SPHINCS+-SHAKE256-192f-simple, SPHINCS+-SHAKE256-192s-robust, SPHINCS+-SHAKE256-192s-simple, SPHINCS+-SHAKE256-256f-robust, SPHINCS+-SHAKE256-256f-simple, SPHINCS+-SHAKE256-256s-robust, SPHINCS+-SHAKE256-256s-simple diff --git a/docs/algorithms/sig_falcon.md b/docs/algorithms/sig_falcon.md index 55d99e0a36..57f826aafd 100644 --- a/docs/algorithms/sig_falcon.md +++ b/docs/algorithms/sig_falcon.md @@ -9,12 +9,13 @@ liboqs algorithm datasheet: `sig_falcon` - **Main cryptographic assumption**: hardness of NTRU lattice problems - **NIST submission URL**: https://csrc.nist.gov/CSRC/media/Projects/Post-Quantum-Cryptography/documents/round-2/submissions/Falcon-Round2.zip - **Submitters (to NIST competition)**: Thomas Prest, Pierre-Alain Fouque, Jeffrey Hoffstein, Paul Kirchner, Vadim Lyubashevsky, Thomas Pornin, Thomas Ricosset, Gregor Seiler, William Whyte, Zhenfei Zhang +- **Submitters' website**: https://falcon-sign.info - **Added to liboqs by**: Dimitrios Sikeridis, Douglas Stebila Parameter sets -------------- - | Parameter set | Security model | Claimed NIST security level | Public key size (bytes) | Secret key size (bytes) | Signature size (bytes) | + Parameter set | Security model | Claimed NIST security level | Public key size (bytes) | Secret key size (bytes) | Signature size (bytes) | |---------------|:--------------:|:---------------------------:|:-----------------------:|:-----------------------:|:----------------------:| | Falcon-512 | EUF-CMA | 1 | 897 | 1281 | 690 | | Falcon-1024 | EUF-CMA | 5 | 1793 | 2305 | 1330 | diff --git a/docs/algorithms/sig_rainbow.md b/docs/algorithms/sig_rainbow.md new file mode 100644 index 0000000000..f99fea9c2d --- /dev/null +++ b/docs/algorithms/sig_rainbow.md @@ -0,0 +1,36 @@ +liboqs algorithm datasheet: `sig_rainbow` +========================================= + + Summary +------- + + - **Name**: Rainbow +- **Algorithm type**: signature +- **Main cryptographic assumption**: multivariable polynomials, unbalanced oil and vinegatr +- **NIST submission URL**: https://csrc.nist.gov/CSRC/media/Projects/Post-Quantum-Cryptography/documents/round-2/submissions/Rainbow-Round2.zip +- **Submitters (to NIST competition)**: Jintai Ding, Ming-Shing Chen, Albrecht Petzoldt, Dieter Schmidt, Bo-Yin Yang +- **Added to liboqs by**: Douglas Stebila + + Parameter sets +-------------- + +| Parameter set | Security model | Claimed NIST security level | Public key size (bytes) | Secret key size (bytes) | Signature size (bytes) | +|--------------------------------|:--------------:|:---------------------------:|:-----------------------:|:-----------------------:|:----------------------:| +| Rainbow-Ia-Classic | EUF-CMA | 1 | 148992 | 92960 | 64 | +| Rainbow-Ia-Cyclic | EUF-CMA | 1 | 58144 | 92960 | 64 | +| Rainbow-Ia-Cyclic-Compressed | EUF-CMA | 1 | 58144 | 64 | 64 | +| Rainbow-IIIc-Classic | EUF-CMA | 3 | 710640 | 511448 | 156 | +| Rainbow-IIIc-Cyclic | EUF-CMA | 3 | 206744 | 511448 | 156 | +| Rainbow-IIIc-Cyclic-Compressed | EUF-CMA | 3 | 206744 | 64 | 156 | +| Rainbow-Vc-Classic | EUF-CMA | 5 | 1705536 | 1227104 | 204 | +| Rainbow-Vc-Cyclic | EUF-CMA | 5 | 491936 | 1227104 | 204 | +| Rainbow-Vc-Cyclic-Compressed | EUF-CMA | 5 | 491936 | 64 | 204 | + + Implementation +-------------- + + - **Source of implementation:** https://github.com/PQClean/PQClean +- **Implementation version:** https://github.com/PQClean/PQClean/commit/9023fef55861faccd82146cf599b9e46fb9606aa +- **License:** CC0 1.0 +- **Language:** C +- **Constant-time:** Yes diff --git a/scripts/copy_from_pqclean/copy_from_pqclean.yml b/scripts/copy_from_pqclean/copy_from_pqclean.yml index 216a994ba8..3b54a4e07f 100644 --- a/scripts/copy_from_pqclean/copy_from_pqclean.yml +++ b/scripts/copy_from_pqclean/copy_from_pqclean.yml @@ -283,72 +283,72 @@ sigs: implementation: clean sources: ['gf31.c', 'mq.c', 'sign.c'] signed_msg_order: sig_then_msg - # - - # name: rainbow - # schemes: - # - - # scheme: "Ia_classic" - # pqclean_scheme: rainbowIa-classic - # pretty_name_full: Rainbow-Ia-Classic - # implementation: clean - # sources: ['blas_comm.c', 'parallel_matrix_op.c', 'rainbow.c', 'rainbow_keypair.c', 'rainbow_keypair_computation.c', 'sign.c', 'utils_hash.c', 'utils_prng.c', 'blas_u32.c', 'gf.c'] - # signed_msg_order: msg_then_sig - # - - # scheme: "Ia_cyclic" - # pqclean_scheme: rainbowIa-cyclic - # pretty_name_full: Rainbow-Ia-Cyclic - # implementation: clean - # sources: ['blas_comm.c', 'parallel_matrix_op.c', 'rainbow.c', 'rainbow_keypair.c', 'rainbow_keypair_computation.c', 'sign.c', 'utils_hash.c', 'utils_prng.c', 'blas_u32.c', 'gf.c'] - # signed_msg_order: msg_then_sig - # - - # scheme: "Ia_cyclic_compressed" - # pqclean_scheme: rainbowIa-cyclic-compressed - # pretty_name_full: Rainbow-Ia-Cyclic-Compressed - # implementation: clean - # sources: ['blas_comm.c', 'parallel_matrix_op.c', 'rainbow.c', 'rainbow_keypair.c', 'rainbow_keypair_computation.c', 'sign.c', 'utils_hash.c', 'utils_prng.c', 'blas_u32.c', 'gf.c'] - # signed_msg_order: msg_then_sig - # - - # scheme: "IIIc_classic" - # pqclean_scheme: rainbowIIIc-classic - # pretty_name_full: Rainbow-IIIc-Classic - # implementation: clean - # sources: ['blas_comm.c', 'parallel_matrix_op.c', 'rainbow.c', 'rainbow_keypair.c', 'rainbow_keypair_computation.c', 'sign.c', 'utils_hash.c', 'utils_prng.c', 'blas_u32.c', 'gf.c'] - # signed_msg_order: msg_then_sig - # - - # scheme: "IIIc_cyclic" - # pqclean_scheme: rainbowIIIc-cyclic - # pretty_name_full: Rainbow-IIIc-Cyclic - # implementation: clean - # sources: ['blas_comm.c', 'parallel_matrix_op.c', 'rainbow.c', 'rainbow_keypair.c', 'rainbow_keypair_computation.c', 'sign.c', 'utils_hash.c', 'utils_prng.c', 'blas_u32.c', 'gf.c'] - # signed_msg_order: msg_then_sig - # - - # scheme: "IIIc_cyclic_compressed" - # pqclean_scheme: rainbowIIIc-cyclic-compressed - # pretty_name_full: Rainbow-IIIc-Cyclic-Compressed - # implementation: clean - # sources: ['blas_comm.c', 'parallel_matrix_op.c', 'rainbow.c', 'rainbow_keypair.c', 'rainbow_keypair_computation.c', 'sign.c', 'utils_hash.c', 'utils_prng.c', 'blas_u32.c', 'gf.c'] - # signed_msg_order: msg_then_sig - # - - # scheme: "Vc_classic" - # pqclean_scheme: rainbowVc-classic - # pretty_name_full: Rainbow-Vc-Classic - # implementation: clean - # sources: ['blas_comm.c', 'parallel_matrix_op.c', 'rainbow.c', 'rainbow_keypair.c', 'rainbow_keypair_computation.c', 'sign.c', 'utils_hash.c', 'utils_prng.c', 'blas_u32.c', 'gf.c'] - # signed_msg_order: msg_then_sig - # - - # scheme: "Vc_cyclic" - # pqclean_scheme: rainbowVc-cyclic - # pretty_name_full: Rainbow-Vc-Cyclic - # implementation: clean - # sources: ['blas_comm.c', 'parallel_matrix_op.c', 'rainbow.c', 'rainbow_keypair.c', 'rainbow_keypair_computation.c', 'sign.c', 'utils_hash.c', 'utils_prng.c', 'blas_u32.c', 'gf.c'] - # signed_msg_order: msg_then_sig - # - - # scheme: "Vc_cyclic_compressed" - # pqclean_scheme: rainbowVc-cyclic-compressed - # pretty_name_full: Rainbow-Vc-Cyclic-Compressed - # implementation: clean - # sources: ['blas_comm.c', 'parallel_matrix_op.c', 'rainbow.c', 'rainbow_keypair.c', 'rainbow_keypair_computation.c', 'sign.c', 'utils_hash.c', 'utils_prng.c', 'blas_u32.c', 'gf.c'] - # signed_msg_order: msg_then_sig + - + name: rainbow + schemes: + - + scheme: "Ia_classic" + pqclean_scheme: rainbowIa-classic + pretty_name_full: Rainbow-Ia-Classic + implementation: clean + sources: ['blas_comm.c', 'parallel_matrix_op.c', 'rainbow.c', 'rainbow_keypair.c', 'rainbow_keypair_computation.c', 'sign.c', 'utils_hash.c', 'utils_prng.c', 'blas.c', 'gf.c'] + signed_msg_order: msg_then_sig + - + scheme: "Ia_cyclic" + pqclean_scheme: rainbowIa-cyclic + pretty_name_full: Rainbow-Ia-Cyclic + implementation: clean + sources: ['blas_comm.c', 'parallel_matrix_op.c', 'rainbow.c', 'rainbow_keypair.c', 'rainbow_keypair_computation.c', 'sign.c', 'utils_hash.c', 'utils_prng.c', 'blas.c', 'gf.c'] + signed_msg_order: msg_then_sig + - + scheme: "Ia_cyclic_compressed" + pqclean_scheme: rainbowIa-cyclic-compressed + pretty_name_full: Rainbow-Ia-Cyclic-Compressed + implementation: clean + sources: ['blas_comm.c', 'parallel_matrix_op.c', 'rainbow.c', 'rainbow_keypair.c', 'rainbow_keypair_computation.c', 'sign.c', 'utils_hash.c', 'utils_prng.c', 'blas.c', 'gf.c'] + signed_msg_order: msg_then_sig + - + scheme: "IIIc_classic" + pqclean_scheme: rainbowIIIc-classic + pretty_name_full: Rainbow-IIIc-Classic + implementation: clean + sources: ['blas_comm.c', 'parallel_matrix_op.c', 'rainbow.c', 'rainbow_keypair.c', 'rainbow_keypair_computation.c', 'sign.c', 'utils_hash.c', 'utils_prng.c', 'blas.c', 'gf.c'] + signed_msg_order: msg_then_sig + - + scheme: "IIIc_cyclic" + pqclean_scheme: rainbowIIIc-cyclic + pretty_name_full: Rainbow-IIIc-Cyclic + implementation: clean + sources: ['blas_comm.c', 'parallel_matrix_op.c', 'rainbow.c', 'rainbow_keypair.c', 'rainbow_keypair_computation.c', 'sign.c', 'utils_hash.c', 'utils_prng.c', 'blas.c', 'gf.c'] + signed_msg_order: msg_then_sig + - + scheme: "IIIc_cyclic_compressed" + pqclean_scheme: rainbowIIIc-cyclic-compressed + pretty_name_full: Rainbow-IIIc-Cyclic-Compressed + implementation: clean + sources: ['blas_comm.c', 'parallel_matrix_op.c', 'rainbow.c', 'rainbow_keypair.c', 'rainbow_keypair_computation.c', 'sign.c', 'utils_hash.c', 'utils_prng.c', 'blas.c', 'gf.c'] + signed_msg_order: msg_then_sig + - + scheme: "Vc_classic" + pqclean_scheme: rainbowVc-classic + pretty_name_full: Rainbow-Vc-Classic + implementation: clean + sources: ['blas_comm.c', 'parallel_matrix_op.c', 'rainbow.c', 'rainbow_keypair.c', 'rainbow_keypair_computation.c', 'sign.c', 'utils_hash.c', 'utils_prng.c', 'blas.c', 'gf.c'] + signed_msg_order: msg_then_sig + - + scheme: "Vc_cyclic" + pqclean_scheme: rainbowVc-cyclic + pretty_name_full: Rainbow-Vc-Cyclic + implementation: clean + sources: ['blas_comm.c', 'parallel_matrix_op.c', 'rainbow.c', 'rainbow_keypair.c', 'rainbow_keypair_computation.c', 'sign.c', 'utils_hash.c', 'utils_prng.c', 'blas.c', 'gf.c'] + signed_msg_order: msg_then_sig + - + scheme: "Vc_cyclic_compressed" + pqclean_scheme: rainbowVc-cyclic-compressed + pretty_name_full: Rainbow-Vc-Cyclic-Compressed + implementation: clean + sources: ['blas_comm.c', 'parallel_matrix_op.c', 'rainbow.c', 'rainbow_keypair.c', 'rainbow_keypair_computation.c', 'sign.c', 'utils_hash.c', 'utils_prng.c', 'blas.c', 'gf.c'] + signed_msg_order: msg_then_sig - name: sphincs schemes: diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a6e5f17302..cf03a23b38 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -59,6 +59,10 @@ if(OQS_ENABLE_SIG_MQDSS) add_subdirectory(sig/mqdss) set(SIG_OBJS ${SIG_OBJS} $) endif() +if(OQS_ENABLE_SIG_RAINBOW) + add_subdirectory(sig/rainbow) + set(SIG_OBJS ${SIG_OBJS} $) +endif() if(OQS_ENABLE_SIG_SPHINCS) add_subdirectory(sig/sphincs) set(SIG_OBJS ${SIG_OBJS} $) diff --git a/src/oqsconfig.h.cmake b/src/oqsconfig.h.cmake index 8a2f82656b..58686b4e8e 100644 --- a/src/oqsconfig.h.cmake +++ b/src/oqsconfig.h.cmake @@ -135,6 +135,17 @@ #cmakedefine OQS_ENABLE_SIG_mqdss_31_48 1 #cmakedefine OQS_ENABLE_SIG_mqdss_31_64 1 +#cmakedefine OQS_ENABLE_SIG_RAINBOW +#cmakedefine OQS_ENABLE_SIG_rainbow_Ia_classic 1 +#cmakedefine OQS_ENABLE_SIG_rainbow_Ia_cyclic 1 +#cmakedefine OQS_ENABLE_SIG_rainbow_Ia_cyclic_compressed 1 +#cmakedefine OQS_ENABLE_SIG_rainbow_IIIc_classic 1 +#cmakedefine OQS_ENABLE_SIG_rainbow_IIIc_cyclic 1 +#cmakedefine OQS_ENABLE_SIG_rainbow_IIIc_cyclic_compressed 1 +#cmakedefine OQS_ENABLE_SIG_rainbow_Vc_classic 1 +#cmakedefine OQS_ENABLE_SIG_rainbow_Vc_cyclic 1 +#cmakedefine OQS_ENABLE_SIG_rainbow_Vc_cyclic_compressed 1 + #cmakedefine OQS_ENABLE_SIG_SPHINCS #cmakedefine OQS_ENABLE_SIG_sphincs_haraka_128f_robust 1 #cmakedefine OQS_ENABLE_SIG_sphincs_haraka_128f_simple 1 diff --git a/src/sig/rainbow/CMakeLists.txt b/src/sig/rainbow/CMakeLists.txt new file mode 100644 index 0000000000..d77b6470c3 --- /dev/null +++ b/src/sig/rainbow/CMakeLists.txt @@ -0,0 +1,32 @@ +# This file was generated by +# scripts/copy_from_pqclean/copy_from_pqclean.py +if(OQS_ENABLE_SIG_rainbow_Ia_classic) + set(SRCS ${SRCS} sig_rainbow_Ia_classic.c pqclean_rainbowIa-classic_clean/blas_comm.c pqclean_rainbowIa-classic_clean/parallel_matrix_op.c pqclean_rainbowIa-classic_clean/rainbow.c pqclean_rainbowIa-classic_clean/rainbow_keypair.c pqclean_rainbowIa-classic_clean/rainbow_keypair_computation.c pqclean_rainbowIa-classic_clean/sign.c pqclean_rainbowIa-classic_clean/utils_hash.c pqclean_rainbowIa-classic_clean/utils_prng.c pqclean_rainbowIa-classic_clean/blas.c pqclean_rainbowIa-classic_clean/gf.c) +endif() +if(OQS_ENABLE_SIG_rainbow_Ia_cyclic) + set(SRCS ${SRCS} sig_rainbow_Ia_cyclic.c pqclean_rainbowIa-cyclic_clean/blas_comm.c pqclean_rainbowIa-cyclic_clean/parallel_matrix_op.c pqclean_rainbowIa-cyclic_clean/rainbow.c pqclean_rainbowIa-cyclic_clean/rainbow_keypair.c pqclean_rainbowIa-cyclic_clean/rainbow_keypair_computation.c pqclean_rainbowIa-cyclic_clean/sign.c pqclean_rainbowIa-cyclic_clean/utils_hash.c pqclean_rainbowIa-cyclic_clean/utils_prng.c pqclean_rainbowIa-cyclic_clean/blas.c pqclean_rainbowIa-cyclic_clean/gf.c) +endif() +if(OQS_ENABLE_SIG_rainbow_Ia_cyclic_compressed) + set(SRCS ${SRCS} sig_rainbow_Ia_cyclic_compressed.c pqclean_rainbowIa-cyclic-compressed_clean/blas_comm.c pqclean_rainbowIa-cyclic-compressed_clean/parallel_matrix_op.c pqclean_rainbowIa-cyclic-compressed_clean/rainbow.c pqclean_rainbowIa-cyclic-compressed_clean/rainbow_keypair.c pqclean_rainbowIa-cyclic-compressed_clean/rainbow_keypair_computation.c pqclean_rainbowIa-cyclic-compressed_clean/sign.c pqclean_rainbowIa-cyclic-compressed_clean/utils_hash.c pqclean_rainbowIa-cyclic-compressed_clean/utils_prng.c pqclean_rainbowIa-cyclic-compressed_clean/blas.c pqclean_rainbowIa-cyclic-compressed_clean/gf.c) +endif() +if(OQS_ENABLE_SIG_rainbow_IIIc_classic) + set(SRCS ${SRCS} sig_rainbow_IIIc_classic.c pqclean_rainbowIIIc-classic_clean/blas_comm.c pqclean_rainbowIIIc-classic_clean/parallel_matrix_op.c pqclean_rainbowIIIc-classic_clean/rainbow.c pqclean_rainbowIIIc-classic_clean/rainbow_keypair.c pqclean_rainbowIIIc-classic_clean/rainbow_keypair_computation.c pqclean_rainbowIIIc-classic_clean/sign.c pqclean_rainbowIIIc-classic_clean/utils_hash.c pqclean_rainbowIIIc-classic_clean/utils_prng.c pqclean_rainbowIIIc-classic_clean/blas.c pqclean_rainbowIIIc-classic_clean/gf.c) +endif() +if(OQS_ENABLE_SIG_rainbow_IIIc_cyclic) + set(SRCS ${SRCS} sig_rainbow_IIIc_cyclic.c pqclean_rainbowIIIc-cyclic_clean/blas_comm.c pqclean_rainbowIIIc-cyclic_clean/parallel_matrix_op.c pqclean_rainbowIIIc-cyclic_clean/rainbow.c pqclean_rainbowIIIc-cyclic_clean/rainbow_keypair.c pqclean_rainbowIIIc-cyclic_clean/rainbow_keypair_computation.c pqclean_rainbowIIIc-cyclic_clean/sign.c pqclean_rainbowIIIc-cyclic_clean/utils_hash.c pqclean_rainbowIIIc-cyclic_clean/utils_prng.c pqclean_rainbowIIIc-cyclic_clean/blas.c pqclean_rainbowIIIc-cyclic_clean/gf.c) +endif() +if(OQS_ENABLE_SIG_rainbow_IIIc_cyclic_compressed) + set(SRCS ${SRCS} sig_rainbow_IIIc_cyclic_compressed.c pqclean_rainbowIIIc-cyclic-compressed_clean/blas_comm.c pqclean_rainbowIIIc-cyclic-compressed_clean/parallel_matrix_op.c pqclean_rainbowIIIc-cyclic-compressed_clean/rainbow.c pqclean_rainbowIIIc-cyclic-compressed_clean/rainbow_keypair.c pqclean_rainbowIIIc-cyclic-compressed_clean/rainbow_keypair_computation.c pqclean_rainbowIIIc-cyclic-compressed_clean/sign.c pqclean_rainbowIIIc-cyclic-compressed_clean/utils_hash.c pqclean_rainbowIIIc-cyclic-compressed_clean/utils_prng.c pqclean_rainbowIIIc-cyclic-compressed_clean/blas.c pqclean_rainbowIIIc-cyclic-compressed_clean/gf.c) +endif() +if(OQS_ENABLE_SIG_rainbow_Vc_classic) + set(SRCS ${SRCS} sig_rainbow_Vc_classic.c pqclean_rainbowVc-classic_clean/blas_comm.c pqclean_rainbowVc-classic_clean/parallel_matrix_op.c pqclean_rainbowVc-classic_clean/rainbow.c pqclean_rainbowVc-classic_clean/rainbow_keypair.c pqclean_rainbowVc-classic_clean/rainbow_keypair_computation.c pqclean_rainbowVc-classic_clean/sign.c pqclean_rainbowVc-classic_clean/utils_hash.c pqclean_rainbowVc-classic_clean/utils_prng.c pqclean_rainbowVc-classic_clean/blas.c pqclean_rainbowVc-classic_clean/gf.c) +endif() +if(OQS_ENABLE_SIG_rainbow_Vc_cyclic) + set(SRCS ${SRCS} sig_rainbow_Vc_cyclic.c pqclean_rainbowVc-cyclic_clean/blas_comm.c pqclean_rainbowVc-cyclic_clean/parallel_matrix_op.c pqclean_rainbowVc-cyclic_clean/rainbow.c pqclean_rainbowVc-cyclic_clean/rainbow_keypair.c pqclean_rainbowVc-cyclic_clean/rainbow_keypair_computation.c pqclean_rainbowVc-cyclic_clean/sign.c pqclean_rainbowVc-cyclic_clean/utils_hash.c pqclean_rainbowVc-cyclic_clean/utils_prng.c pqclean_rainbowVc-cyclic_clean/blas.c pqclean_rainbowVc-cyclic_clean/gf.c) +endif() +if(OQS_ENABLE_SIG_rainbow_Vc_cyclic_compressed) + set(SRCS ${SRCS} sig_rainbow_Vc_cyclic_compressed.c pqclean_rainbowVc-cyclic-compressed_clean/blas_comm.c pqclean_rainbowVc-cyclic-compressed_clean/parallel_matrix_op.c pqclean_rainbowVc-cyclic-compressed_clean/rainbow.c pqclean_rainbowVc-cyclic-compressed_clean/rainbow_keypair.c pqclean_rainbowVc-cyclic-compressed_clean/rainbow_keypair_computation.c pqclean_rainbowVc-cyclic-compressed_clean/sign.c pqclean_rainbowVc-cyclic-compressed_clean/utils_hash.c pqclean_rainbowVc-cyclic-compressed_clean/utils_prng.c pqclean_rainbowVc-cyclic-compressed_clean/blas.c pqclean_rainbowVc-cyclic-compressed_clean/gf.c) +endif() + +add_library(rainbow OBJECT ${SRCS}) +target_include_directories(rainbow PRIVATE ${PROJECT_SOURCE_DIR}/src/common/pqclean_shims) \ No newline at end of file diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/LICENSE b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/LICENSE new file mode 100644 index 0000000000..cb00a6e354 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/LICENSE @@ -0,0 +1,8 @@ +`Software implementation of Rainbow for NIST R2 submission' by Ming-Shing Chen + +To the extent possible under law, the person who associated CC0 with +`Software implementation of Rainbow for NIST R2 submission' has waived all copyright and related or neighboring rights +to `Software implementation of Rainbow for NIST R2 submission'. + +You should have received a copy of the CC0 legalcode along with this +work. If not, see . diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/api.h b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/api.h new file mode 100644 index 0000000000..9dc88a7d82 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/api.h @@ -0,0 +1,32 @@ +#ifndef PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_API_H +#define PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_API_H + +#include +#include + +#define PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_CRYPTO_SECRETKEYBYTES 511448 +#define PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_CRYPTO_PUBLICKEYBYTES 710640 +#define PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_CRYPTO_BYTES 156 +#define PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_CRYPTO_ALGNAME "RAINBOW(256,68,36,36) - classic" + +int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + + +int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_crypto_sign_signature( + uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_crypto_sign_verify( + const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + + +#endif diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/blas.c b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/blas.c new file mode 100644 index 0000000000..5e14d7bd4c --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/blas.c @@ -0,0 +1,31 @@ +#include "blas.h" +#include "gf.h" + +#include + +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_predicated_add(uint8_t *accu_b, uint8_t predicate, const uint8_t *a, size_t _num_byte) { + uint8_t pr_u8 = (uint8_t) ((uint8_t) 0 - predicate); + for (size_t i = 0; i < _num_byte; i++) { + accu_b[i] ^= (a[i] & pr_u8); + } +} + +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_add(uint8_t *accu_b, const uint8_t *a, size_t _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + accu_b[i] ^= a[i]; + } +} + + +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_mul_scalar(uint8_t *a, uint8_t b, size_t _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + a[i] = PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256_mul(a[i], b); + } +} + +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_madd(uint8_t *accu_c, const uint8_t *a, uint8_t gf256_b, size_t _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + accu_c[i] ^= PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256_mul(a[i], gf256_b); + } +} + diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/blas.h b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/blas.h new file mode 100644 index 0000000000..da4eda640d --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/blas.h @@ -0,0 +1,19 @@ +#ifndef _BLAS_H_ +#define _BLAS_H_ +/// @file blas.h +/// @brief Functions for implementing basic linear algebra functions. +/// + +#include "rainbow_config.h" +#include +#include + +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_predicated_add(uint8_t *accu_b, uint8_t predicate, const uint8_t *a, size_t _num_byte); +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_add(uint8_t *accu_b, const uint8_t *a, size_t _num_byte); + + +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_mul_scalar(uint8_t *a, uint8_t b, size_t _num_byte); +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_madd(uint8_t *accu_c, const uint8_t *a, uint8_t gf256_b, size_t _num_byte); + + +#endif // _BLAS_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/blas_comm.c b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/blas_comm.c new file mode 100644 index 0000000000..ad2b31ff5c --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/blas_comm.c @@ -0,0 +1,144 @@ +/// @file blas_comm.c +/// @brief The standard implementations for blas_comm.h +/// + +#include "blas_comm.h" +#include "blas.h" +#include "gf.h" +#include "rainbow_config.h" + +#include +#include + +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_set_zero(uint8_t *b, unsigned int _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + b[i] = 0; + } +} +/// @brief get an element from GF(256) vector . +/// +/// @param[in] a - the input vector a. +/// @param[in] i - the index in the vector a. +/// @return the value of the element. +/// +uint8_t PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_get_ele(const uint8_t *a, unsigned int i) { + return a[i]; +} + +unsigned int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_is_zero(const uint8_t *a, unsigned int _num_byte) { + uint8_t r = 0; + while (_num_byte--) { + r |= a[0]; + a++; + } + return (0 == r); +} + +/// polynomial multplication +/// School boook +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_polymul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int _num) { + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_set_zero(c, _num * 2 - 1); + for (unsigned int i = 0; i < _num; i++) { + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_madd(c + i, a, b[i], _num); + } +} + +static void gf256mat_prod_ref(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b) { + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_set_zero(c, n_A_vec_byte); + for (unsigned int i = 0; i < n_A_width; i++) { + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_madd(c, matA, b[i], n_A_vec_byte); + matA += n_A_vec_byte; + } +} + +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256mat_mul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int len_vec) { + unsigned int n_vec_byte = len_vec; + for (unsigned int k = 0; k < len_vec; k++) { + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_set_zero(c, n_vec_byte); + const uint8_t *bk = b + n_vec_byte * k; + for (unsigned int i = 0; i < len_vec; i++) { + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_madd(c, a + n_vec_byte * i, bk[i], n_vec_byte); + } + c += n_vec_byte; + } +} + +static unsigned int gf256mat_gauss_elim_ref(uint8_t *mat, unsigned int h, unsigned int w) { + unsigned int r8 = 1; + + for (unsigned int i = 0; i < h; i++) { + uint8_t *ai = mat + w * i; + unsigned int skip_len_align4 = i & ((unsigned int)~0x3); + + for (unsigned int j = i + 1; j < h; j++) { + uint8_t *aj = mat + w * j; + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_predicated_add(ai + skip_len_align4, !PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256_is_nonzero(ai[i]), aj + skip_len_align4, w - skip_len_align4); + } + r8 &= PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256_is_nonzero(ai[i]); + uint8_t pivot = ai[i]; + pivot = PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256_inv(pivot); + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_mul_scalar(ai + skip_len_align4, pivot, w - skip_len_align4); + for (unsigned int j = 0; j < h; j++) { + if (i == j) { + continue; + } + uint8_t *aj = mat + w * j; + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_madd(aj + skip_len_align4, ai + skip_len_align4, aj[i], w - skip_len_align4); + } + } + + return r8; +} + +static unsigned int gf256mat_solve_linear_eq_ref(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n) { + uint8_t mat[64 * 64]; + for (unsigned int i = 0; i < n; i++) { + memcpy(mat + i * (n + 1), inp_mat + i * n, n); + mat[i * (n + 1) + n] = c_terms[i]; + } + unsigned int r8 = PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256mat_gauss_elim(mat, n, n + 1); + for (unsigned int i = 0; i < n; i++) { + sol[i] = mat[i * (n + 1) + n]; + } + return r8; +} + +static inline void gf256mat_submat(uint8_t *mat2, unsigned int w2, unsigned int st, const uint8_t *mat, unsigned int w, unsigned int h) { + for (unsigned int i = 0; i < h; i++) { + for (unsigned int j = 0; j < w2; j++) { + mat2[i * w2 + j] = mat[i * w + st + j]; + } + } +} + +unsigned int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256mat_inv(uint8_t *inv_a, const uint8_t *a, unsigned int H, uint8_t *buffer) { + uint8_t *aa = buffer; + for (unsigned int i = 0; i < H; i++) { + uint8_t *ai = aa + i * 2 * H; + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_set_zero(ai, 2 * H); + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_add(ai, a + i * H, H); + ai[H + i] = 1; + } + unsigned int r8 = PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256mat_gauss_elim(aa, H, 2 * H); + gf256mat_submat(inv_a, H, H, aa, 2 * H, H); + return r8; +} + + +// choosing the implementations depends on the macros _BLAS_AVX2_ and _BLAS_SSE + +#define gf256mat_prod_impl gf256mat_prod_ref +#define gf256mat_gauss_elim_impl gf256mat_gauss_elim_ref +#define gf256mat_solve_linear_eq_impl gf256mat_solve_linear_eq_ref +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256mat_prod(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b) { + gf256mat_prod_impl(c, matA, n_A_vec_byte, n_A_width, b); +} + +unsigned int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256mat_gauss_elim(uint8_t *mat, unsigned int h, unsigned int w) { + return gf256mat_gauss_elim_impl(mat, h, w); +} + +unsigned int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256mat_solve_linear_eq(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n) { + return gf256mat_solve_linear_eq_impl(sol, inp_mat, c_terms, n); +} + diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/blas_comm.h b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/blas_comm.h new file mode 100644 index 0000000000..6357c0ab22 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/blas_comm.h @@ -0,0 +1,90 @@ +#ifndef _BLAS_COMM_H_ +#define _BLAS_COMM_H_ +/// @file blas_comm.h +/// @brief Common functions for linear algebra. +/// + +#include "rainbow_config.h" +#include + +/// @brief set a vector to 0. +/// +/// @param[in,out] b - the vector b. +/// @param[in] _num_byte - number of bytes for the vector b. +/// +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_set_zero(uint8_t *b, unsigned int _num_byte); + +/// @brief get an element from GF(256) vector . +/// +/// @param[in] a - the input vector a. +/// @param[in] i - the index in the vector a. +/// @return the value of the element. +/// +uint8_t PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_get_ele(const uint8_t *a, unsigned int i); + +/// @brief check if a vector is 0. +/// +/// @param[in] a - the vector a. +/// @param[in] _num_byte - number of bytes for the vector a. +/// @return 1(true) if a is 0. 0(false) else. +/// +unsigned int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_is_zero(const uint8_t *a, unsigned int _num_byte); + +/// @brief polynomial multiplication: c = a*b +/// +/// @param[out] c - the output polynomial c +/// @param[in] a - the vector a. +/// @param[in] b - the vector b. +/// @param[in] _num - number of elements for the polynomials a and b. +/// +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_polymul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int _num); + +/// @brief matrix-vector multiplication: c = matA * b , in GF(256) +/// +/// @param[out] c - the output vector c +/// @param[in] matA - a column-major matrix A. +/// @param[in] n_A_vec_byte - the size of column vectors in bytes. +/// @param[in] n_A_width - the width of matrix A. +/// @param[in] b - the vector b. +/// +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256mat_prod(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b); + +/// @brief matrix-matrix multiplication: c = a * b , in GF(256) +/// +/// @param[out] c - the output matrix c +/// @param[in] c - a matrix a. +/// @param[in] b - a matrix b. +/// @param[in] len_vec - the length of column vectors. +/// +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256mat_mul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int len_vec); + +/// @brief Gauss elimination for a matrix, in GF(256) +/// +/// @param[in,out] mat - the matrix. +/// @param[in] h - the height of the matrix. +/// @param[in] w - the width of the matrix. +/// @return 1(true) if success. 0(false) if the matrix is singular. +/// +unsigned int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256mat_gauss_elim(uint8_t *mat, unsigned int h, unsigned int w); + +/// @brief Solving linear equations, in GF(256) +/// +/// @param[out] sol - the solutions. +/// @param[in] inp_mat - the matrix parts of input equations. +/// @param[in] c_terms - the constant terms of the input equations. +/// @param[in] n - the number of equations. +/// @return 1(true) if success. 0(false) if the matrix is singular. +/// +unsigned int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256mat_solve_linear_eq(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n); + +/// @brief Computing the inverse matrix, in GF(256) +/// +/// @param[out] inv_a - the output of matrix a. +/// @param[in] a - a matrix a. +/// @param[in] H - height of matrix a, i.e., matrix a is an HxH matrix. +/// @param[in] buffer - The buffer for computations. it has to be as large as 2 input matrixes. +/// @return 1(true) if success. 0(false) if the matrix is singular. +/// +unsigned int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256mat_inv(uint8_t *inv_a, const uint8_t *a, unsigned int H, uint8_t *buffer); + +#endif // _BLAS_COMM_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/gf.c b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/gf.c new file mode 100644 index 0000000000..130e193f82 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/gf.c @@ -0,0 +1,91 @@ +#include "gf.h" + +//// gf4 := gf2[x]/x^2+x+1 +static inline uint8_t gf4_mul_2(uint8_t a) { + uint8_t r = (uint8_t)(a << 1); + r ^= (uint8_t)((a >> 1) * 7); + return r; +} + +static inline uint8_t gf4_mul(uint8_t a, uint8_t b) { + uint8_t r = (uint8_t)(a * (b & 1)); + return r ^ (uint8_t)(gf4_mul_2(a) * (b >> 1)); +} + +static inline uint8_t gf4_squ(uint8_t a) { + return a ^ (a >> 1); +} + +//// gf16 := gf4[y]/y^2+y+x +uint8_t PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf16_mul(uint8_t a, uint8_t b) { + uint8_t a0 = a & 3; + uint8_t a1 = (a >> 2); + uint8_t b0 = b & 3; + uint8_t b1 = (b >> 2); + uint8_t a0b0 = gf4_mul(a0, b0); + uint8_t a1b1 = gf4_mul(a1, b1); + uint8_t a0b1_a1b0 = gf4_mul(a0 ^ a1, b0 ^ b1) ^ a0b0 ^ a1b1; + uint8_t a1b1_x2 = gf4_mul_2(a1b1); + return (uint8_t)((a0b1_a1b0 ^ a1b1) << 2 ^ a0b0 ^ a1b1_x2); +} + +static inline uint8_t gf16_squ(uint8_t a) { + uint8_t a0 = a & 3; + uint8_t a1 = (a >> 2); + a1 = gf4_squ(a1); + uint8_t a1squ_x2 = gf4_mul_2(a1); + return (uint8_t)((a1 << 2) ^ a1squ_x2 ^ gf4_squ(a0)); +} + +uint8_t PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256_is_nonzero(uint8_t a) { + unsigned int a8 = a; + unsigned int r = ((unsigned int)0) - a8; + r >>= 8; + return r & 1; +} + +static inline uint8_t gf4_mul_3(uint8_t a) { + uint8_t msk = (uint8_t)((a - 2) >> 1); + return (uint8_t)((msk & ((int)a * 3)) | ((~msk) & ((int)a - 1))); +} +static inline uint8_t gf16_mul_8(uint8_t a) { + uint8_t a0 = a & 3; + uint8_t a1 = a >> 2; + return (uint8_t)((gf4_mul_2(a0 ^ a1) << 2) | gf4_mul_3(a1)); +} + +// gf256 := gf16[X]/X^2+X+xy +uint8_t PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256_mul(uint8_t a, uint8_t b) { + uint8_t a0 = a & 15; + uint8_t a1 = (a >> 4); + uint8_t b0 = b & 15; + uint8_t b1 = (b >> 4); + uint8_t a0b0 = PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf16_mul(a0, b0); + uint8_t a1b1 = PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf16_mul(a1, b1); + uint8_t a0b1_a1b0 = PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf16_mul(a0 ^ a1, b0 ^ b1) ^ a0b0 ^ a1b1; + uint8_t a1b1_x8 = gf16_mul_8(a1b1); + return (uint8_t)((a0b1_a1b0 ^ a1b1) << 4 ^ a0b0 ^ a1b1_x8); +} + +static inline uint8_t gf256_squ(uint8_t a) { + uint8_t a0 = a & 15; + uint8_t a1 = (a >> 4); + a1 = gf16_squ(a1); + uint8_t a1squ_x8 = gf16_mul_8(a1); + return (uint8_t)((a1 << 4) ^ a1squ_x8 ^ gf16_squ(a0)); +} + +uint8_t PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256_inv(uint8_t a) { + // 128+64+32+16+8+4+2 = 254 + uint8_t a2 = gf256_squ(a); + uint8_t a4 = gf256_squ(a2); + uint8_t a8 = gf256_squ(a4); + uint8_t a4_2 = PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256_mul(a4, a2); + uint8_t a8_4_2 = PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256_mul(a4_2, a8); + uint8_t a64_ = gf256_squ(a8_4_2); + a64_ = gf256_squ(a64_); + a64_ = gf256_squ(a64_); + uint8_t a64_2 = PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256_mul(a64_, a8_4_2); + uint8_t a128_ = gf256_squ(a64_2); + return PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256_mul(a2, a128_); +} diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/gf.h b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/gf.h new file mode 100644 index 0000000000..92d72be02a --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/gf.h @@ -0,0 +1,19 @@ +#ifndef _GF16_H_ +#define _GF16_H_ + +#include "rainbow_config.h" +#include + +/// @file gf16.h +/// @brief Library for arithmetics in GF(16) and GF(256) +/// + +uint8_t PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf16_mul(uint8_t a, uint8_t b); + + +uint8_t PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256_is_nonzero(uint8_t a); +uint8_t PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256_inv(uint8_t a); +uint8_t PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256_mul(uint8_t a, uint8_t b); + + +#endif // _GF16_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/parallel_matrix_op.c b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/parallel_matrix_op.c new file mode 100644 index 0000000000..5dc73ab322 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/parallel_matrix_op.c @@ -0,0 +1,183 @@ +/// @file parallel_matrix_op.c +/// @brief the standard implementations for functions in parallel_matrix_op.h +/// +/// the standard implementations for functions in parallel_matrix_op.h +/// + +#include "parallel_matrix_op.h" +#include "blas.h" +#include "blas_comm.h" + +/// +/// @brief Calculate the corresponding index in an array for an upper-triangle(UT) matrix. +/// +/// @param[in] i_row - the i-th row in an upper-triangle matrix. +/// @param[in] j_col - the j-th column in an upper-triangle matrix. +/// @param[in] dim - the dimension of the upper-triangle matrix, i.e., an dim x dim matrix. +/// @return the corresponding index in an array storage. +/// +unsigned int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_idx_of_trimat(unsigned int i_row, unsigned int j_col, unsigned int dim) { + return (dim + dim - i_row + 1) * i_row / 2 + j_col - i_row; +} + +/// +/// @brief Calculate the corresponding index in an array for an upper-triangle or lower-triangle matrix. +/// +/// @param[in] i_row - the i-th row in a triangle matrix. +/// @param[in] j_col - the j-th column in a triangle matrix. +/// @param[in] dim - the dimension of the triangle matrix, i.e., an dim x dim matrix. +/// @return the corresponding index in an array storage. +/// +static inline unsigned int idx_of_2trimat(unsigned int i_row, unsigned int j_col, unsigned int n_var) { + if (i_row > j_col) { + return PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_idx_of_trimat(j_col, i_row, n_var); + } + return PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_idx_of_trimat(i_row, j_col, n_var); +} + +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_UpperTrianglize(unsigned char *btriC, const unsigned char *bA, unsigned int Awidth, unsigned int size_batch) { + unsigned char *runningC = btriC; + unsigned int Aheight = Awidth; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < i; j++) { + unsigned int idx = PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_idx_of_trimat(j, i, Aheight); + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_add(btriC + idx * size_batch, bA + size_batch * (i * Awidth + j), size_batch); + } + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_add(runningC, bA + size_batch * (i * Awidth + i), size_batch * (Aheight - i)); + runningC += size_batch * (Aheight - i); + } +} + +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Awidth = Bheight; + unsigned int Aheight = Awidth; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + if (k < i) { + continue; + } + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_madd(bC, &btriA[(k - i) * size_batch], PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + btriA += (Aheight - i) * size_batch; + } +} + +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_trimatTr_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Aheight = Bheight; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + if (i < k) { + continue; + } + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_madd(bC, &btriA[size_batch * (PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_idx_of_trimat(k, i, Aheight))], PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_2trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Aheight = Bheight; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + if (i == k) { + continue; + } + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_madd(bC, &btriA[size_batch * (idx_of_2trimat(i, k, Aheight))], PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_matTr_madd_gf256(unsigned char *bC, const unsigned char *A_to_tr, unsigned int Aheight, unsigned int size_Acolvec, unsigned int Awidth, + const unsigned char *bB, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Atr_height = Awidth; + unsigned int Atr_width = Aheight; + for (unsigned int i = 0; i < Atr_height; i++) { + for (unsigned int j = 0; j < Atr_width; j++) { + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_madd(bC, &bB[j * Bwidth * size_batch], PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_get_ele(&A_to_tr[size_Acolvec * i], j), size_batch * Bwidth); + } + bC += size_batch * Bwidth; + } +} + +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_bmatTr_madd_gf256(unsigned char *bC, const unsigned char *bA_to_tr, unsigned int Awidth_before_tr, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + const unsigned char *bA = bA_to_tr; + unsigned int Aheight = Awidth_before_tr; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_madd(bC, &bA[size_batch * (i + k * Aheight)], PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_mat_madd_gf256(unsigned char *bC, const unsigned char *bA, unsigned int Aheight, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Awidth = Bheight; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_madd(bC, &bA[k * size_batch], PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + bA += (Awidth) * size_batch; + } +} + +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_quad_trimat_eval_gf256(unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned int dim, unsigned int size_batch) { + unsigned char tmp[256]; + + unsigned char _x[256]; + for (unsigned int i = 0; i < dim; i++) { + _x[i] = PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_get_ele(x, i); + } + + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_set_zero(y, size_batch); + for (unsigned int i = 0; i < dim; i++) { + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_set_zero(tmp, size_batch); + for (unsigned int j = i; j < dim; j++) { + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_madd(tmp, trimat, _x[j], size_batch); + trimat += size_batch; + } + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_madd(y, tmp, _x[i], size_batch); + } +} + +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_quad_recmat_eval_gf256(unsigned char *z, const unsigned char *y, unsigned int dim_y, const unsigned char *mat, + const unsigned char *x, unsigned dim_x, unsigned size_batch) { + unsigned char tmp[128]; + + unsigned char _x[128]; + for (unsigned int i = 0; i < dim_x; i++) { + _x[i] = PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_get_ele(x, i); + } + unsigned char _y[128]; + for (unsigned int i = 0; i < dim_y; i++) { + _y[i] = PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_get_ele(y, i); + } + + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_set_zero(z, size_batch); + for (unsigned int i = 0; i < dim_y; i++) { + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_set_zero(tmp, size_batch); + for (unsigned int j = 0; j < dim_x; j++) { + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_madd(tmp, mat, _x[j], size_batch); + mat += size_batch; + } + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_madd(z, tmp, _y[i], size_batch); + } +} + diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/parallel_matrix_op.h b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/parallel_matrix_op.h new file mode 100644 index 0000000000..78c1e83f84 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/parallel_matrix_op.h @@ -0,0 +1,260 @@ +#ifndef _P_MATRIX_OP_H_ +#define _P_MATRIX_OP_H_ +/// @file parallel_matrix_op.h +/// @brief Librarys for operations of batched matrixes. +/// +/// + +//////////////// Section: triangle matrix <-> rectangle matrix /////////////////////////////////// + +/// +/// @brief Calculate the corresponding index in an array for an upper-triangle(UT) matrix. +/// +/// @param[in] i_row - the i-th row in an upper-triangle matrix. +/// @param[in] j_col - the j-th column in an upper-triangle matrix. +/// @param[in] dim - the dimension of the upper-triangle matrix, i.e., an dim x dim matrix. +/// @return the corresponding index in an array storage. +/// +unsigned int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_idx_of_trimat(unsigned int i_row, unsigned int j_col, unsigned int dim); + +/// +/// @brief Upper trianglize a rectangle matrix to the corresponding upper-trangle matrix. +/// +/// @param[out] btriC - the batched upper-trianglized matrix C. +/// @param[in] bA - a batched retangle matrix A. +/// @param[in] bwidth - the width of the batched matrix A, i.e., A is a Awidth x Awidth matrix. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_UpperTrianglize(unsigned char *btriC, const unsigned char *bA, unsigned int Awidth, unsigned int size_batch); + +//////////////////// Section: matrix multiplications /////////////////////////////// + +/// +/// @brief bC += btriA * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_trimat_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += btriA * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += btriA^Tr * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. A will be transposed while multiplying. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_trimatTr_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += btriA^Tr * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A, which will be transposed while multiplying. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_trimatTr_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += (btriA + btriA^Tr) *B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. The operand for multiplication is (btriA + btriA^Tr). +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_2trimat_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += (btriA + btriA^Tr) *B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. The operand for multiplication is (btriA + btriA^Tr). +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_2trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += A^Tr * bB , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] A_to_tr - a column-major matrix A. The operand for multiplication is A^Tr. +/// @param[in] Aheight - the height of A. +/// @param[in] size_Acolvec - the size of a column vector in A. +/// @param[in] Awidth - the width of A. +/// @param[in] bB - a batched matrix B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_matTr_madd_gf16(unsigned char *bC, + const unsigned char *A_to_tr, unsigned int Aheight, unsigned int size_Acolvec, unsigned int Awidth, + const unsigned char *bB, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += A^Tr * bB , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] A_to_tr - a column-major matrix A. The operand for multiplication is A^Tr. +/// @param[in] Aheight - the height of A. +/// @param[in] size_Acolvec - the size of a column vector in A. +/// @param[in] Awidth - the width of A. +/// @param[in] bB - a batched matrix B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_matTr_madd_gf256(unsigned char *bC, + const unsigned char *A_to_tr, unsigned int Aheight, unsigned int size_Acolvec, unsigned int Awidth, + const unsigned char *bB, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA^Tr * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA_to_tr - a batched matrix A. The operand for multiplication is (bA^Tr). +/// @param[in] Awidth_befor_tr - the width of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_bmatTr_madd_gf16(unsigned char *bC, const unsigned char *bA_to_tr, unsigned int Awidth_before_tr, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA^Tr * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA_to_tr - a batched matrix A. The operand for multiplication is (bA^Tr). +/// @param[in] Awidth_befor_tr - the width of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_bmatTr_madd_gf256(unsigned char *bC, const unsigned char *bA_to_tr, unsigned int Awidth_before_tr, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA - a batched matrix A. +/// @param[in] Aheigh - the height of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_mat_madd_gf16(unsigned char *bC, const unsigned char *bA, unsigned int Aheight, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA - a batched matrix A. +/// @param[in] Aheigh - the height of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_mat_madd_gf256(unsigned char *bC, const unsigned char *bA, unsigned int Aheight, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +//////////////////// Section: "quadratric" matrix evaluation /////////////////////////////// + +/// +/// @brief y = x^Tr * trimat * x , in GF(16) +/// +/// @param[out] y - the returned batched element y. +/// @param[in] trimat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim - the dimension of matrix trimat (and x). +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_quad_trimat_eval_gf16(unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned int dim, unsigned int size_batch); + +/// +/// @brief y = x^Tr * trimat * x , in GF(256) +/// +/// @param[out] y - the returned batched element y. +/// @param[in] trimat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim - the dimension of matrix trimat (and x). +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_quad_trimat_eval_gf256(unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned int dim, unsigned int size_batch); + +/// +/// @brief z = y^Tr * mat * x , in GF(16) +/// +/// @param[out] z - the returned batched element z. +/// @param[in] y - an input vector y. +/// @param[in] dim_y - the length of y. +/// @param[in] mat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim_x - the length of x. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_quad_recmat_eval_gf16(unsigned char *z, const unsigned char *y, unsigned int dim_y, + const unsigned char *mat, const unsigned char *x, unsigned int dim_x, unsigned int size_batch); + +/// +/// @brief z = y^Tr * mat * x , in GF(256) +/// +/// @param[out] z - the returned batched element z. +/// @param[in] y - an input vector y. +/// @param[in] dim_y - the length of y. +/// @param[in] mat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim_x - the length of x. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_quad_recmat_eval_gf256(unsigned char *z, const unsigned char *y, unsigned int dim_y, + const unsigned char *mat, const unsigned char *x, unsigned int dim_x, unsigned int size_batch); + +#endif // _P_MATRIX_OP_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/rainbow.c b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/rainbow.c new file mode 100644 index 0000000000..fc80868999 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/rainbow.c @@ -0,0 +1,168 @@ +/// @file rainbow.c +/// @brief The standard implementations for functions in rainbow.h +/// + +#include "blas.h" +#include "parallel_matrix_op.h" +#include "rainbow.h" +#include "rainbow_blas.h" +#include "rainbow_config.h" +#include "rainbow_keypair.h" +#include "utils_hash.h" +#include "utils_prng.h" +#include +#include +#include + +#define MAX_ATTEMPT_FRMAT 128 + +int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_rainbow_sign(uint8_t *signature, const sk_t *sk, const uint8_t *_digest) { + uint8_t mat_l1[_O1 * _O1_BYTE]; + uint8_t mat_l2[_O2 * _O2_BYTE]; + uint8_t mat_buffer[2 * _MAX_O * _MAX_O_BYTE]; + + // setup PRNG + prng_t prng_sign; + uint8_t prng_preseed[LEN_SKSEED + _HASH_LEN]; + memcpy(prng_preseed, sk->sk_seed, LEN_SKSEED); + memcpy(prng_preseed + LEN_SKSEED, _digest, _HASH_LEN); // prng_preseed = sk_seed || digest + uint8_t prng_seed[_HASH_LEN]; + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_hash_msg(prng_seed, _HASH_LEN, prng_preseed, _HASH_LEN + LEN_SKSEED); + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_prng_set(&prng_sign, prng_seed, _HASH_LEN); // seed = H( sk_seed || digest ) + for (unsigned int i = 0; i < LEN_SKSEED + _HASH_LEN; i++) { + prng_preseed[i] ^= prng_preseed[i]; // clean + } + for (unsigned int i = 0; i < _HASH_LEN; i++) { + prng_seed[i] ^= prng_seed[i]; // clean + } + + // roll vinegars. + uint8_t vinegar[_V1_BYTE]; + unsigned int n_attempt = 0; + unsigned int l1_succ = 0; + while (!l1_succ) { + if (MAX_ATTEMPT_FRMAT <= n_attempt) { + break; + } + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_prng_gen(&prng_sign, vinegar, _V1_BYTE); // generating vinegars + gfmat_prod(mat_l1, sk->l1_F2, _O1 * _O1_BYTE, _V1, vinegar); // generating the linear equations for layer 1 + l1_succ = gfmat_inv(mat_l1, mat_l1, _O1, mat_buffer); // check if the linear equation solvable + n_attempt++; + } + + // Given the vinegars, pre-compute variables needed for layer 2 + uint8_t r_l1_F1[_O1_BYTE] = {0}; + uint8_t r_l2_F1[_O2_BYTE] = {0}; + batch_quad_trimat_eval(r_l1_F1, sk->l1_F1, vinegar, _V1, _O1_BYTE); + batch_quad_trimat_eval(r_l2_F1, sk->l2_F1, vinegar, _V1, _O2_BYTE); + uint8_t mat_l2_F3[_O2 * _O2_BYTE]; + uint8_t mat_l2_F2[_O1 * _O2_BYTE]; + gfmat_prod(mat_l2_F3, sk->l2_F3, _O2 * _O2_BYTE, _V1, vinegar); + gfmat_prod(mat_l2_F2, sk->l2_F2, _O1 * _O2_BYTE, _V1, vinegar); + + // Some local variables. + uint8_t _z[_PUB_M_BYTE]; + uint8_t y[_PUB_M_BYTE]; + uint8_t *x_v1 = vinegar; + uint8_t x_o1[_O1_BYTE]; + uint8_t x_o2[_O1_BYTE]; + + uint8_t digest_salt[_HASH_LEN + _SALT_BYTE]; + memcpy(digest_salt, _digest, _HASH_LEN); + uint8_t *salt = digest_salt + _HASH_LEN; + + uint8_t temp_o[_MAX_O_BYTE + 32] = {0}; + unsigned int succ = 0; + while (!succ) { + if (MAX_ATTEMPT_FRMAT <= n_attempt) { + break; + } + // The computation: H(digest||salt) --> z --S--> y --C-map--> x --T--> w + + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_prng_gen(&prng_sign, salt, _SALT_BYTE); // roll the salt + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_hash_msg(_z, _PUB_M_BYTE, digest_salt, _HASH_LEN + _SALT_BYTE); // H(digest||salt) + + // y = S^-1 * z + memcpy(y, _z, _PUB_M_BYTE); // identity part of S + gfmat_prod(temp_o, sk->s1, _O1_BYTE, _O2, _z + _O1_BYTE); + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_add(y, temp_o, _O1_BYTE); + + // Central Map: + // layer 1: calculate x_o1 + memcpy(temp_o, r_l1_F1, _O1_BYTE); + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_add(temp_o, y, _O1_BYTE); + gfmat_prod(x_o1, mat_l1, _O1_BYTE, _O1, temp_o); + + // layer 2: calculate x_o2 + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_set_zero(temp_o, _O2_BYTE); + gfmat_prod(temp_o, mat_l2_F2, _O2_BYTE, _O1, x_o1); // F2 + batch_quad_trimat_eval(mat_l2, sk->l2_F5, x_o1, _O1, _O2_BYTE); // F5 + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_add(temp_o, mat_l2, _O2_BYTE); + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_add(temp_o, r_l2_F1, _O2_BYTE); // F1 + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_add(temp_o, y + _O1_BYTE, _O2_BYTE); + + // generate the linear equations of the 2nd layer + gfmat_prod(mat_l2, sk->l2_F6, _O2 * _O2_BYTE, _O1, x_o1); // F6 + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_add(mat_l2, mat_l2_F3, _O2 * _O2_BYTE); // F3 + succ = gfmat_inv(mat_l2, mat_l2, _O2, mat_buffer); + gfmat_prod(x_o2, mat_l2, _O2_BYTE, _O2, temp_o); // solve l2 eqs + + n_attempt++; + }; + // w = T^-1 * y + uint8_t w[_PUB_N_BYTE]; + // identity part of T. + memcpy(w, x_v1, _V1_BYTE); + memcpy(w + _V1_BYTE, x_o1, _O1_BYTE); + memcpy(w + _V2_BYTE, x_o2, _O2_BYTE); + // Computing the t1 part. + gfmat_prod(y, sk->t1, _V1_BYTE, _O1, x_o1); + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_add(w, y, _V1_BYTE); + // Computing the t4 part. + gfmat_prod(y, sk->t4, _V1_BYTE, _O2, x_o2); + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_add(w, y, _V1_BYTE); + // Computing the t3 part. + gfmat_prod(y, sk->t3, _O1_BYTE, _O2, x_o2); + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_add(w + _V1_BYTE, y, _O1_BYTE); + + memset(signature, 0, _SIGNATURE_BYTE); // set the output 0 + // clean + memset(&prng_sign, 0, sizeof(prng_t)); + memset(vinegar, 0, _V1_BYTE); + memset(r_l1_F1, 0, _O1_BYTE); + memset(r_l2_F1, 0, _O2_BYTE); + memset(_z, 0, _PUB_M_BYTE); + memset(y, 0, _PUB_M_BYTE); + memset(x_o1, 0, _O1_BYTE); + memset(x_o2, 0, _O2_BYTE); + memset(temp_o, 0, sizeof(temp_o)); + + // return: copy w and salt to the signature. + if (MAX_ATTEMPT_FRMAT <= n_attempt) { + return -1; + } + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_add(signature, w, _PUB_N_BYTE); + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_add(signature + _PUB_N_BYTE, salt, _SALT_BYTE); + return 0; +} + +int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_rainbow_verify(const uint8_t *digest, const uint8_t *signature, const pk_t *pk) { + unsigned char digest_ck[_PUB_M_BYTE]; + // public_map( digest_ck , pk , signature ); Evaluating the quadratic public polynomials. + batch_quad_trimat_eval(digest_ck, pk->pk, signature, _PUB_N, _PUB_M_BYTE); + + unsigned char correct[_PUB_M_BYTE]; + unsigned char digest_salt[_HASH_LEN + _SALT_BYTE]; + memcpy(digest_salt, digest, _HASH_LEN); + memcpy(digest_salt + _HASH_LEN, signature + _PUB_N_BYTE, _SALT_BYTE); + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_hash_msg(correct, _PUB_M_BYTE, digest_salt, _HASH_LEN + _SALT_BYTE); // H( digest || salt ) + + // check consistancy. + unsigned char cc = 0; + for (unsigned int i = 0; i < _PUB_M_BYTE; i++) { + cc |= (digest_ck[i] ^ correct[i]); + } + return (0 == cc) ? 0 : -1; +} + + diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/rainbow.h b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/rainbow.h new file mode 100644 index 0000000000..9d3aad327f --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/rainbow.h @@ -0,0 +1,33 @@ +#ifndef _RAINBOW_H_ +#define _RAINBOW_H_ +/// @file rainbow.h +/// @brief APIs for rainbow. +/// + +#include "rainbow_config.h" +#include "rainbow_keypair.h" + +#include + +/// +/// @brief Signing function for classical secret key. +/// +/// @param[out] signature - the signature. +/// @param[in] sk - the secret key. +/// @param[in] digest - the digest. +/// +int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_rainbow_sign(uint8_t *signature, const sk_t *sk, const uint8_t *digest); + +/// +/// @brief Verifying function. +/// +/// @param[in] digest - the digest. +/// @param[in] signature - the signature. +/// @param[in] pk - the public key. +/// @return 0 for successful verified. -1 for failed verification. +/// +int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_rainbow_verify(const uint8_t *digest, const uint8_t *signature, const pk_t *pk); + + + +#endif // _RAINBOW_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/rainbow_blas.h b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/rainbow_blas.h new file mode 100644 index 0000000000..b8048608e8 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/rainbow_blas.h @@ -0,0 +1,32 @@ +#ifndef _RAINBOW_BLAS_H_ +#define _RAINBOW_BLAS_H_ +/// @file rainbow_blas.h +/// @brief Defining the functions used in rainbow.c acconding to the definitions in rainbow_config.h +/// +/// Defining the functions used in rainbow.c acconding to the definitions in rainbow_config.h + +#include "blas.h" +#include "blas_comm.h" +#include "parallel_matrix_op.h" +#include "rainbow_config.h" + + +#define gfv_get_ele PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_get_ele +#define gfv_mul_scalar PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_mul_scalar +#define gfv_madd PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_madd + +#define gfmat_prod PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256mat_prod +#define gfmat_inv PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256mat_inv + +#define batch_trimat_madd PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_trimat_madd_gf256 +#define batch_trimatTr_madd PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_trimatTr_madd_gf256 +#define batch_2trimat_madd PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_2trimat_madd_gf256 +#define batch_matTr_madd PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_matTr_madd_gf256 +#define batch_bmatTr_madd PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_bmatTr_madd_gf256 +#define batch_mat_madd PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_mat_madd_gf256 + +#define batch_quad_trimat_eval PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_quad_trimat_eval_gf256 +#define batch_quad_recmat_eval PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_batch_quad_recmat_eval_gf256 + + +#endif // _RAINBOW_BLAS_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/rainbow_config.h b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/rainbow_config.h new file mode 100644 index 0000000000..b8bb361d69 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/rainbow_config.h @@ -0,0 +1,48 @@ +#ifndef _H_RAINBOW_CONFIG_H_ +#define _H_RAINBOW_CONFIG_H_ + +/// @file rainbow_config.h +/// @brief Defining the parameters of the Rainbow and the corresponding constants. +/// + +#define _GFSIZE 256 +#define _V1 68 +#define _O1 36 +#define _O2 36 +#define _MAX_O 36 +#define _HASH_LEN 48 + + +#define _V2 ((_V1) + (_O1)) + +/// size of N, in # of gf elements. +#define _PUB_N (_V1 + _O1 + _O2) + +/// size of M, in # gf elements. +#define _PUB_M (_O1 + _O2) + +/// size of variables, in # bytes. + +// GF256 +#define _V1_BYTE (_V1) +#define _V2_BYTE (_V2) +#define _O1_BYTE (_O1) +#define _O2_BYTE (_O2) +#define _MAX_O_BYTE (_MAX_O) +#define _PUB_N_BYTE (_PUB_N) +#define _PUB_M_BYTE (_PUB_M) + + +/// length of seed for public key, in # bytes +#define LEN_PKSEED 32 + +/// length of seed for secret key, in # bytes +#define LEN_SKSEED 32 + +/// length of salt for a signature, in # bytes +#define _SALT_BYTE 16 + +/// length of a signature +#define _SIGNATURE_BYTE (_PUB_N_BYTE + _SALT_BYTE) + +#endif // _H_RAINBOW_CONFIG_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/rainbow_keypair.c b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/rainbow_keypair.c new file mode 100644 index 0000000000..656704e7d0 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/rainbow_keypair.c @@ -0,0 +1,126 @@ +/// @file rainbow_keypair.c +/// @brief implementations of functions in rainbow_keypair.h +/// + +#include "rainbow_keypair.h" +#include "blas.h" +#include "blas_comm.h" +#include "rainbow_blas.h" +#include "rainbow_keypair_computation.h" +#include "utils_prng.h" +#include +#include +#include + +static void generate_S_T(unsigned char *s_and_t, prng_t *prng0) { + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_prng_gen(prng0, s_and_t, _O1_BYTE * _O2); // S1 + s_and_t += _O1_BYTE * _O2; + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_prng_gen(prng0, s_and_t, _V1_BYTE * _O1); // T1 + s_and_t += _V1_BYTE * _O1; + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_prng_gen(prng0, s_and_t, _V1_BYTE * _O2); // T2 + s_and_t += _V1_BYTE * _O2; + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_prng_gen(prng0, s_and_t, _O1_BYTE * _O2); // T3 +} + +static unsigned int generate_l1_F12(unsigned char *sk, prng_t *prng0) { + unsigned int n_byte_generated = 0; + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_prng_gen(prng0, sk, _O1_BYTE * N_TRIANGLE_TERMS(_V1)); // l1_F1 + sk += _O1_BYTE * N_TRIANGLE_TERMS(_V1); + n_byte_generated += _O1_BYTE * N_TRIANGLE_TERMS(_V1); + + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_prng_gen(prng0, sk, _O1_BYTE * _V1 * _O1); // l1_F2 + n_byte_generated += _O1_BYTE * _V1 * _O1; + return n_byte_generated; +} + +static unsigned int generate_l2_F12356(unsigned char *sk, prng_t *prng0) { + unsigned int n_byte_generated = 0; + + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * N_TRIANGLE_TERMS(_V1)); // l2_F1 + sk += _O2_BYTE * N_TRIANGLE_TERMS(_V1); + n_byte_generated += _O2_BYTE * N_TRIANGLE_TERMS(_V1); + + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * _V1 * _O1); // l2_F2 + sk += _O2_BYTE * _V1 * _O1; + n_byte_generated += _O2_BYTE * _V1 * _O1; + + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * _V1 * _O2); // l2_F3 + sk += _O2_BYTE * _V1 * _O1; + n_byte_generated += _O2_BYTE * _V1 * _O1; + + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * N_TRIANGLE_TERMS(_O1)); // l2_F5 + sk += _O2_BYTE * N_TRIANGLE_TERMS(_O1); + n_byte_generated += _O2_BYTE * N_TRIANGLE_TERMS(_O1); + + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * _O1 * _O2); // l2_F6 + n_byte_generated += _O2_BYTE * _O1 * _O2; + + return n_byte_generated; +} + +static void generate_B1_B2(unsigned char *sk, prng_t *prng0) { + sk += generate_l1_F12(sk, prng0); + generate_l2_F12356(sk, prng0); +} + +static void calculate_t4(unsigned char *t2_to_t4, const unsigned char *t1, const unsigned char *t3) { + // t4 = T_sk.t1 * T_sk.t3 - T_sk.t2 + unsigned char temp[_V1_BYTE + 32]; + unsigned char *t4 = t2_to_t4; + for (unsigned int i = 0; i < _O2; i++) { /// t3 width + gfmat_prod(temp, t1, _V1_BYTE, _O1, t3); + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_add(t4, temp, _V1_BYTE); + t4 += _V1_BYTE; + t3 += _O1_BYTE; + } +} + +static void obsfucate_l1_polys(unsigned char *l1_polys, const unsigned char *l2_polys, unsigned int n_terms, const unsigned char *s1) { + unsigned char temp[_O1_BYTE + 32]; + while (n_terms--) { + gfmat_prod(temp, s1, _O1_BYTE, _O2, l2_polys); + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_gf256v_add(l1_polys, temp, _O1_BYTE); + l1_polys += _O1_BYTE; + l2_polys += _O2_BYTE; + } +} + +/////////////////// Classic ////////////////////////////////// + +static void _generate_secretkey(sk_t *sk, const unsigned char *sk_seed) { + memcpy(sk->sk_seed, sk_seed, LEN_SKSEED); + + // set up prng + prng_t prng0; + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_prng_set(&prng0, sk_seed, LEN_SKSEED); + + // generating secret key with prng. + generate_S_T(sk->s1, &prng0); + generate_B1_B2(sk->l1_F1, &prng0); + + // clean prng + memset(&prng0, 0, sizeof(prng_t)); +} + +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_generate_keypair(pk_t *rpk, sk_t *sk, const unsigned char *sk_seed) { + _generate_secretkey(sk, sk_seed); + + // set up a temporary structure ext_cpk_t for calculating public key. + ext_cpk_t pk; + + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_calculate_Q_from_F(&pk, sk, sk); // compute the public key in ext_cpk_t format. + calculate_t4(sk->t4, sk->t1, sk->t3); + + obsfucate_l1_polys(pk.l1_Q1, pk.l2_Q1, N_TRIANGLE_TERMS(_V1), sk->s1); + obsfucate_l1_polys(pk.l1_Q2, pk.l2_Q2, _V1 * _O1, sk->s1); + obsfucate_l1_polys(pk.l1_Q3, pk.l2_Q3, _V1 * _O2, sk->s1); + obsfucate_l1_polys(pk.l1_Q5, pk.l2_Q5, N_TRIANGLE_TERMS(_O1), sk->s1); + obsfucate_l1_polys(pk.l1_Q6, pk.l2_Q6, _O1 * _O2, sk->s1); + obsfucate_l1_polys(pk.l1_Q9, pk.l2_Q9, N_TRIANGLE_TERMS(_O2), sk->s1); + // so far, the pk contains the full pk but in ext_cpk_t format. + + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_extcpk_to_pk(rpk, &pk); // convert the public key from ext_cpk_t to pk_t. +} + + + diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/rainbow_keypair.h b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/rainbow_keypair.h new file mode 100644 index 0000000000..3fd3457005 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/rainbow_keypair.h @@ -0,0 +1,61 @@ +#ifndef _RAINBOW_KEYPAIR_H_ +#define _RAINBOW_KEYPAIR_H_ +/// @file rainbow_keypair.h +/// @brief Formats of key pairs and functions for generating key pairs. +/// Formats of key pairs and functions for generating key pairs. +/// + +#include "rainbow_config.h" + +#define N_TRIANGLE_TERMS(n_var) ((n_var) * ((n_var) + 1) / 2) + +/// @brief public key for classic rainbow +/// +/// public key for classic rainbow +/// +typedef struct rainbow_publickey { + unsigned char pk[(_PUB_M_BYTE)*N_TRIANGLE_TERMS(_PUB_N)]; +} pk_t; + +/// @brief secret key for classic rainbow +/// +/// secret key for classic rainbow +/// +typedef struct rainbow_secretkey { + /// + /// seed for generating secret key. + /// Generating S, T, and F for classic rainbow. + /// Generating S and T only for cyclic rainbow. + unsigned char sk_seed[LEN_SKSEED]; + + unsigned char s1[_O1_BYTE * _O2]; ///< part of S map + unsigned char t1[_V1_BYTE * _O1]; ///< part of T map + unsigned char t4[_V1_BYTE * _O2]; ///< part of T map + unsigned char t3[_O1_BYTE * _O2]; ///< part of T map + + unsigned char l1_F1[_O1_BYTE * N_TRIANGLE_TERMS(_V1)]; ///< part of C-map, F1, Layer1 + unsigned char l1_F2[_O1_BYTE * _V1 * _O1]; ///< part of C-map, F2, Layer1 + + unsigned char l2_F1[_O2_BYTE * N_TRIANGLE_TERMS(_V1)]; ///< part of C-map, F1, Layer2 + unsigned char l2_F2[_O2_BYTE * _V1 * _O1]; ///< part of C-map, F2, Layer2 + + unsigned char l2_F3[_O2_BYTE * _V1 * _O2]; ///< part of C-map, F3, Layer2 + unsigned char l2_F5[_O2_BYTE * N_TRIANGLE_TERMS(_O1)]; ///< part of C-map, F5, Layer2 + unsigned char l2_F6[_O2_BYTE * _O1 * _O2]; ///< part of C-map, F6, Layer2 +} sk_t; + + +/// +/// @brief Generate key pairs for classic rainbow. +/// +/// @param[out] pk - the public key. +/// @param[out] sk - the secret key. +/// @param[in] sk_seed - seed for generating the secret key. +/// +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_generate_keypair(pk_t *pk, sk_t *sk, const unsigned char *sk_seed); + + + + + +#endif // _RAINBOW_KEYPAIR_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/rainbow_keypair_computation.c b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/rainbow_keypair_computation.c new file mode 100644 index 0000000000..796b7de257 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/rainbow_keypair_computation.c @@ -0,0 +1,189 @@ +/// @file rainbow_keypair_computation.c +/// @brief Implementations for functions in rainbow_keypair_computation.h +/// + +#include "rainbow_keypair_computation.h" +#include "blas.h" +#include "blas_comm.h" +#include "rainbow_blas.h" +#include "rainbow_keypair.h" +#include +#include +#include + +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_extcpk_to_pk(pk_t *pk, const ext_cpk_t *cpk) { + const unsigned char *idx_l1 = cpk->l1_Q1; + const unsigned char *idx_l2 = cpk->l2_Q1; + for (unsigned int i = 0; i < _V1; i++) { + for (unsigned int j = i; j < _V1; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q2; + idx_l2 = cpk->l2_Q2; + for (unsigned int i = 0; i < _V1; i++) { + for (unsigned int j = _V1; j < _V1 + _O1; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q3; + idx_l2 = cpk->l2_Q3; + for (unsigned int i = 0; i < _V1; i++) { + for (unsigned int j = _V1 + _O1; j < _PUB_N; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q5; + idx_l2 = cpk->l2_Q5; + for (unsigned int i = _V1; i < _V1 + _O1; i++) { + for (unsigned int j = i; j < _V1 + _O1; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q6; + idx_l2 = cpk->l2_Q6; + for (unsigned int i = _V1; i < _V1 + _O1; i++) { + for (unsigned int j = _V1 + _O1; j < _PUB_N; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q9; + idx_l2 = cpk->l2_Q9; + for (unsigned int i = _V1 + _O1; i < _PUB_N; i++) { + for (unsigned int j = i; j < _PUB_N; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } +} + +static void calculate_Q_from_F_ref(ext_cpk_t *Qs, const sk_t *Fs, const sk_t *Ts) { + /* + Layer 1 + Computing : + Q_pk.l1_F1s[i] = F_sk.l1_F1s[i] + + Q_pk.l1_F2s[i] = (F1* T1 + F2) + F1tr * t1 + Q_pk.l1_F5s[i] = UT( T1tr* (F1 * T1 + F2) ) + */ + const unsigned char *t2 = Ts->t4; + + memcpy(Qs->l1_Q1, Fs->l1_F1, _O1_BYTE * N_TRIANGLE_TERMS(_V1)); + + memcpy(Qs->l1_Q2, Fs->l1_F2, _O1_BYTE * _V1 * _O1); + batch_trimat_madd(Qs->l1_Q2, Fs->l1_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O1_BYTE); // F1*T1 + F2 + + memset(Qs->l1_Q3, 0, _O1_BYTE * _V1 * _O2); + memset(Qs->l1_Q5, 0, _O1_BYTE * N_TRIANGLE_TERMS(_O1)); + memset(Qs->l1_Q6, 0, _O1_BYTE * _O1 * _O2); + memset(Qs->l1_Q9, 0, _O1_BYTE * N_TRIANGLE_TERMS(_O2)); + + // l1_Q5 : _O1_BYTE * _O1 * _O1 + // l1_Q9 : _O1_BYTE * _O2 * _O2 + // l2_Q5 : _O2_BYTE * _V1 * _O1 + // l2_Q9 : _O2_BYTE * _V1 * _O2 + + unsigned char tempQ[_O1_BYTE * _O1 * _O1 + 32]; + + memset(tempQ, 0, _O1_BYTE * _O1 * _O1); // l1_Q5 + batch_matTr_madd(tempQ, Ts->t1, _V1, _V1_BYTE, _O1, Qs->l1_Q2, _O1, _O1_BYTE); // t1_tr*(F1*T1 + F2) + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_UpperTrianglize(Qs->l1_Q5, tempQ, _O1, _O1_BYTE); // UT( ... ) // Q5 + + batch_trimatTr_madd(Qs->l1_Q2, Fs->l1_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O1_BYTE); // Q2 + /* + Computing: + F1_T2 = F1 * t2 + F2_T3 = F2 * t3 + F1_F1T_T2 + F2_T3 = F1_T2 + F2_T3 + F1tr * t2 + Q_pk.l1_F3s[i] = F1_F1T_T2 + F2_T3 + Q_pk.l1_F6s[i] = T1tr* ( F1_F1T_T2 + F2_T3 ) + F2tr * t2 + Q_pk.l1_F9s[i] = UT( T2tr* ( F1_T2 + F2_T3 ) ) + */ + batch_trimat_madd(Qs->l1_Q3, Fs->l1_F1, t2, _V1, _V1_BYTE, _O2, _O1_BYTE); // F1*T2 + batch_mat_madd(Qs->l1_Q3, Fs->l1_F2, _V1, Ts->t3, _O1, _O1_BYTE, _O2, _O1_BYTE); // F1_T2 + F2_T3 + + memset(tempQ, 0, _O1_BYTE * _O2 * _O2); // l1_Q9 + batch_matTr_madd(tempQ, t2, _V1, _V1_BYTE, _O2, Qs->l1_Q3, _O2, _O1_BYTE); // T2tr * ( F1_T2 + F2_T3 ) + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_UpperTrianglize(Qs->l1_Q9, tempQ, _O2, _O1_BYTE); // Q9 + + batch_trimatTr_madd(Qs->l1_Q3, Fs->l1_F1, t2, _V1, _V1_BYTE, _O2, _O1_BYTE); // F1_F1T_T2 + F2_T3 // Q3 + + batch_bmatTr_madd(Qs->l1_Q6, Fs->l1_F2, _O1, t2, _V1, _V1_BYTE, _O2, _O1_BYTE); // F2tr*T2 + batch_matTr_madd(Qs->l1_Q6, Ts->t1, _V1, _V1_BYTE, _O1, Qs->l1_Q3, _O2, _O1_BYTE); // Q6 + + /* + layer 2 + Computing: + Q1 = F1 + Q2 = F1_F1T*T1 + F2 + Q5 = UT( T1tr( F1*T1 + F2 ) + F5 ) + */ + memcpy(Qs->l2_Q1, Fs->l2_F1, _O2_BYTE * N_TRIANGLE_TERMS(_V1)); + + memcpy(Qs->l2_Q2, Fs->l2_F2, _O2_BYTE * _V1 * _O1); + batch_trimat_madd(Qs->l2_Q2, Fs->l2_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O2_BYTE); // F1*T1 + F2 + + memcpy(Qs->l2_Q5, Fs->l2_F5, _O2_BYTE * N_TRIANGLE_TERMS(_O1)); + memset(tempQ, 0, _O2_BYTE * _O1 * _O1); // l2_Q5 + batch_matTr_madd(tempQ, Ts->t1, _V1, _V1_BYTE, _O1, Qs->l2_Q2, _O1, _O2_BYTE); // t1_tr*(F1*T1 + F2) + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_UpperTrianglize(Qs->l2_Q5, tempQ, _O1, _O2_BYTE); // UT( ... ) // Q5 + + batch_trimatTr_madd(Qs->l2_Q2, Fs->l2_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O2_BYTE); // Q2 + + /* + Computing: + F1_T2 = F1 * t2 + F2_T3 = F2 * t3 + F1_F1T_T2 + F2_T3 = F1_T2 + F2_T3 + F1tr * t2 + + Q3 = F1_F1T*T2 + F2*T3 + F3 + Q9 = UT( T2tr*( F1*T2 + F2*T3 + F3 ) + T3tr*( F5*T3 + F6 ) ) + Q6 = T1tr*( F1_F1T*T2 + F2*T3 + F3 ) + F2Tr*T2 + F5_F5T*T3 + F6 + */ + memcpy(Qs->l2_Q3, Fs->l2_F3, _O2_BYTE * _V1 * _O2); + batch_trimat_madd(Qs->l2_Q3, Fs->l2_F1, t2, _V1, _V1_BYTE, _O2, _O2_BYTE); // F1*T2 + F3 + batch_mat_madd(Qs->l2_Q3, Fs->l2_F2, _V1, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // F1_T2 + F2_T3 + F3 + + memset(tempQ, 0, _O2_BYTE * _O2 * _O2); // l2_Q9 + batch_matTr_madd(tempQ, t2, _V1, _V1_BYTE, _O2, Qs->l2_Q3, _O2, _O2_BYTE); // T2tr * ( ..... ) + + memcpy(Qs->l2_Q6, Fs->l2_F6, _O2_BYTE * _O1 * _O2); + + batch_trimat_madd(Qs->l2_Q6, Fs->l2_F5, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // F5*T3 + F6 + batch_matTr_madd(tempQ, Ts->t3, _O1, _O1_BYTE, _O2, Qs->l2_Q6, _O2, _O2_BYTE); // T2tr*( ..... ) + T3tr*( ..... ) + memset(Qs->l2_Q9, 0, _O2_BYTE * N_TRIANGLE_TERMS(_O2)); + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_UpperTrianglize(Qs->l2_Q9, tempQ, _O2, _O2_BYTE); // Q9 + + batch_trimatTr_madd(Qs->l2_Q3, Fs->l2_F1, t2, _V1, _V1_BYTE, _O2, _O2_BYTE); // F1_F1T_T2 + F2_T3 + F3 // Q3 + + batch_bmatTr_madd(Qs->l2_Q6, Fs->l2_F2, _O1, t2, _V1, _V1_BYTE, _O2, _O2_BYTE); // F5*T3 + F6 + F2tr*T2 + batch_trimatTr_madd(Qs->l2_Q6, Fs->l2_F5, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // F2tr*T2 + F5_F5T*T3 + F6 + batch_matTr_madd(Qs->l2_Q6, Ts->t1, _V1, _V1_BYTE, _O1, Qs->l2_Q3, _O2, _O2_BYTE); // Q6 +} +#define calculate_Q_from_F_impl calculate_Q_from_F_ref +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_calculate_Q_from_F(ext_cpk_t *Qs, const sk_t *Fs, const sk_t *Ts) { + calculate_Q_from_F_impl(Qs, Fs, Ts); +} diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/rainbow_keypair_computation.h b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/rainbow_keypair_computation.h new file mode 100644 index 0000000000..d9aa3446f6 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/rainbow_keypair_computation.h @@ -0,0 +1,53 @@ +#ifndef _RAINBOW_KEYPAIR_COMP_H_ +#define _RAINBOW_KEYPAIR_COMP_H_ +/// @file rainbow_keypair_computation.h +/// @brief Functions for calculating pk/sk while generating keys. +/// +/// Defining an internal structure of public key. +/// Functions for calculating pk/sk for key generation. +/// + +#include "rainbow_keypair.h" + +/// @brief The (internal use) public key for rainbow +/// +/// The (internal use) public key for rainbow. The public +/// polynomials are divided into l1_Q1, l1_Q2, ... l1_Q9, +/// l2_Q1, .... , l2_Q9. +/// +typedef struct rainbow_extend_publickey { + unsigned char l1_Q1[_O1_BYTE * N_TRIANGLE_TERMS(_V1)]; + unsigned char l1_Q2[_O1_BYTE * _V1 * _O1]; + unsigned char l1_Q3[_O1_BYTE * _V1 * _O2]; + unsigned char l1_Q5[_O1_BYTE * N_TRIANGLE_TERMS(_O1)]; + unsigned char l1_Q6[_O1_BYTE * _O1 * _O2]; + unsigned char l1_Q9[_O1_BYTE * N_TRIANGLE_TERMS(_O2)]; + + unsigned char l2_Q1[_O2_BYTE * N_TRIANGLE_TERMS(_V1)]; + unsigned char l2_Q2[_O2_BYTE * _V1 * _O1]; + unsigned char l2_Q3[_O2_BYTE * _V1 * _O2]; + unsigned char l2_Q5[_O2_BYTE * N_TRIANGLE_TERMS(_O1)]; + unsigned char l2_Q6[_O2_BYTE * _O1 * _O2]; + unsigned char l2_Q9[_O2_BYTE * N_TRIANGLE_TERMS(_O2)]; +} ext_cpk_t; + +/// +/// @brief converting formats of public keys : from ext_cpk_t version to pk_t +/// +/// @param[out] pk - the classic public key. +/// @param[in] cpk - the internel public key. +/// +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_extcpk_to_pk(pk_t *pk, const ext_cpk_t *cpk); +///////////////////////////////////////////////// + +/// +/// @brief Computing public key from secret key +/// +/// @param[out] Qs - the public key +/// @param[in] Fs - parts of the secret key: l1_F1, l1_F2, l2_F1, l2_F2, l2_F3, l2_F5, l2_F6 +/// @param[in] Ts - parts of the secret key: T1, T4, T3 +/// +void PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_calculate_Q_from_F(ext_cpk_t *Qs, const sk_t *Fs, const sk_t *Ts); + + +#endif // _RAINBOW_KEYPAIR_COMP_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/sign.c b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/sign.c new file mode 100644 index 0000000000..4d7cd1e18a --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/sign.c @@ -0,0 +1,74 @@ +/// @file sign.c +/// @brief the implementations for functions in api.h +/// +/// + +#include "api.h" +#include "rainbow.h" +#include "rainbow_config.h" +#include "rainbow_keypair.h" +#include "randombytes.h" +#include "utils_hash.h" +#include +#include + +int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { + unsigned char sk_seed[LEN_SKSEED] = {0}; + randombytes(sk_seed, LEN_SKSEED); + + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_generate_keypair((pk_t *)pk, (sk_t *)sk, sk_seed); + return 0; +} + +int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { + unsigned char digest[_HASH_LEN]; + + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_hash_msg(digest, _HASH_LEN, m, mlen); + + memcpy(sm, m, mlen); + smlen[0] = mlen + _SIGNATURE_BYTE; + + return PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_rainbow_sign(sm + mlen, (const sk_t *)sk, digest); +} + +int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { + int rc; + if (_SIGNATURE_BYTE > smlen) { + rc = -1; + } else { + *mlen = smlen - _SIGNATURE_BYTE; + + unsigned char digest[_HASH_LEN]; + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_hash_msg(digest, _HASH_LEN, sm, *mlen); + + rc = PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_rainbow_verify(digest, sm + mlen[0], (const pk_t *)pk); + } + if (!rc) { + memmove(m, sm, smlen - _SIGNATURE_BYTE); + } else { // bad signature + *mlen = (size_t) -1; + memset(m, 0, smlen); + } + return rc; +} + +int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_crypto_sign_signature( + uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + unsigned char digest[_HASH_LEN]; + + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_hash_msg(digest, _HASH_LEN, m, mlen); + *siglen = _SIGNATURE_BYTE; + return PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_rainbow_sign(sig, (const sk_t *)sk, digest); +} + +int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_crypto_sign_verify( + const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + if (siglen != _SIGNATURE_BYTE) { + return -1; + } + unsigned char digest[_HASH_LEN]; + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_hash_msg(digest, _HASH_LEN, m, mlen); + return PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_rainbow_verify(digest, sig, (const pk_t *)pk); +} diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/utils_hash.c b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/utils_hash.c new file mode 100644 index 0000000000..58948cd977 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/utils_hash.c @@ -0,0 +1,50 @@ +/// @file utils_hash.c +/// @brief the adapter for SHA2 families. +/// +/// + +#include "utils_hash.h" +#include "rainbow_config.h" +#include "sha2.h" + +static inline int _hash(unsigned char *digest, const unsigned char *m, size_t mlen) { + sha384(digest, m, mlen); + return 0; +} + +static inline int expand_hash(unsigned char *digest, size_t n_digest, const unsigned char *hash) { + if (_HASH_LEN >= n_digest) { + for (size_t i = 0; i < n_digest; i++) { + digest[i] = hash[i]; + } + return 0; + } + for (size_t i = 0; i < _HASH_LEN; i++) { + digest[i] = hash[i]; + } + n_digest -= _HASH_LEN; + + while (_HASH_LEN <= n_digest) { + _hash(digest + _HASH_LEN, digest, _HASH_LEN); + + n_digest -= _HASH_LEN; + digest += _HASH_LEN; + } + unsigned char temp[_HASH_LEN]; + if (n_digest) { + _hash(temp, digest, _HASH_LEN); + for (size_t i = 0; i < n_digest; i++) { + digest[_HASH_LEN + i] = temp[i]; + } + } + return 0; +} + +int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_hash_msg(unsigned char *digest, + size_t len_digest, + const unsigned char *m, + size_t mlen) { + unsigned char buf[_HASH_LEN]; + _hash(buf, m, mlen); + return expand_hash(digest, len_digest, buf); +} diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/utils_hash.h b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/utils_hash.h new file mode 100644 index 0000000000..7e7babfbd4 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/utils_hash.h @@ -0,0 +1,11 @@ +#ifndef _UTILS_HASH_H_ +#define _UTILS_HASH_H_ +/// @file utils_hash.h +/// @brief the interface for adapting hash functions. +/// + +#include + +int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_hash_msg(unsigned char *digest, size_t len_digest, const unsigned char *m, size_t mlen); + +#endif // _UTILS_HASH_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/utils_prng.c b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/utils_prng.c new file mode 100644 index 0000000000..61b65cfd30 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/utils_prng.c @@ -0,0 +1,97 @@ +/// @file utils_prng.c +/// @brief The implementation of PRNG related functions. +/// + +#include "utils_prng.h" +#include "aes.h" +#include "randombytes.h" +#include "utils_hash.h" +#include +#include + +static void prng_update(const unsigned char *provided_data, + unsigned char *Key, + unsigned char *V) { + unsigned char temp[48]; + aes256ctx ctx; + aes256_keyexp(&ctx, Key); + for (int i = 0; i < 3; i++) { + //increment V + for (int j = 15; j >= 0; j--) { + if (V[j] == 0xff) { + V[j] = 0x00; + } else { + V[j]++; + break; + } + } + aes256_ecb(temp + 16 * i, V, 1, &ctx); + } + if (provided_data != NULL) { + for (int i = 0; i < 48; i++) { + temp[i] ^= provided_data[i]; + } + } + aes256_ctx_release(&ctx); + memcpy(Key, temp, 32); + memcpy(V, temp + 32, 16); +} +static void randombytes_init_with_state(prng_t *state, + unsigned char *entropy_input_48bytes) { + memset(state->Key, 0x00, 32); + memset(state->V, 0x00, 16); + prng_update(entropy_input_48bytes, state->Key, state->V); +} + +static int randombytes_with_state(prng_t *state, + unsigned char *x, + size_t xlen) { + + unsigned char block[16]; + int i = 0; + + aes256ctx ctx; + aes256_keyexp(&ctx, state->Key); + + while (xlen > 0) { + //increment V + for (int j = 15; j >= 0; j--) { + if (state->V[j] == 0xff) { + state->V[j] = 0x00; + } else { + state->V[j]++; + break; + } + } + aes256_ecb(block, state->V, 1, &ctx); + if (xlen > 15) { + memcpy(x + i, block, 16); + i += 16; + xlen -= 16; + } else { + memcpy(x + i, block, xlen); + xlen = 0; + } + } + aes256_ctx_release(&ctx); + prng_update(NULL, state->Key, state->V); + return 0; +} + +int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_prng_set(prng_t *ctx, const void *prng_seed, unsigned long prng_seedlen) { + unsigned char seed[48]; + if (prng_seedlen >= 48) { + memcpy(seed, prng_seed, 48); + } else { + memcpy(seed, prng_seed, prng_seedlen); + PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_hash_msg(seed + prng_seedlen, 48 - (unsigned)prng_seedlen, (const unsigned char *)prng_seed, prng_seedlen); + } + + randombytes_init_with_state(ctx, seed); + + return 0; +} + +int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_prng_gen(prng_t *ctx, unsigned char *out, unsigned long outlen) { + return randombytes_with_state(ctx, out, outlen); +} diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/utils_prng.h b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/utils_prng.h new file mode 100644 index 0000000000..6b4999c75e --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-classic_clean/utils_prng.h @@ -0,0 +1,18 @@ +#ifndef _UTILS_PRNG_H_ +#define _UTILS_PRNG_H_ +/// @file utils_prng.h +/// @brief the interface for adapting PRNG functions. +/// +/// + +#include "randombytes.h" + +typedef struct { + unsigned char Key[32]; + unsigned char V[16]; +} prng_t; + +int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_prng_set(prng_t *ctx, const void *prng_seed, unsigned long prng_seedlen); +int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_prng_gen(prng_t *ctx, unsigned char *out, unsigned long outlen); + +#endif // _UTILS_PRNG_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/LICENSE b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/LICENSE new file mode 100644 index 0000000000..cb00a6e354 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/LICENSE @@ -0,0 +1,8 @@ +`Software implementation of Rainbow for NIST R2 submission' by Ming-Shing Chen + +To the extent possible under law, the person who associated CC0 with +`Software implementation of Rainbow for NIST R2 submission' has waived all copyright and related or neighboring rights +to `Software implementation of Rainbow for NIST R2 submission'. + +You should have received a copy of the CC0 legalcode along with this +work. If not, see . diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/api.h b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/api.h new file mode 100644 index 0000000000..a4a171a976 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/api.h @@ -0,0 +1,32 @@ +#ifndef PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_API_H +#define PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_API_H + +#include +#include + +#define PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_CRYPTO_SECRETKEYBYTES 64 +#define PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_CRYPTO_PUBLICKEYBYTES 206744 +#define PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_CRYPTO_BYTES 156 +#define PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_CRYPTO_ALGNAME "RAINBOW(256,68,36,36) - cyclic compressed" + +int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + + +int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_crypto_sign_signature( + uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_crypto_sign_verify( + const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + + +#endif diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/blas.c b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/blas.c new file mode 100644 index 0000000000..624432f29b --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/blas.c @@ -0,0 +1,31 @@ +#include "blas.h" +#include "gf.h" + +#include + +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_predicated_add(uint8_t *accu_b, uint8_t predicate, const uint8_t *a, size_t _num_byte) { + uint8_t pr_u8 = (uint8_t) ((uint8_t) 0 - predicate); + for (size_t i = 0; i < _num_byte; i++) { + accu_b[i] ^= (a[i] & pr_u8); + } +} + +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_add(uint8_t *accu_b, const uint8_t *a, size_t _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + accu_b[i] ^= a[i]; + } +} + + +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_mul_scalar(uint8_t *a, uint8_t b, size_t _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + a[i] = PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256_mul(a[i], b); + } +} + +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_madd(uint8_t *accu_c, const uint8_t *a, uint8_t gf256_b, size_t _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + accu_c[i] ^= PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256_mul(a[i], gf256_b); + } +} + diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/blas.h b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/blas.h new file mode 100644 index 0000000000..b3b0a33f1b --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/blas.h @@ -0,0 +1,19 @@ +#ifndef _BLAS_H_ +#define _BLAS_H_ +/// @file blas.h +/// @brief Functions for implementing basic linear algebra functions. +/// + +#include "rainbow_config.h" +#include +#include + +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_predicated_add(uint8_t *accu_b, uint8_t predicate, const uint8_t *a, size_t _num_byte); +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_add(uint8_t *accu_b, const uint8_t *a, size_t _num_byte); + + +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_mul_scalar(uint8_t *a, uint8_t b, size_t _num_byte); +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_madd(uint8_t *accu_c, const uint8_t *a, uint8_t gf256_b, size_t _num_byte); + + +#endif // _BLAS_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/blas_comm.c b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/blas_comm.c new file mode 100644 index 0000000000..83fbfc61ba --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/blas_comm.c @@ -0,0 +1,144 @@ +/// @file blas_comm.c +/// @brief The standard implementations for blas_comm.h +/// + +#include "blas_comm.h" +#include "blas.h" +#include "gf.h" +#include "rainbow_config.h" + +#include +#include + +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_set_zero(uint8_t *b, unsigned int _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + b[i] = 0; + } +} +/// @brief get an element from GF(256) vector . +/// +/// @param[in] a - the input vector a. +/// @param[in] i - the index in the vector a. +/// @return the value of the element. +/// +uint8_t PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_get_ele(const uint8_t *a, unsigned int i) { + return a[i]; +} + +unsigned int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_is_zero(const uint8_t *a, unsigned int _num_byte) { + uint8_t r = 0; + while (_num_byte--) { + r |= a[0]; + a++; + } + return (0 == r); +} + +/// polynomial multplication +/// School boook +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_polymul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int _num) { + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_set_zero(c, _num * 2 - 1); + for (unsigned int i = 0; i < _num; i++) { + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_madd(c + i, a, b[i], _num); + } +} + +static void gf256mat_prod_ref(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b) { + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_set_zero(c, n_A_vec_byte); + for (unsigned int i = 0; i < n_A_width; i++) { + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_madd(c, matA, b[i], n_A_vec_byte); + matA += n_A_vec_byte; + } +} + +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256mat_mul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int len_vec) { + unsigned int n_vec_byte = len_vec; + for (unsigned int k = 0; k < len_vec; k++) { + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_set_zero(c, n_vec_byte); + const uint8_t *bk = b + n_vec_byte * k; + for (unsigned int i = 0; i < len_vec; i++) { + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_madd(c, a + n_vec_byte * i, bk[i], n_vec_byte); + } + c += n_vec_byte; + } +} + +static unsigned int gf256mat_gauss_elim_ref(uint8_t *mat, unsigned int h, unsigned int w) { + unsigned int r8 = 1; + + for (unsigned int i = 0; i < h; i++) { + uint8_t *ai = mat + w * i; + unsigned int skip_len_align4 = i & ((unsigned int)~0x3); + + for (unsigned int j = i + 1; j < h; j++) { + uint8_t *aj = mat + w * j; + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_predicated_add(ai + skip_len_align4, !PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256_is_nonzero(ai[i]), aj + skip_len_align4, w - skip_len_align4); + } + r8 &= PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256_is_nonzero(ai[i]); + uint8_t pivot = ai[i]; + pivot = PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256_inv(pivot); + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_mul_scalar(ai + skip_len_align4, pivot, w - skip_len_align4); + for (unsigned int j = 0; j < h; j++) { + if (i == j) { + continue; + } + uint8_t *aj = mat + w * j; + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_madd(aj + skip_len_align4, ai + skip_len_align4, aj[i], w - skip_len_align4); + } + } + + return r8; +} + +static unsigned int gf256mat_solve_linear_eq_ref(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n) { + uint8_t mat[64 * 64]; + for (unsigned int i = 0; i < n; i++) { + memcpy(mat + i * (n + 1), inp_mat + i * n, n); + mat[i * (n + 1) + n] = c_terms[i]; + } + unsigned int r8 = PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256mat_gauss_elim(mat, n, n + 1); + for (unsigned int i = 0; i < n; i++) { + sol[i] = mat[i * (n + 1) + n]; + } + return r8; +} + +static inline void gf256mat_submat(uint8_t *mat2, unsigned int w2, unsigned int st, const uint8_t *mat, unsigned int w, unsigned int h) { + for (unsigned int i = 0; i < h; i++) { + for (unsigned int j = 0; j < w2; j++) { + mat2[i * w2 + j] = mat[i * w + st + j]; + } + } +} + +unsigned int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256mat_inv(uint8_t *inv_a, const uint8_t *a, unsigned int H, uint8_t *buffer) { + uint8_t *aa = buffer; + for (unsigned int i = 0; i < H; i++) { + uint8_t *ai = aa + i * 2 * H; + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_set_zero(ai, 2 * H); + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_add(ai, a + i * H, H); + ai[H + i] = 1; + } + unsigned int r8 = PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256mat_gauss_elim(aa, H, 2 * H); + gf256mat_submat(inv_a, H, H, aa, 2 * H, H); + return r8; +} + + +// choosing the implementations depends on the macros _BLAS_AVX2_ and _BLAS_SSE + +#define gf256mat_prod_impl gf256mat_prod_ref +#define gf256mat_gauss_elim_impl gf256mat_gauss_elim_ref +#define gf256mat_solve_linear_eq_impl gf256mat_solve_linear_eq_ref +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256mat_prod(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b) { + gf256mat_prod_impl(c, matA, n_A_vec_byte, n_A_width, b); +} + +unsigned int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256mat_gauss_elim(uint8_t *mat, unsigned int h, unsigned int w) { + return gf256mat_gauss_elim_impl(mat, h, w); +} + +unsigned int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256mat_solve_linear_eq(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n) { + return gf256mat_solve_linear_eq_impl(sol, inp_mat, c_terms, n); +} + diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/blas_comm.h b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/blas_comm.h new file mode 100644 index 0000000000..e86298fe20 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/blas_comm.h @@ -0,0 +1,90 @@ +#ifndef _BLAS_COMM_H_ +#define _BLAS_COMM_H_ +/// @file blas_comm.h +/// @brief Common functions for linear algebra. +/// + +#include "rainbow_config.h" +#include + +/// @brief set a vector to 0. +/// +/// @param[in,out] b - the vector b. +/// @param[in] _num_byte - number of bytes for the vector b. +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_set_zero(uint8_t *b, unsigned int _num_byte); + +/// @brief get an element from GF(256) vector . +/// +/// @param[in] a - the input vector a. +/// @param[in] i - the index in the vector a. +/// @return the value of the element. +/// +uint8_t PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_get_ele(const uint8_t *a, unsigned int i); + +/// @brief check if a vector is 0. +/// +/// @param[in] a - the vector a. +/// @param[in] _num_byte - number of bytes for the vector a. +/// @return 1(true) if a is 0. 0(false) else. +/// +unsigned int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_is_zero(const uint8_t *a, unsigned int _num_byte); + +/// @brief polynomial multiplication: c = a*b +/// +/// @param[out] c - the output polynomial c +/// @param[in] a - the vector a. +/// @param[in] b - the vector b. +/// @param[in] _num - number of elements for the polynomials a and b. +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_polymul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int _num); + +/// @brief matrix-vector multiplication: c = matA * b , in GF(256) +/// +/// @param[out] c - the output vector c +/// @param[in] matA - a column-major matrix A. +/// @param[in] n_A_vec_byte - the size of column vectors in bytes. +/// @param[in] n_A_width - the width of matrix A. +/// @param[in] b - the vector b. +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256mat_prod(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b); + +/// @brief matrix-matrix multiplication: c = a * b , in GF(256) +/// +/// @param[out] c - the output matrix c +/// @param[in] c - a matrix a. +/// @param[in] b - a matrix b. +/// @param[in] len_vec - the length of column vectors. +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256mat_mul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int len_vec); + +/// @brief Gauss elimination for a matrix, in GF(256) +/// +/// @param[in,out] mat - the matrix. +/// @param[in] h - the height of the matrix. +/// @param[in] w - the width of the matrix. +/// @return 1(true) if success. 0(false) if the matrix is singular. +/// +unsigned int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256mat_gauss_elim(uint8_t *mat, unsigned int h, unsigned int w); + +/// @brief Solving linear equations, in GF(256) +/// +/// @param[out] sol - the solutions. +/// @param[in] inp_mat - the matrix parts of input equations. +/// @param[in] c_terms - the constant terms of the input equations. +/// @param[in] n - the number of equations. +/// @return 1(true) if success. 0(false) if the matrix is singular. +/// +unsigned int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256mat_solve_linear_eq(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n); + +/// @brief Computing the inverse matrix, in GF(256) +/// +/// @param[out] inv_a - the output of matrix a. +/// @param[in] a - a matrix a. +/// @param[in] H - height of matrix a, i.e., matrix a is an HxH matrix. +/// @param[in] buffer - The buffer for computations. it has to be as large as 2 input matrixes. +/// @return 1(true) if success. 0(false) if the matrix is singular. +/// +unsigned int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256mat_inv(uint8_t *inv_a, const uint8_t *a, unsigned int H, uint8_t *buffer); + +#endif // _BLAS_COMM_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/gf.c b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/gf.c new file mode 100644 index 0000000000..4f0462504f --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/gf.c @@ -0,0 +1,91 @@ +#include "gf.h" + +//// gf4 := gf2[x]/x^2+x+1 +static inline uint8_t gf4_mul_2(uint8_t a) { + uint8_t r = (uint8_t)(a << 1); + r ^= (uint8_t)((a >> 1) * 7); + return r; +} + +static inline uint8_t gf4_mul(uint8_t a, uint8_t b) { + uint8_t r = (uint8_t)(a * (b & 1)); + return r ^ (uint8_t)(gf4_mul_2(a) * (b >> 1)); +} + +static inline uint8_t gf4_squ(uint8_t a) { + return a ^ (a >> 1); +} + +//// gf16 := gf4[y]/y^2+y+x +uint8_t PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf16_mul(uint8_t a, uint8_t b) { + uint8_t a0 = a & 3; + uint8_t a1 = (a >> 2); + uint8_t b0 = b & 3; + uint8_t b1 = (b >> 2); + uint8_t a0b0 = gf4_mul(a0, b0); + uint8_t a1b1 = gf4_mul(a1, b1); + uint8_t a0b1_a1b0 = gf4_mul(a0 ^ a1, b0 ^ b1) ^ a0b0 ^ a1b1; + uint8_t a1b1_x2 = gf4_mul_2(a1b1); + return (uint8_t)((a0b1_a1b0 ^ a1b1) << 2 ^ a0b0 ^ a1b1_x2); +} + +static inline uint8_t gf16_squ(uint8_t a) { + uint8_t a0 = a & 3; + uint8_t a1 = (a >> 2); + a1 = gf4_squ(a1); + uint8_t a1squ_x2 = gf4_mul_2(a1); + return (uint8_t)((a1 << 2) ^ a1squ_x2 ^ gf4_squ(a0)); +} + +uint8_t PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256_is_nonzero(uint8_t a) { + unsigned int a8 = a; + unsigned int r = ((unsigned int)0) - a8; + r >>= 8; + return r & 1; +} + +static inline uint8_t gf4_mul_3(uint8_t a) { + uint8_t msk = (uint8_t)((a - 2) >> 1); + return (uint8_t)((msk & ((int)a * 3)) | ((~msk) & ((int)a - 1))); +} +static inline uint8_t gf16_mul_8(uint8_t a) { + uint8_t a0 = a & 3; + uint8_t a1 = a >> 2; + return (uint8_t)((gf4_mul_2(a0 ^ a1) << 2) | gf4_mul_3(a1)); +} + +// gf256 := gf16[X]/X^2+X+xy +uint8_t PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256_mul(uint8_t a, uint8_t b) { + uint8_t a0 = a & 15; + uint8_t a1 = (a >> 4); + uint8_t b0 = b & 15; + uint8_t b1 = (b >> 4); + uint8_t a0b0 = PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf16_mul(a0, b0); + uint8_t a1b1 = PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf16_mul(a1, b1); + uint8_t a0b1_a1b0 = PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf16_mul(a0 ^ a1, b0 ^ b1) ^ a0b0 ^ a1b1; + uint8_t a1b1_x8 = gf16_mul_8(a1b1); + return (uint8_t)((a0b1_a1b0 ^ a1b1) << 4 ^ a0b0 ^ a1b1_x8); +} + +static inline uint8_t gf256_squ(uint8_t a) { + uint8_t a0 = a & 15; + uint8_t a1 = (a >> 4); + a1 = gf16_squ(a1); + uint8_t a1squ_x8 = gf16_mul_8(a1); + return (uint8_t)((a1 << 4) ^ a1squ_x8 ^ gf16_squ(a0)); +} + +uint8_t PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256_inv(uint8_t a) { + // 128+64+32+16+8+4+2 = 254 + uint8_t a2 = gf256_squ(a); + uint8_t a4 = gf256_squ(a2); + uint8_t a8 = gf256_squ(a4); + uint8_t a4_2 = PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256_mul(a4, a2); + uint8_t a8_4_2 = PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256_mul(a4_2, a8); + uint8_t a64_ = gf256_squ(a8_4_2); + a64_ = gf256_squ(a64_); + a64_ = gf256_squ(a64_); + uint8_t a64_2 = PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256_mul(a64_, a8_4_2); + uint8_t a128_ = gf256_squ(a64_2); + return PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256_mul(a2, a128_); +} diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/gf.h b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/gf.h new file mode 100644 index 0000000000..e8c06d8446 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/gf.h @@ -0,0 +1,19 @@ +#ifndef _GF16_H_ +#define _GF16_H_ + +#include "rainbow_config.h" +#include + +/// @file gf16.h +/// @brief Library for arithmetics in GF(16) and GF(256) +/// + +uint8_t PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf16_mul(uint8_t a, uint8_t b); + + +uint8_t PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256_is_nonzero(uint8_t a); +uint8_t PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256_inv(uint8_t a); +uint8_t PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256_mul(uint8_t a, uint8_t b); + + +#endif // _GF16_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/parallel_matrix_op.c b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/parallel_matrix_op.c new file mode 100644 index 0000000000..540ae738f1 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/parallel_matrix_op.c @@ -0,0 +1,183 @@ +/// @file parallel_matrix_op.c +/// @brief the standard implementations for functions in parallel_matrix_op.h +/// +/// the standard implementations for functions in parallel_matrix_op.h +/// + +#include "parallel_matrix_op.h" +#include "blas.h" +#include "blas_comm.h" + +/// +/// @brief Calculate the corresponding index in an array for an upper-triangle(UT) matrix. +/// +/// @param[in] i_row - the i-th row in an upper-triangle matrix. +/// @param[in] j_col - the j-th column in an upper-triangle matrix. +/// @param[in] dim - the dimension of the upper-triangle matrix, i.e., an dim x dim matrix. +/// @return the corresponding index in an array storage. +/// +unsigned int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_idx_of_trimat(unsigned int i_row, unsigned int j_col, unsigned int dim) { + return (dim + dim - i_row + 1) * i_row / 2 + j_col - i_row; +} + +/// +/// @brief Calculate the corresponding index in an array for an upper-triangle or lower-triangle matrix. +/// +/// @param[in] i_row - the i-th row in a triangle matrix. +/// @param[in] j_col - the j-th column in a triangle matrix. +/// @param[in] dim - the dimension of the triangle matrix, i.e., an dim x dim matrix. +/// @return the corresponding index in an array storage. +/// +static inline unsigned int idx_of_2trimat(unsigned int i_row, unsigned int j_col, unsigned int n_var) { + if (i_row > j_col) { + return PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_idx_of_trimat(j_col, i_row, n_var); + } + return PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_idx_of_trimat(i_row, j_col, n_var); +} + +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_UpperTrianglize(unsigned char *btriC, const unsigned char *bA, unsigned int Awidth, unsigned int size_batch) { + unsigned char *runningC = btriC; + unsigned int Aheight = Awidth; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < i; j++) { + unsigned int idx = PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_idx_of_trimat(j, i, Aheight); + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_add(btriC + idx * size_batch, bA + size_batch * (i * Awidth + j), size_batch); + } + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_add(runningC, bA + size_batch * (i * Awidth + i), size_batch * (Aheight - i)); + runningC += size_batch * (Aheight - i); + } +} + +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Awidth = Bheight; + unsigned int Aheight = Awidth; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + if (k < i) { + continue; + } + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_madd(bC, &btriA[(k - i) * size_batch], PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + btriA += (Aheight - i) * size_batch; + } +} + +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_trimatTr_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Aheight = Bheight; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + if (i < k) { + continue; + } + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_madd(bC, &btriA[size_batch * (PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_idx_of_trimat(k, i, Aheight))], PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_2trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Aheight = Bheight; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + if (i == k) { + continue; + } + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_madd(bC, &btriA[size_batch * (idx_of_2trimat(i, k, Aheight))], PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_matTr_madd_gf256(unsigned char *bC, const unsigned char *A_to_tr, unsigned int Aheight, unsigned int size_Acolvec, unsigned int Awidth, + const unsigned char *bB, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Atr_height = Awidth; + unsigned int Atr_width = Aheight; + for (unsigned int i = 0; i < Atr_height; i++) { + for (unsigned int j = 0; j < Atr_width; j++) { + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_madd(bC, &bB[j * Bwidth * size_batch], PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_get_ele(&A_to_tr[size_Acolvec * i], j), size_batch * Bwidth); + } + bC += size_batch * Bwidth; + } +} + +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_bmatTr_madd_gf256(unsigned char *bC, const unsigned char *bA_to_tr, unsigned int Awidth_before_tr, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + const unsigned char *bA = bA_to_tr; + unsigned int Aheight = Awidth_before_tr; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_madd(bC, &bA[size_batch * (i + k * Aheight)], PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_mat_madd_gf256(unsigned char *bC, const unsigned char *bA, unsigned int Aheight, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Awidth = Bheight; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_madd(bC, &bA[k * size_batch], PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + bA += (Awidth) * size_batch; + } +} + +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_quad_trimat_eval_gf256(unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned int dim, unsigned int size_batch) { + unsigned char tmp[256]; + + unsigned char _x[256]; + for (unsigned int i = 0; i < dim; i++) { + _x[i] = PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_get_ele(x, i); + } + + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_set_zero(y, size_batch); + for (unsigned int i = 0; i < dim; i++) { + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_set_zero(tmp, size_batch); + for (unsigned int j = i; j < dim; j++) { + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_madd(tmp, trimat, _x[j], size_batch); + trimat += size_batch; + } + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_madd(y, tmp, _x[i], size_batch); + } +} + +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_quad_recmat_eval_gf256(unsigned char *z, const unsigned char *y, unsigned int dim_y, const unsigned char *mat, + const unsigned char *x, unsigned dim_x, unsigned size_batch) { + unsigned char tmp[128]; + + unsigned char _x[128]; + for (unsigned int i = 0; i < dim_x; i++) { + _x[i] = PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_get_ele(x, i); + } + unsigned char _y[128]; + for (unsigned int i = 0; i < dim_y; i++) { + _y[i] = PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_get_ele(y, i); + } + + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_set_zero(z, size_batch); + for (unsigned int i = 0; i < dim_y; i++) { + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_set_zero(tmp, size_batch); + for (unsigned int j = 0; j < dim_x; j++) { + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_madd(tmp, mat, _x[j], size_batch); + mat += size_batch; + } + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_madd(z, tmp, _y[i], size_batch); + } +} + diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/parallel_matrix_op.h b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/parallel_matrix_op.h new file mode 100644 index 0000000000..63d8231113 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/parallel_matrix_op.h @@ -0,0 +1,260 @@ +#ifndef _P_MATRIX_OP_H_ +#define _P_MATRIX_OP_H_ +/// @file parallel_matrix_op.h +/// @brief Librarys for operations of batched matrixes. +/// +/// + +//////////////// Section: triangle matrix <-> rectangle matrix /////////////////////////////////// + +/// +/// @brief Calculate the corresponding index in an array for an upper-triangle(UT) matrix. +/// +/// @param[in] i_row - the i-th row in an upper-triangle matrix. +/// @param[in] j_col - the j-th column in an upper-triangle matrix. +/// @param[in] dim - the dimension of the upper-triangle matrix, i.e., an dim x dim matrix. +/// @return the corresponding index in an array storage. +/// +unsigned int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_idx_of_trimat(unsigned int i_row, unsigned int j_col, unsigned int dim); + +/// +/// @brief Upper trianglize a rectangle matrix to the corresponding upper-trangle matrix. +/// +/// @param[out] btriC - the batched upper-trianglized matrix C. +/// @param[in] bA - a batched retangle matrix A. +/// @param[in] bwidth - the width of the batched matrix A, i.e., A is a Awidth x Awidth matrix. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_UpperTrianglize(unsigned char *btriC, const unsigned char *bA, unsigned int Awidth, unsigned int size_batch); + +//////////////////// Section: matrix multiplications /////////////////////////////// + +/// +/// @brief bC += btriA * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_trimat_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += btriA * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += btriA^Tr * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. A will be transposed while multiplying. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_trimatTr_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += btriA^Tr * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A, which will be transposed while multiplying. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_trimatTr_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += (btriA + btriA^Tr) *B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. The operand for multiplication is (btriA + btriA^Tr). +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_2trimat_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += (btriA + btriA^Tr) *B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. The operand for multiplication is (btriA + btriA^Tr). +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_2trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += A^Tr * bB , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] A_to_tr - a column-major matrix A. The operand for multiplication is A^Tr. +/// @param[in] Aheight - the height of A. +/// @param[in] size_Acolvec - the size of a column vector in A. +/// @param[in] Awidth - the width of A. +/// @param[in] bB - a batched matrix B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_matTr_madd_gf16(unsigned char *bC, + const unsigned char *A_to_tr, unsigned int Aheight, unsigned int size_Acolvec, unsigned int Awidth, + const unsigned char *bB, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += A^Tr * bB , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] A_to_tr - a column-major matrix A. The operand for multiplication is A^Tr. +/// @param[in] Aheight - the height of A. +/// @param[in] size_Acolvec - the size of a column vector in A. +/// @param[in] Awidth - the width of A. +/// @param[in] bB - a batched matrix B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_matTr_madd_gf256(unsigned char *bC, + const unsigned char *A_to_tr, unsigned int Aheight, unsigned int size_Acolvec, unsigned int Awidth, + const unsigned char *bB, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA^Tr * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA_to_tr - a batched matrix A. The operand for multiplication is (bA^Tr). +/// @param[in] Awidth_befor_tr - the width of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_bmatTr_madd_gf16(unsigned char *bC, const unsigned char *bA_to_tr, unsigned int Awidth_before_tr, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA^Tr * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA_to_tr - a batched matrix A. The operand for multiplication is (bA^Tr). +/// @param[in] Awidth_befor_tr - the width of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_bmatTr_madd_gf256(unsigned char *bC, const unsigned char *bA_to_tr, unsigned int Awidth_before_tr, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA - a batched matrix A. +/// @param[in] Aheigh - the height of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_mat_madd_gf16(unsigned char *bC, const unsigned char *bA, unsigned int Aheight, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA - a batched matrix A. +/// @param[in] Aheigh - the height of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_mat_madd_gf256(unsigned char *bC, const unsigned char *bA, unsigned int Aheight, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +//////////////////// Section: "quadratric" matrix evaluation /////////////////////////////// + +/// +/// @brief y = x^Tr * trimat * x , in GF(16) +/// +/// @param[out] y - the returned batched element y. +/// @param[in] trimat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim - the dimension of matrix trimat (and x). +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_quad_trimat_eval_gf16(unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned int dim, unsigned int size_batch); + +/// +/// @brief y = x^Tr * trimat * x , in GF(256) +/// +/// @param[out] y - the returned batched element y. +/// @param[in] trimat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim - the dimension of matrix trimat (and x). +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_quad_trimat_eval_gf256(unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned int dim, unsigned int size_batch); + +/// +/// @brief z = y^Tr * mat * x , in GF(16) +/// +/// @param[out] z - the returned batched element z. +/// @param[in] y - an input vector y. +/// @param[in] dim_y - the length of y. +/// @param[in] mat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim_x - the length of x. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_quad_recmat_eval_gf16(unsigned char *z, const unsigned char *y, unsigned int dim_y, + const unsigned char *mat, const unsigned char *x, unsigned int dim_x, unsigned int size_batch); + +/// +/// @brief z = y^Tr * mat * x , in GF(256) +/// +/// @param[out] z - the returned batched element z. +/// @param[in] y - an input vector y. +/// @param[in] dim_y - the length of y. +/// @param[in] mat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim_x - the length of x. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_quad_recmat_eval_gf256(unsigned char *z, const unsigned char *y, unsigned int dim_y, + const unsigned char *mat, const unsigned char *x, unsigned int dim_x, unsigned int size_batch); + +#endif // _P_MATRIX_OP_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/rainbow.c b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/rainbow.c new file mode 100644 index 0000000000..4dc14cfaed --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/rainbow.c @@ -0,0 +1,179 @@ +/// @file rainbow.c +/// @brief The standard implementations for functions in rainbow.h +/// + +#include "blas.h" +#include "parallel_matrix_op.h" +#include "rainbow.h" +#include "rainbow_blas.h" +#include "rainbow_config.h" +#include "rainbow_keypair.h" +#include "utils_hash.h" +#include "utils_prng.h" +#include +#include +#include + +#define MAX_ATTEMPT_FRMAT 128 + +int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_rainbow_sign(uint8_t *signature, const sk_t *sk, const uint8_t *_digest) { + uint8_t mat_l1[_O1 * _O1_BYTE]; + uint8_t mat_l2[_O2 * _O2_BYTE]; + uint8_t mat_buffer[2 * _MAX_O * _MAX_O_BYTE]; + + // setup PRNG + prng_t prng_sign; + uint8_t prng_preseed[LEN_SKSEED + _HASH_LEN]; + memcpy(prng_preseed, sk->sk_seed, LEN_SKSEED); + memcpy(prng_preseed + LEN_SKSEED, _digest, _HASH_LEN); // prng_preseed = sk_seed || digest + uint8_t prng_seed[_HASH_LEN]; + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_hash_msg(prng_seed, _HASH_LEN, prng_preseed, _HASH_LEN + LEN_SKSEED); + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_prng_set(&prng_sign, prng_seed, _HASH_LEN); // seed = H( sk_seed || digest ) + for (unsigned int i = 0; i < LEN_SKSEED + _HASH_LEN; i++) { + prng_preseed[i] ^= prng_preseed[i]; // clean + } + for (unsigned int i = 0; i < _HASH_LEN; i++) { + prng_seed[i] ^= prng_seed[i]; // clean + } + + // roll vinegars. + uint8_t vinegar[_V1_BYTE]; + unsigned int n_attempt = 0; + unsigned int l1_succ = 0; + while (!l1_succ) { + if (MAX_ATTEMPT_FRMAT <= n_attempt) { + break; + } + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_prng_gen(&prng_sign, vinegar, _V1_BYTE); // generating vinegars + gfmat_prod(mat_l1, sk->l1_F2, _O1 * _O1_BYTE, _V1, vinegar); // generating the linear equations for layer 1 + l1_succ = gfmat_inv(mat_l1, mat_l1, _O1, mat_buffer); // check if the linear equation solvable + n_attempt++; + } + + // Given the vinegars, pre-compute variables needed for layer 2 + uint8_t r_l1_F1[_O1_BYTE] = {0}; + uint8_t r_l2_F1[_O2_BYTE] = {0}; + batch_quad_trimat_eval(r_l1_F1, sk->l1_F1, vinegar, _V1, _O1_BYTE); + batch_quad_trimat_eval(r_l2_F1, sk->l2_F1, vinegar, _V1, _O2_BYTE); + uint8_t mat_l2_F3[_O2 * _O2_BYTE]; + uint8_t mat_l2_F2[_O1 * _O2_BYTE]; + gfmat_prod(mat_l2_F3, sk->l2_F3, _O2 * _O2_BYTE, _V1, vinegar); + gfmat_prod(mat_l2_F2, sk->l2_F2, _O1 * _O2_BYTE, _V1, vinegar); + + // Some local variables. + uint8_t _z[_PUB_M_BYTE]; + uint8_t y[_PUB_M_BYTE]; + uint8_t *x_v1 = vinegar; + uint8_t x_o1[_O1_BYTE]; + uint8_t x_o2[_O1_BYTE]; + + uint8_t digest_salt[_HASH_LEN + _SALT_BYTE]; + memcpy(digest_salt, _digest, _HASH_LEN); + uint8_t *salt = digest_salt + _HASH_LEN; + + uint8_t temp_o[_MAX_O_BYTE + 32] = {0}; + unsigned int succ = 0; + while (!succ) { + if (MAX_ATTEMPT_FRMAT <= n_attempt) { + break; + } + // The computation: H(digest||salt) --> z --S--> y --C-map--> x --T--> w + + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_prng_gen(&prng_sign, salt, _SALT_BYTE); // roll the salt + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_hash_msg(_z, _PUB_M_BYTE, digest_salt, _HASH_LEN + _SALT_BYTE); // H(digest||salt) + + // y = S^-1 * z + memcpy(y, _z, _PUB_M_BYTE); // identity part of S + gfmat_prod(temp_o, sk->s1, _O1_BYTE, _O2, _z + _O1_BYTE); + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_add(y, temp_o, _O1_BYTE); + + // Central Map: + // layer 1: calculate x_o1 + memcpy(temp_o, r_l1_F1, _O1_BYTE); + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_add(temp_o, y, _O1_BYTE); + gfmat_prod(x_o1, mat_l1, _O1_BYTE, _O1, temp_o); + + // layer 2: calculate x_o2 + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_set_zero(temp_o, _O2_BYTE); + gfmat_prod(temp_o, mat_l2_F2, _O2_BYTE, _O1, x_o1); // F2 + batch_quad_trimat_eval(mat_l2, sk->l2_F5, x_o1, _O1, _O2_BYTE); // F5 + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_add(temp_o, mat_l2, _O2_BYTE); + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_add(temp_o, r_l2_F1, _O2_BYTE); // F1 + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_add(temp_o, y + _O1_BYTE, _O2_BYTE); + + // generate the linear equations of the 2nd layer + gfmat_prod(mat_l2, sk->l2_F6, _O2 * _O2_BYTE, _O1, x_o1); // F6 + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_add(mat_l2, mat_l2_F3, _O2 * _O2_BYTE); // F3 + succ = gfmat_inv(mat_l2, mat_l2, _O2, mat_buffer); + gfmat_prod(x_o2, mat_l2, _O2_BYTE, _O2, temp_o); // solve l2 eqs + + n_attempt++; + }; + // w = T^-1 * y + uint8_t w[_PUB_N_BYTE]; + // identity part of T. + memcpy(w, x_v1, _V1_BYTE); + memcpy(w + _V1_BYTE, x_o1, _O1_BYTE); + memcpy(w + _V2_BYTE, x_o2, _O2_BYTE); + // Computing the t1 part. + gfmat_prod(y, sk->t1, _V1_BYTE, _O1, x_o1); + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_add(w, y, _V1_BYTE); + // Computing the t4 part. + gfmat_prod(y, sk->t4, _V1_BYTE, _O2, x_o2); + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_add(w, y, _V1_BYTE); + // Computing the t3 part. + gfmat_prod(y, sk->t3, _O1_BYTE, _O2, x_o2); + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_add(w + _V1_BYTE, y, _O1_BYTE); + + memset(signature, 0, _SIGNATURE_BYTE); // set the output 0 + // clean + memset(&prng_sign, 0, sizeof(prng_t)); + memset(vinegar, 0, _V1_BYTE); + memset(r_l1_F1, 0, _O1_BYTE); + memset(r_l2_F1, 0, _O2_BYTE); + memset(_z, 0, _PUB_M_BYTE); + memset(y, 0, _PUB_M_BYTE); + memset(x_o1, 0, _O1_BYTE); + memset(x_o2, 0, _O2_BYTE); + memset(temp_o, 0, sizeof(temp_o)); + + // return: copy w and salt to the signature. + if (MAX_ATTEMPT_FRMAT <= n_attempt) { + return -1; + } + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_add(signature, w, _PUB_N_BYTE); + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_add(signature + _PUB_N_BYTE, salt, _SALT_BYTE); + return 0; +} + +int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_rainbow_verify(const uint8_t *digest, const uint8_t *signature, const pk_t *pk) { + unsigned char digest_ck[_PUB_M_BYTE]; + // public_map( digest_ck , pk , signature ); Evaluating the quadratic public polynomials. + batch_quad_trimat_eval(digest_ck, pk->pk, signature, _PUB_N, _PUB_M_BYTE); + + unsigned char correct[_PUB_M_BYTE]; + unsigned char digest_salt[_HASH_LEN + _SALT_BYTE]; + memcpy(digest_salt, digest, _HASH_LEN); + memcpy(digest_salt + _HASH_LEN, signature + _PUB_N_BYTE, _SALT_BYTE); + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_hash_msg(correct, _PUB_M_BYTE, digest_salt, _HASH_LEN + _SALT_BYTE); // H( digest || salt ) + + // check consistancy. + unsigned char cc = 0; + for (unsigned int i = 0; i < _PUB_M_BYTE; i++) { + cc |= (digest_ck[i] ^ correct[i]); + } + return (0 == cc) ? 0 : -1; +} + +/////////////// cyclic version /////////////////////////// +int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_rainbow_sign_cyclic(uint8_t *signature, const csk_t *csk, const uint8_t *digest) { + unsigned char sk[sizeof(sk_t) + 32]; + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_generate_secretkey_cyclic((sk_t *)sk, csk->pk_seed, csk->sk_seed); // generating classic secret key. + return PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_rainbow_sign(signature, (sk_t *)sk, digest); +} + +int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_rainbow_verify_cyclic(const uint8_t *digest, const uint8_t *signature, const cpk_t *_pk) { + unsigned char pk[sizeof(pk_t) + 32]; + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_cpk_to_pk((pk_t *)pk, _pk); // generating classic public key. + return PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_rainbow_verify(digest, signature, (pk_t *)pk); +} diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/rainbow.h b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/rainbow.h new file mode 100644 index 0000000000..7decea2a99 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/rainbow.h @@ -0,0 +1,50 @@ +#ifndef _RAINBOW_H_ +#define _RAINBOW_H_ +/// @file rainbow.h +/// @brief APIs for rainbow. +/// + +#include "rainbow_config.h" +#include "rainbow_keypair.h" + +#include + +/// +/// @brief Signing function for classical secret key. +/// +/// @param[out] signature - the signature. +/// @param[in] sk - the secret key. +/// @param[in] digest - the digest. +/// +int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_rainbow_sign(uint8_t *signature, const sk_t *sk, const uint8_t *digest); + +/// +/// @brief Verifying function. +/// +/// @param[in] digest - the digest. +/// @param[in] signature - the signature. +/// @param[in] pk - the public key. +/// @return 0 for successful verified. -1 for failed verification. +/// +int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_rainbow_verify(const uint8_t *digest, const uint8_t *signature, const pk_t *pk); + +/// +/// @brief Signing function for compressed secret key of the cyclic rainbow. +/// +/// @param[out] signature - the signature. +/// @param[in] sk - the compressed secret key. +/// @param[in] digest - the digest. +/// +int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_rainbow_sign_cyclic(uint8_t *signature, const csk_t *sk, const uint8_t *digest); + +/// +/// @brief Verifying function for cyclic public keys. +/// +/// @param[in] digest - the digest. +/// @param[in] signature - the signature. +/// @param[in] pk - the public key of cyclic rainbow. +/// @return 0 for successful verified. -1 for failed verification. +/// +int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_rainbow_verify_cyclic(const uint8_t *digest, const uint8_t *signature, const cpk_t *pk); + +#endif // _RAINBOW_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/rainbow_blas.h b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/rainbow_blas.h new file mode 100644 index 0000000000..90fd2a0143 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/rainbow_blas.h @@ -0,0 +1,32 @@ +#ifndef _RAINBOW_BLAS_H_ +#define _RAINBOW_BLAS_H_ +/// @file rainbow_blas.h +/// @brief Defining the functions used in rainbow.c acconding to the definitions in rainbow_config.h +/// +/// Defining the functions used in rainbow.c acconding to the definitions in rainbow_config.h + +#include "blas.h" +#include "blas_comm.h" +#include "parallel_matrix_op.h" +#include "rainbow_config.h" + + +#define gfv_get_ele PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_get_ele +#define gfv_mul_scalar PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_mul_scalar +#define gfv_madd PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_madd + +#define gfmat_prod PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256mat_prod +#define gfmat_inv PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256mat_inv + +#define batch_trimat_madd PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_trimat_madd_gf256 +#define batch_trimatTr_madd PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_trimatTr_madd_gf256 +#define batch_2trimat_madd PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_2trimat_madd_gf256 +#define batch_matTr_madd PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_matTr_madd_gf256 +#define batch_bmatTr_madd PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_bmatTr_madd_gf256 +#define batch_mat_madd PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_mat_madd_gf256 + +#define batch_quad_trimat_eval PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_quad_trimat_eval_gf256 +#define batch_quad_recmat_eval PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_batch_quad_recmat_eval_gf256 + + +#endif // _RAINBOW_BLAS_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/rainbow_config.h b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/rainbow_config.h new file mode 100644 index 0000000000..b8bb361d69 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/rainbow_config.h @@ -0,0 +1,48 @@ +#ifndef _H_RAINBOW_CONFIG_H_ +#define _H_RAINBOW_CONFIG_H_ + +/// @file rainbow_config.h +/// @brief Defining the parameters of the Rainbow and the corresponding constants. +/// + +#define _GFSIZE 256 +#define _V1 68 +#define _O1 36 +#define _O2 36 +#define _MAX_O 36 +#define _HASH_LEN 48 + + +#define _V2 ((_V1) + (_O1)) + +/// size of N, in # of gf elements. +#define _PUB_N (_V1 + _O1 + _O2) + +/// size of M, in # gf elements. +#define _PUB_M (_O1 + _O2) + +/// size of variables, in # bytes. + +// GF256 +#define _V1_BYTE (_V1) +#define _V2_BYTE (_V2) +#define _O1_BYTE (_O1) +#define _O2_BYTE (_O2) +#define _MAX_O_BYTE (_MAX_O) +#define _PUB_N_BYTE (_PUB_N) +#define _PUB_M_BYTE (_PUB_M) + + +/// length of seed for public key, in # bytes +#define LEN_PKSEED 32 + +/// length of seed for secret key, in # bytes +#define LEN_SKSEED 32 + +/// length of salt for a signature, in # bytes +#define _SALT_BYTE 16 + +/// length of a signature +#define _SIGNATURE_BYTE (_PUB_N_BYTE + _SALT_BYTE) + +#endif // _H_RAINBOW_CONFIG_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/rainbow_keypair.c b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/rainbow_keypair.c new file mode 100644 index 0000000000..9c31685483 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/rainbow_keypair.c @@ -0,0 +1,188 @@ +/// @file rainbow_keypair.c +/// @brief implementations of functions in rainbow_keypair.h +/// + +#include "rainbow_keypair.h" +#include "blas.h" +#include "blas_comm.h" +#include "rainbow_blas.h" +#include "rainbow_keypair_computation.h" +#include "utils_prng.h" +#include +#include +#include + +static void generate_S_T(unsigned char *s_and_t, prng_t *prng0) { + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_prng_gen(prng0, s_and_t, _O1_BYTE * _O2); // S1 + s_and_t += _O1_BYTE * _O2; + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_prng_gen(prng0, s_and_t, _V1_BYTE * _O1); // T1 + s_and_t += _V1_BYTE * _O1; + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_prng_gen(prng0, s_and_t, _V1_BYTE * _O2); // T2 + s_and_t += _V1_BYTE * _O2; + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_prng_gen(prng0, s_and_t, _O1_BYTE * _O2); // T3 +} + +static unsigned int generate_l1_F12(unsigned char *sk, prng_t *prng0) { + unsigned int n_byte_generated = 0; + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_prng_gen(prng0, sk, _O1_BYTE * N_TRIANGLE_TERMS(_V1)); // l1_F1 + sk += _O1_BYTE * N_TRIANGLE_TERMS(_V1); + n_byte_generated += _O1_BYTE * N_TRIANGLE_TERMS(_V1); + + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_prng_gen(prng0, sk, _O1_BYTE * _V1 * _O1); // l1_F2 + n_byte_generated += _O1_BYTE * _V1 * _O1; + return n_byte_generated; +} + +static unsigned int generate_l2_F12356(unsigned char *sk, prng_t *prng0) { + unsigned int n_byte_generated = 0; + + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_prng_gen(prng0, sk, _O2_BYTE * N_TRIANGLE_TERMS(_V1)); // l2_F1 + sk += _O2_BYTE * N_TRIANGLE_TERMS(_V1); + n_byte_generated += _O2_BYTE * N_TRIANGLE_TERMS(_V1); + + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_prng_gen(prng0, sk, _O2_BYTE * _V1 * _O1); // l2_F2 + sk += _O2_BYTE * _V1 * _O1; + n_byte_generated += _O2_BYTE * _V1 * _O1; + + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_prng_gen(prng0, sk, _O2_BYTE * _V1 * _O2); // l2_F3 + sk += _O2_BYTE * _V1 * _O1; + n_byte_generated += _O2_BYTE * _V1 * _O1; + + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_prng_gen(prng0, sk, _O2_BYTE * N_TRIANGLE_TERMS(_O1)); // l2_F5 + sk += _O2_BYTE * N_TRIANGLE_TERMS(_O1); + n_byte_generated += _O2_BYTE * N_TRIANGLE_TERMS(_O1); + + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_prng_gen(prng0, sk, _O2_BYTE * _O1 * _O2); // l2_F6 + n_byte_generated += _O2_BYTE * _O1 * _O2; + + return n_byte_generated; +} + +static void generate_B1_B2(unsigned char *sk, prng_t *prng0) { + sk += generate_l1_F12(sk, prng0); + generate_l2_F12356(sk, prng0); +} + +static void calculate_t4(unsigned char *t2_to_t4, const unsigned char *t1, const unsigned char *t3) { + // t4 = T_sk.t1 * T_sk.t3 - T_sk.t2 + unsigned char temp[_V1_BYTE + 32]; + unsigned char *t4 = t2_to_t4; + for (unsigned int i = 0; i < _O2; i++) { /// t3 width + gfmat_prod(temp, t1, _V1_BYTE, _O1, t3); + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_add(t4, temp, _V1_BYTE); + t4 += _V1_BYTE; + t3 += _O1_BYTE; + } +} + +static void obsfucate_l1_polys(unsigned char *l1_polys, const unsigned char *l2_polys, unsigned int n_terms, const unsigned char *s1) { + unsigned char temp[_O1_BYTE + 32]; + while (n_terms--) { + gfmat_prod(temp, s1, _O1_BYTE, _O2, l2_polys); + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_gf256v_add(l1_polys, temp, _O1_BYTE); + l1_polys += _O1_BYTE; + l2_polys += _O2_BYTE; + } +} + +/////////////////// Classic ////////////////////////////////// + + +///////////////////// Cyclic ////////////////////////////////// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_generate_keypair_cyclic(cpk_t *pk, sk_t *sk, const unsigned char *pk_seed, const unsigned char *sk_seed) { + memcpy(pk->pk_seed, pk_seed, LEN_PKSEED); + memcpy(sk->sk_seed, sk_seed, LEN_SKSEED); + + // prng for sk + prng_t prng; + prng_t *prng0 = &prng; + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_prng_set(prng0, sk_seed, LEN_SKSEED); + generate_S_T(sk->s1, prng0); // S,T: only a part of sk + + unsigned char t2[sizeof(sk->t4)]; + memcpy(t2, sk->t4, _V1_BYTE * _O2); // temporarily store t2 + calculate_t4(sk->t4, sk->t1, sk->t3); // t2 <- t4 + + // prng for pk + sk_t inst_Qs; + sk_t *Qs = &inst_Qs; + prng_t *prng1 = &prng; + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_prng_set(prng1, pk_seed, LEN_PKSEED); + generate_B1_B2(Qs->l1_F1, prng1); // generating l1_Q1, l1_Q2, l2_Q1, l2_Q2, l2_Q3, l2_Q5, l2_Q6 + obsfucate_l1_polys(Qs->l1_F1, Qs->l2_F1, N_TRIANGLE_TERMS(_V1), sk->s1); + obsfucate_l1_polys(Qs->l1_F2, Qs->l2_F2, _V1 * _O1, sk->s1); + // so far, the Qs contains l1_F1, l1_F2, l2_F1, l2_F2, l2_F3, l2_F5, l2_F6. + + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_calculate_F_from_Q(sk, Qs, sk); // calcuate the rest parts of secret key from Qs and S,T + + unsigned char t4[sizeof(sk->t4)]; + memcpy(t4, sk->t4, _V1_BYTE * _O2); // temporarily store t4 + memcpy(sk->t4, t2, _V1_BYTE * _O2); // restore t2 + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_calculate_Q_from_F_cyclic(pk, sk, sk); // calculate the rest parts of public key: l1_Q3, l1_Q5, l1_Q6, l1_Q9, l2_Q9 + memcpy(sk->t4, t4, _V1_BYTE * _O2); // restore t4 + + obsfucate_l1_polys(pk->l1_Q3, Qs->l2_F3, _V1 * _O2, sk->s1); + obsfucate_l1_polys(pk->l1_Q5, Qs->l2_F5, N_TRIANGLE_TERMS(_O1), sk->s1); + obsfucate_l1_polys(pk->l1_Q6, Qs->l2_F6, _O1 * _O2, sk->s1); + obsfucate_l1_polys(pk->l1_Q9, pk->l2_Q9, N_TRIANGLE_TERMS(_O2), sk->s1); + + // clean + memset(&prng, 0, sizeof(prng_t)); +} + + +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_generate_compact_keypair_cyclic(cpk_t *pk, csk_t *rsk, const unsigned char *pk_seed, const unsigned char *sk_seed) { + memcpy(rsk->pk_seed, pk_seed, LEN_PKSEED); + memcpy(rsk->sk_seed, sk_seed, LEN_SKSEED); + sk_t sk; + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_generate_keypair_cyclic(pk, &sk, pk_seed, sk_seed); +} + +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_generate_secretkey_cyclic(sk_t *sk, const unsigned char *pk_seed, const unsigned char *sk_seed) { + memcpy(sk->sk_seed, sk_seed, LEN_SKSEED); + + // prng for sk + prng_t prng0; + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_prng_set(&prng0, sk_seed, LEN_SKSEED); + generate_S_T(sk->s1, &prng0); + calculate_t4(sk->t4, sk->t1, sk->t3); + + // prng for pk + sk_t inst_Qs; + sk_t *Qs = &inst_Qs; + prng_t prng1; + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_prng_set(&prng1, pk_seed, LEN_PKSEED); + generate_B1_B2(Qs->l1_F1, &prng1); + + obsfucate_l1_polys(Qs->l1_F1, Qs->l2_F1, N_TRIANGLE_TERMS(_V1), sk->s1); + obsfucate_l1_polys(Qs->l1_F2, Qs->l2_F2, _V1 * _O1, sk->s1); + + // calcuate the parts of sk according to pk. + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_calculate_F_from_Q(sk, Qs, sk); + + // clean prng for sk + memset(&prng0, 0, sizeof(prng_t)); +} +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_cpk_to_pk(pk_t *rpk, const cpk_t *cpk) { + // procedure: cpk_t --> extcpk_t --> pk_t + + // convert from cpk_t to extcpk_t + ext_cpk_t pk; + + // setup prng + prng_t prng0; + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_prng_set(&prng0, cpk->pk_seed, LEN_SKSEED); + + // generating parts of key with prng + generate_l1_F12(pk.l1_Q1, &prng0); + // copying parts of key from input. l1_Q3, l1_Q5, l1_Q6, l1_Q9 + memcpy(pk.l1_Q3, cpk->l1_Q3, _O1_BYTE * (_V1 * _O2 + N_TRIANGLE_TERMS(_O1) + _O1 * _O2 + N_TRIANGLE_TERMS(_O2))); + + // generating parts of key with prng + generate_l2_F12356(pk.l2_Q1, &prng0); + // copying parts of key from input: l2_Q9 + memcpy(pk.l2_Q9, cpk->l2_Q9, _O2_BYTE * N_TRIANGLE_TERMS(_O2)); + + // convert from extcpk_t to pk_t + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_extcpk_to_pk(rpk, &pk); +} diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/rainbow_keypair.h b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/rainbow_keypair.h new file mode 100644 index 0000000000..4ca8876e15 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/rainbow_keypair.h @@ -0,0 +1,111 @@ +#ifndef _RAINBOW_KEYPAIR_H_ +#define _RAINBOW_KEYPAIR_H_ +/// @file rainbow_keypair.h +/// @brief Formats of key pairs and functions for generating key pairs. +/// Formats of key pairs and functions for generating key pairs. +/// + +#include "rainbow_config.h" + +#define N_TRIANGLE_TERMS(n_var) ((n_var) * ((n_var) + 1) / 2) + +/// @brief public key for classic rainbow +/// +/// public key for classic rainbow +/// +typedef struct rainbow_publickey { + unsigned char pk[(_PUB_M_BYTE)*N_TRIANGLE_TERMS(_PUB_N)]; +} pk_t; + +/// @brief secret key for classic rainbow +/// +/// secret key for classic rainbow +/// +typedef struct rainbow_secretkey { + /// + /// seed for generating secret key. + /// Generating S, T, and F for classic rainbow. + /// Generating S and T only for cyclic rainbow. + unsigned char sk_seed[LEN_SKSEED]; + + unsigned char s1[_O1_BYTE * _O2]; ///< part of S map + unsigned char t1[_V1_BYTE * _O1]; ///< part of T map + unsigned char t4[_V1_BYTE * _O2]; ///< part of T map + unsigned char t3[_O1_BYTE * _O2]; ///< part of T map + + unsigned char l1_F1[_O1_BYTE * N_TRIANGLE_TERMS(_V1)]; ///< part of C-map, F1, Layer1 + unsigned char l1_F2[_O1_BYTE * _V1 * _O1]; ///< part of C-map, F2, Layer1 + + unsigned char l2_F1[_O2_BYTE * N_TRIANGLE_TERMS(_V1)]; ///< part of C-map, F1, Layer2 + unsigned char l2_F2[_O2_BYTE * _V1 * _O1]; ///< part of C-map, F2, Layer2 + + unsigned char l2_F3[_O2_BYTE * _V1 * _O2]; ///< part of C-map, F3, Layer2 + unsigned char l2_F5[_O2_BYTE * N_TRIANGLE_TERMS(_O1)]; ///< part of C-map, F5, Layer2 + unsigned char l2_F6[_O2_BYTE * _O1 * _O2]; ///< part of C-map, F6, Layer2 +} sk_t; + +/// @brief public key for cyclic rainbow +/// +/// public key for cyclic rainbow +/// +typedef struct rainbow_publickey_cyclic { + unsigned char pk_seed[LEN_PKSEED]; ///< seed for generating l1_Q1,l1_Q2,l2_Q1,l2_Q2,l2_Q3,l2_Q5,l2_Q6 + + unsigned char l1_Q3[_O1_BYTE * _V1 * _O2]; ///< Q3, layer1 + unsigned char l1_Q5[_O1_BYTE * N_TRIANGLE_TERMS(_O1)]; ///< Q5, layer1 + unsigned char l1_Q6[_O1_BYTE * _O1 * _O2]; ///< Q6, layer1 + unsigned char l1_Q9[_O1_BYTE * N_TRIANGLE_TERMS(_O2)]; ///< Q9, layer1 + + unsigned char l2_Q9[_O2_BYTE * N_TRIANGLE_TERMS(_O2)]; ///< Q9, layer2 +} cpk_t; + +/// @brief compressed secret key for cyclic rainbow +/// +/// compressed secret key for cyclic rainbow +/// +typedef struct rainbow_secretkey_cyclic { + unsigned char pk_seed[LEN_PKSEED]; ///< seed for generating a part of public key. + unsigned char sk_seed[LEN_SKSEED]; ///< seed for generating a part of secret key. +} csk_t; + + +/// +/// @brief Generate key pairs for cyclic rainbow. +/// +/// @param[out] pk - the public key. +/// @param[out] sk - the secret key. +/// @param[in] pk_seed - seed for generating parts of public key. +/// @param[in] sk_seed - seed for generating secret key. +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_generate_keypair_cyclic(cpk_t *pk, sk_t *sk, const unsigned char *pk_seed, const unsigned char *sk_seed); + +/// +/// @brief Generate compressed key pairs for cyclic rainbow. +/// +/// @param[out] pk - the public key. +/// @param[out] sk - the compressed secret key. +/// @param[in] pk_seed - seed for generating parts of the public key. +/// @param[in] sk_seed - seed for generating the secret key. +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_generate_compact_keypair_cyclic(cpk_t *pk, csk_t *sk, const unsigned char *pk_seed, const unsigned char *sk_seed); + +/// +/// @brief Generate secret key for cyclic rainbow. +/// +/// @param[out] sk - the secret key. +/// @param[in] pk_seed - seed for generating parts of the pbulic key. +/// @param[in] sk_seed - seed for generating the secret key. +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_generate_secretkey_cyclic(sk_t *sk, const unsigned char *pk_seed, const unsigned char *sk_seed); + +//////////////////////////////////// + +/// +/// @brief converting formats of public keys : from cyclic version to classic key +/// +/// @param[out] pk - the classic public key. +/// @param[in] cpk - the cyclic public key. +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_cpk_to_pk(pk_t *pk, const cpk_t *cpk); + +#endif // _RAINBOW_KEYPAIR_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/rainbow_keypair_computation.c b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/rainbow_keypair_computation.c new file mode 100644 index 0000000000..2e577e037b --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/rainbow_keypair_computation.c @@ -0,0 +1,213 @@ +/// @file rainbow_keypair_computation.c +/// @brief Implementations for functions in rainbow_keypair_computation.h +/// + +#include "rainbow_keypair_computation.h" +#include "blas.h" +#include "blas_comm.h" +#include "rainbow_blas.h" +#include "rainbow_keypair.h" +#include +#include +#include + +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_extcpk_to_pk(pk_t *pk, const ext_cpk_t *cpk) { + const unsigned char *idx_l1 = cpk->l1_Q1; + const unsigned char *idx_l2 = cpk->l2_Q1; + for (unsigned int i = 0; i < _V1; i++) { + for (unsigned int j = i; j < _V1; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q2; + idx_l2 = cpk->l2_Q2; + for (unsigned int i = 0; i < _V1; i++) { + for (unsigned int j = _V1; j < _V1 + _O1; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q3; + idx_l2 = cpk->l2_Q3; + for (unsigned int i = 0; i < _V1; i++) { + for (unsigned int j = _V1 + _O1; j < _PUB_N; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q5; + idx_l2 = cpk->l2_Q5; + for (unsigned int i = _V1; i < _V1 + _O1; i++) { + for (unsigned int j = i; j < _V1 + _O1; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q6; + idx_l2 = cpk->l2_Q6; + for (unsigned int i = _V1; i < _V1 + _O1; i++) { + for (unsigned int j = _V1 + _O1; j < _PUB_N; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q9; + idx_l2 = cpk->l2_Q9; + for (unsigned int i = _V1 + _O1; i < _PUB_N; i++) { + for (unsigned int j = i; j < _PUB_N; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } +} + +static void calculate_F_from_Q_ref(sk_t *Fs, const sk_t *Qs, sk_t *Ts) { + // Layer 1 + // F_sk.l1_F1s[i] = Q_pk.l1_F1s[i] + memcpy(Fs->l1_F1, Qs->l1_F1, _O1_BYTE * N_TRIANGLE_TERMS(_V1)); + + // F_sk.l1_F2s[i] = ( Q_pk.l1_F1s[i] + Q_pk.l1_F1s[i].transpose() ) * T_sk.t1 + Q_pk.l1_F2s[i] + memcpy(Fs->l1_F2, Qs->l1_F2, _O1_BYTE * _V1 * _O1); + batch_2trimat_madd(Fs->l1_F2, Qs->l1_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O1_BYTE); + + /* + Layer 2 + computations: + + F_sk.l2_F1s[i] = Q_pk.l2_F1s[i] + + Q1_T1 = Q_pk.l2_F1s[i]*T_sk.t1 + F_sk.l2_F2s[i] = Q1_T1 + Q_pk.l2_F2s[i] + Q_pk.l2_F1s[i].transpose() * T_sk.t1 + F_sk.l2_F5s[i] = UT( t1_tr* ( Q1_T1 + Q_pk.l2_F2s[i] ) ) + Q_pk.l2_F5s[i] + + Q1_Q1T_T4 = (Q_pk.l2_F1s[i] + Q_pk.l2_F1s[i].transpose()) * t4 + #Q1_Q1T_T4 = Q1_Q1T * t4 + Q2_T3 = Q_pk.l2_F2s[i]*T_sk.t3 + F_sk.l2_F3s[i] = Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] + F_sk.l2_F6s[i] = t1_tr * ( Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] ) + + Q_pk.l2_F2s[i].transpose() * t4 + + (Q_pk.l2_F5s[i] + Q_pk.l2_F5s[i].transpose())*T_sk.t3 + Q_pk.l2_F6s[i] + + */ + memcpy(Fs->l2_F1, Qs->l2_F1, _O2_BYTE * N_TRIANGLE_TERMS(_V1)); // F_sk.l2_F1s[i] = Q_pk.l2_F1s[i] + + // F_sk.l2_F2s[i] = Q1_T1 + Q_pk.l2_F2s[i] + Q_pk.l2_F1s[i].transpose() * T_sk.t1 + // F_sk.l2_F5s[i] = UT( t1_tr* ( Q1_T1 + Q_pk.l2_F2s[i] ) ) + Q_pk.l2_F5s[i] + memcpy(Fs->l2_F2, Qs->l2_F2, _O2_BYTE * _V1 * _O1); + batch_trimat_madd(Fs->l2_F2, Qs->l2_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O2_BYTE); // Q1_T1+ Q2 + + unsigned char tempQ[_O1 * _O1 * _O2_BYTE + 32]; + memset(tempQ, 0, _O1 * _O1 * _O2_BYTE); + batch_matTr_madd(tempQ, Ts->t1, _V1, _V1_BYTE, _O1, Fs->l2_F2, _O1, _O2_BYTE); // t1_tr*(Q1_T1+Q2) + memcpy(Fs->l2_F5, Qs->l2_F5, _O2_BYTE * N_TRIANGLE_TERMS(_O1)); // F5 + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_UpperTrianglize(Fs->l2_F5, tempQ, _O1, _O2_BYTE); // UT( ... ) + + batch_trimatTr_madd(Fs->l2_F2, Qs->l2_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O2_BYTE); // F2 = Q1_T1 + Q2 + Q1^tr*t1 + + // Q1_Q1T_T4 = (Q_pk.l2_F1s[i] + Q_pk.l2_F1s[i].transpose()) * t4 + // Q2_T3 = Q_pk.l2_F2s[i]*T_sk.t3 + // F_sk.l2_F3s[i] = Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] + memcpy(Fs->l2_F3, Qs->l2_F3, _V1 * _O2 * _O2_BYTE); + batch_2trimat_madd(Fs->l2_F3, Qs->l2_F1, Ts->t4, _V1, _V1_BYTE, _O2, _O2_BYTE); // Q1_Q1T_T4 + batch_mat_madd(Fs->l2_F3, Qs->l2_F2, _V1, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // Q2_T3 + + // F_sk.l2_F6s[i] = t1_tr * ( Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] ) + // + Q_pk.l2_F2s[i].transpose() * t4 + // + (Q_pk.l2_F5s[i] + Q_pk.l2_F5s[i].transpose())*T_sk.t3 + Q_pk.l2_F6s[i] + memcpy(Fs->l2_F6, Qs->l2_F6, _O1 * _O2 * _O2_BYTE); + batch_matTr_madd(Fs->l2_F6, Ts->t1, _V1, _V1_BYTE, _O1, Fs->l2_F3, _O2, _O2_BYTE); // t1_tr * ( Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] ) + batch_2trimat_madd(Fs->l2_F6, Qs->l2_F5, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // (Q_pk.l2_F5s[i] + Q_pk.l2_F5s[i].transpose())*T_sk.t3 + batch_bmatTr_madd(Fs->l2_F6, Qs->l2_F2, _O1, Ts->t4, _V1, _V1_BYTE, _O2, _O2_BYTE); +} + +static void calculate_Q_from_F_cyclic_ref(cpk_t *Qs, const sk_t *Fs, const sk_t *Ts) { + // Layer 1: Computing Q5, Q3, Q6, Q9 + + // Q_pk.l1_F5s[i] = UT( T1tr* (F1 * T1 + F2) ) + const unsigned char *t2 = Ts->t4; + sk_t tempQ; + memcpy(tempQ.l1_F2, Fs->l1_F2, _O1_BYTE * _V1 * _O1); + batch_trimat_madd(tempQ.l1_F2, Fs->l1_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O1_BYTE); // F1*T1 + F2 + memset(tempQ.l2_F1, 0, sizeof(tempQ.l2_F1)); + memset(tempQ.l2_F2, 0, sizeof(tempQ.l2_F2)); + batch_matTr_madd(tempQ.l2_F1, Ts->t1, _V1, _V1_BYTE, _O1, tempQ.l1_F2, _O1, _O1_BYTE); // T1tr*(F1*T1 + F2) + memset(Qs->l1_Q5, 0, _O1_BYTE * N_TRIANGLE_TERMS(_O1)); + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_UpperTrianglize(Qs->l1_Q5, tempQ.l2_F1, _O1, _O1_BYTE); // UT( ... ) // Q5 + + /* + F1_T2 = F1 * t2 + F2_T3 = F2 * t3 + F1_F1T_T2 + F2_T3 = F1_T2 + F2_T3 + F1tr * t2 + Q_pk.l1_F3s[i] = F1_F1T_T2 + F2_T3 + Q_pk.l1_F6s[i] = T1tr* ( F1_F1T_T2 + F2_T3 ) + F2tr * t2 + Q_pk.l1_F9s[i] = UT( T2tr* ( F1_T2 + F2_T3 ) ) + */ + memset(Qs->l1_Q3, 0, _O1_BYTE * _V1 * _O2); + memset(Qs->l1_Q6, 0, _O1_BYTE * _O1 * _O2); + memset(Qs->l1_Q9, 0, _O1_BYTE * N_TRIANGLE_TERMS(_O2)); + + batch_trimat_madd(Qs->l1_Q3, Fs->l1_F1, t2, _V1, _V1_BYTE, _O2, _O1_BYTE); // F1*T2 + batch_mat_madd(Qs->l1_Q3, Fs->l1_F2, _V1, Ts->t3, _O1, _O1_BYTE, _O2, _O1_BYTE); // F1_T2 + F2_T3 + + memset(tempQ.l1_F2, 0, _O1_BYTE * _V1 * _O2); // should be F3. assuming: _O1 >= _O2 + batch_matTr_madd(tempQ.l1_F2, t2, _V1, _V1_BYTE, _O2, Qs->l1_Q3, _O2, _O1_BYTE); // T2tr * ( F1_T2 + F2_T3 ) + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_UpperTrianglize(Qs->l1_Q9, tempQ.l1_F2, _O2, _O1_BYTE); // Q9 + + batch_trimatTr_madd(Qs->l1_Q3, Fs->l1_F1, t2, _V1, _V1_BYTE, _O2, _O1_BYTE); // F1_F1T_T2 + F2_T3 // Q3 + + batch_bmatTr_madd(Qs->l1_Q6, Fs->l1_F2, _O1, t2, _V1, _V1_BYTE, _O2, _O1_BYTE); // F2tr*T2 + batch_matTr_madd(Qs->l1_Q6, Ts->t1, _V1, _V1_BYTE, _O1, Qs->l1_Q3, _O2, _O1_BYTE); // Q6 + /* + Layer 2 + Computing Q9: + + F1_T2 = F1 * t2 + F2_T3 = F2 * t3 + Q9 = UT( T2tr*( F1*T2 + F2*T3 + F3 ) + T3tr*( F5*T3 + F6 ) ) + */ + sk_t tempQ2; + memcpy(tempQ2.l2_F3, Fs->l2_F3, _O2_BYTE * _V1 * _O2); /// F3 actually. + batch_trimat_madd(tempQ2.l2_F3, Fs->l2_F1, t2, _V1, _V1_BYTE, _O2, _O2_BYTE); // F1*T2 + F3 + batch_mat_madd(tempQ2.l2_F3, Fs->l2_F2, _V1, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // F1_T2 + F2_T3 + F3 + + memset(tempQ.l2_F3, 0, _O2_BYTE * _V1 * _O2); + batch_matTr_madd(tempQ.l2_F3, t2, _V1, _V1_BYTE, _O2, tempQ2.l2_F3, _O2, _O2_BYTE); // T2tr * ( ..... ) + + memcpy(tempQ.l2_F6, Fs->l2_F6, _O2_BYTE * _O1 * _O2); + batch_trimat_madd(tempQ.l2_F6, Fs->l2_F5, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // F5*T3 + F6 + + batch_matTr_madd(tempQ.l2_F3, Ts->t3, _O1, _O1_BYTE, _O2, tempQ.l2_F6, _O2, _O2_BYTE); // T2tr*( ..... ) + T3tr*( ..... ) + memset(Qs->l2_Q9, 0, _O2_BYTE * N_TRIANGLE_TERMS(_O2)); + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_UpperTrianglize(Qs->l2_Q9, tempQ.l2_F3, _O2, _O2_BYTE); // Q9 +} + +// Choosing implementations depends on the macros: _BLAS_SSE_ and _BLAS_AVX2_ +#define calculate_F_from_Q_impl calculate_F_from_Q_ref +#define calculate_Q_from_F_cyclic_impl calculate_Q_from_F_cyclic_ref + +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_calculate_F_from_Q(sk_t *Fs, const sk_t *Qs, sk_t *Ts) { + calculate_F_from_Q_impl(Fs, Qs, Ts); +} + +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_calculate_Q_from_F_cyclic(cpk_t *Qs, const sk_t *Fs, const sk_t *Ts) { + calculate_Q_from_F_cyclic_impl(Qs, Fs, Ts); +} diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/rainbow_keypair_computation.h b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/rainbow_keypair_computation.h new file mode 100644 index 0000000000..22bb2c08eb --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/rainbow_keypair_computation.h @@ -0,0 +1,71 @@ +#ifndef _RAINBOW_KEYPAIR_COMP_H_ +#define _RAINBOW_KEYPAIR_COMP_H_ +/// @file rainbow_keypair_computation.h +/// @brief Functions for calculating pk/sk while generating keys. +/// +/// Defining an internal structure of public key. +/// Functions for calculating pk/sk for key generation. +/// + +#include "rainbow_keypair.h" + +/// @brief The (internal use) public key for rainbow +/// +/// The (internal use) public key for rainbow. The public +/// polynomials are divided into l1_Q1, l1_Q2, ... l1_Q9, +/// l2_Q1, .... , l2_Q9. +/// +typedef struct rainbow_extend_publickey { + unsigned char l1_Q1[_O1_BYTE * N_TRIANGLE_TERMS(_V1)]; + unsigned char l1_Q2[_O1_BYTE * _V1 * _O1]; + unsigned char l1_Q3[_O1_BYTE * _V1 * _O2]; + unsigned char l1_Q5[_O1_BYTE * N_TRIANGLE_TERMS(_O1)]; + unsigned char l1_Q6[_O1_BYTE * _O1 * _O2]; + unsigned char l1_Q9[_O1_BYTE * N_TRIANGLE_TERMS(_O2)]; + + unsigned char l2_Q1[_O2_BYTE * N_TRIANGLE_TERMS(_V1)]; + unsigned char l2_Q2[_O2_BYTE * _V1 * _O1]; + unsigned char l2_Q3[_O2_BYTE * _V1 * _O2]; + unsigned char l2_Q5[_O2_BYTE * N_TRIANGLE_TERMS(_O1)]; + unsigned char l2_Q6[_O2_BYTE * _O1 * _O2]; + unsigned char l2_Q9[_O2_BYTE * N_TRIANGLE_TERMS(_O2)]; +} ext_cpk_t; + +/// +/// @brief converting formats of public keys : from ext_cpk_t version to pk_t +/// +/// @param[out] pk - the classic public key. +/// @param[in] cpk - the internel public key. +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_extcpk_to_pk(pk_t *pk, const ext_cpk_t *cpk); +///////////////////////////////////////////////// + +/// +/// @brief Computing public key from secret key +/// +/// @param[out] Qs - the public key +/// @param[in] Fs - parts of the secret key: l1_F1, l1_F2, l2_F1, l2_F2, l2_F3, l2_F5, l2_F6 +/// @param[in] Ts - parts of the secret key: T1, T4, T3 +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_calculate_Q_from_F(ext_cpk_t *Qs, const sk_t *Fs, const sk_t *Ts); + + +/// +/// @brief Computing parts of the sk from parts of pk and sk +/// +/// @param[out] Fs - parts of the sk: l1_F1, l1_F2, l2_F1, l2_F2, l2_F3, l2_F5, l2_F6 +/// @param[in] Qs - parts of the pk: l1_Q1, l1_Q2, l2_Q1, l2_Q2, l2_Q3, l2_Q5, l2_Q6 +/// @param[in] Ts - parts of the sk: T1, T4, T3 +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_calculate_F_from_Q(sk_t *Fs, const sk_t *Qs, sk_t *Ts); + +/// +/// @brief Computing parts of the pk from the secret key +/// +/// @param[out] Qs - parts of the pk: l1_Q3, l1_Q5, l2_Q6, l1_Q9, l2_Q9 +/// @param[in] Fs - parts of the sk: l1_F1, l1_F2, l2_F1, l2_F2, l2_F3, l2_F5, l2_F6 +/// @param[in] Ts - parts of the sk: T1, T4, T3 +/// +void PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_calculate_Q_from_F_cyclic(cpk_t *Qs, const sk_t *Fs, const sk_t *Ts); + +#endif // _RAINBOW_KEYPAIR_COMP_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/sign.c b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/sign.c new file mode 100644 index 0000000000..8e83a52c09 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/sign.c @@ -0,0 +1,76 @@ +/// @file sign.c +/// @brief the implementations for functions in api.h +/// +/// + +#include "api.h" +#include "rainbow.h" +#include "rainbow_config.h" +#include "rainbow_keypair.h" +#include "randombytes.h" +#include "utils_hash.h" +#include +#include + +int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { + unsigned char sk_seed[LEN_SKSEED] = {0}; + randombytes(sk_seed, LEN_SKSEED); + + unsigned char pk_seed[LEN_PKSEED] = {0}; + randombytes(pk_seed, LEN_PKSEED); + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_generate_compact_keypair_cyclic((cpk_t *)pk, (csk_t *)sk, pk_seed, sk_seed); + return 0; +} + +int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { + unsigned char digest[_HASH_LEN]; + + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_hash_msg(digest, _HASH_LEN, m, mlen); + + memcpy(sm, m, mlen); + smlen[0] = mlen + _SIGNATURE_BYTE; + + return PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_rainbow_sign_cyclic(sm + mlen, (const csk_t *)sk, digest); +} + +int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { + int rc; + if (_SIGNATURE_BYTE > smlen) { + rc = -1; + } else { + *mlen = smlen - _SIGNATURE_BYTE; + + unsigned char digest[_HASH_LEN]; + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_hash_msg(digest, _HASH_LEN, sm, *mlen); + + rc = PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_rainbow_verify_cyclic(digest, sm + mlen[0], (const cpk_t *)pk); + } + if (!rc) { + memmove(m, sm, smlen - _SIGNATURE_BYTE); + } else { // bad signature + *mlen = (size_t) -1; + memset(m, 0, smlen); + } + return rc; +} + +int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_crypto_sign_signature( + uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + unsigned char digest[_HASH_LEN]; + + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_hash_msg(digest, _HASH_LEN, m, mlen); + *siglen = _SIGNATURE_BYTE; + return PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_rainbow_sign_cyclic(sig, (const csk_t *)sk, digest); +} + +int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_crypto_sign_verify( + const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + if (siglen != _SIGNATURE_BYTE) { + return -1; + } + unsigned char digest[_HASH_LEN]; + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_hash_msg(digest, _HASH_LEN, m, mlen); + return PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_rainbow_verify_cyclic(digest, sig, (const cpk_t *)pk); +} diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/utils_hash.c b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/utils_hash.c new file mode 100644 index 0000000000..77cbed93c4 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/utils_hash.c @@ -0,0 +1,50 @@ +/// @file utils_hash.c +/// @brief the adapter for SHA2 families. +/// +/// + +#include "utils_hash.h" +#include "rainbow_config.h" +#include "sha2.h" + +static inline int _hash(unsigned char *digest, const unsigned char *m, size_t mlen) { + sha384(digest, m, mlen); + return 0; +} + +static inline int expand_hash(unsigned char *digest, size_t n_digest, const unsigned char *hash) { + if (_HASH_LEN >= n_digest) { + for (size_t i = 0; i < n_digest; i++) { + digest[i] = hash[i]; + } + return 0; + } + for (size_t i = 0; i < _HASH_LEN; i++) { + digest[i] = hash[i]; + } + n_digest -= _HASH_LEN; + + while (_HASH_LEN <= n_digest) { + _hash(digest + _HASH_LEN, digest, _HASH_LEN); + + n_digest -= _HASH_LEN; + digest += _HASH_LEN; + } + unsigned char temp[_HASH_LEN]; + if (n_digest) { + _hash(temp, digest, _HASH_LEN); + for (size_t i = 0; i < n_digest; i++) { + digest[_HASH_LEN + i] = temp[i]; + } + } + return 0; +} + +int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_hash_msg(unsigned char *digest, + size_t len_digest, + const unsigned char *m, + size_t mlen) { + unsigned char buf[_HASH_LEN]; + _hash(buf, m, mlen); + return expand_hash(digest, len_digest, buf); +} diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/utils_hash.h b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/utils_hash.h new file mode 100644 index 0000000000..0f034bfc3e --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/utils_hash.h @@ -0,0 +1,11 @@ +#ifndef _UTILS_HASH_H_ +#define _UTILS_HASH_H_ +/// @file utils_hash.h +/// @brief the interface for adapting hash functions. +/// + +#include + +int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_hash_msg(unsigned char *digest, size_t len_digest, const unsigned char *m, size_t mlen); + +#endif // _UTILS_HASH_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/utils_prng.c b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/utils_prng.c new file mode 100644 index 0000000000..89722fc526 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/utils_prng.c @@ -0,0 +1,97 @@ +/// @file utils_prng.c +/// @brief The implementation of PRNG related functions. +/// + +#include "utils_prng.h" +#include "aes.h" +#include "randombytes.h" +#include "utils_hash.h" +#include +#include + +static void prng_update(const unsigned char *provided_data, + unsigned char *Key, + unsigned char *V) { + unsigned char temp[48]; + aes256ctx ctx; + aes256_keyexp(&ctx, Key); + for (int i = 0; i < 3; i++) { + //increment V + for (int j = 15; j >= 0; j--) { + if (V[j] == 0xff) { + V[j] = 0x00; + } else { + V[j]++; + break; + } + } + aes256_ecb(temp + 16 * i, V, 1, &ctx); + } + if (provided_data != NULL) { + for (int i = 0; i < 48; i++) { + temp[i] ^= provided_data[i]; + } + } + aes256_ctx_release(&ctx); + memcpy(Key, temp, 32); + memcpy(V, temp + 32, 16); +} +static void randombytes_init_with_state(prng_t *state, + unsigned char *entropy_input_48bytes) { + memset(state->Key, 0x00, 32); + memset(state->V, 0x00, 16); + prng_update(entropy_input_48bytes, state->Key, state->V); +} + +static int randombytes_with_state(prng_t *state, + unsigned char *x, + size_t xlen) { + + unsigned char block[16]; + int i = 0; + + aes256ctx ctx; + aes256_keyexp(&ctx, state->Key); + + while (xlen > 0) { + //increment V + for (int j = 15; j >= 0; j--) { + if (state->V[j] == 0xff) { + state->V[j] = 0x00; + } else { + state->V[j]++; + break; + } + } + aes256_ecb(block, state->V, 1, &ctx); + if (xlen > 15) { + memcpy(x + i, block, 16); + i += 16; + xlen -= 16; + } else { + memcpy(x + i, block, xlen); + xlen = 0; + } + } + aes256_ctx_release(&ctx); + prng_update(NULL, state->Key, state->V); + return 0; +} + +int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_prng_set(prng_t *ctx, const void *prng_seed, unsigned long prng_seedlen) { + unsigned char seed[48]; + if (prng_seedlen >= 48) { + memcpy(seed, prng_seed, 48); + } else { + memcpy(seed, prng_seed, prng_seedlen); + PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_hash_msg(seed + prng_seedlen, 48 - (unsigned)prng_seedlen, (const unsigned char *)prng_seed, prng_seedlen); + } + + randombytes_init_with_state(ctx, seed); + + return 0; +} + +int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_prng_gen(prng_t *ctx, unsigned char *out, unsigned long outlen) { + return randombytes_with_state(ctx, out, outlen); +} diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/utils_prng.h b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/utils_prng.h new file mode 100644 index 0000000000..9e47af8a22 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic-compressed_clean/utils_prng.h @@ -0,0 +1,18 @@ +#ifndef _UTILS_PRNG_H_ +#define _UTILS_PRNG_H_ +/// @file utils_prng.h +/// @brief the interface for adapting PRNG functions. +/// +/// + +#include "randombytes.h" + +typedef struct { + unsigned char Key[32]; + unsigned char V[16]; +} prng_t; + +int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_prng_set(prng_t *ctx, const void *prng_seed, unsigned long prng_seedlen); +int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_prng_gen(prng_t *ctx, unsigned char *out, unsigned long outlen); + +#endif // _UTILS_PRNG_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/LICENSE b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/LICENSE new file mode 100644 index 0000000000..cb00a6e354 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/LICENSE @@ -0,0 +1,8 @@ +`Software implementation of Rainbow for NIST R2 submission' by Ming-Shing Chen + +To the extent possible under law, the person who associated CC0 with +`Software implementation of Rainbow for NIST R2 submission' has waived all copyright and related or neighboring rights +to `Software implementation of Rainbow for NIST R2 submission'. + +You should have received a copy of the CC0 legalcode along with this +work. If not, see . diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/api.h b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/api.h new file mode 100644 index 0000000000..cf8628c204 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/api.h @@ -0,0 +1,32 @@ +#ifndef PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_API_H +#define PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_API_H + +#include +#include + +#define PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_CRYPTO_SECRETKEYBYTES 511448 +#define PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_CRYPTO_PUBLICKEYBYTES 206744 +#define PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_CRYPTO_BYTES 156 +#define PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_CRYPTO_ALGNAME "RAINBOW(256,68,36,36) - cyclic" + +int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + + +int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_crypto_sign_signature( + uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_crypto_sign_verify( + const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + + +#endif diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/blas.c b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/blas.c new file mode 100644 index 0000000000..687602fd2a --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/blas.c @@ -0,0 +1,31 @@ +#include "blas.h" +#include "gf.h" + +#include + +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_predicated_add(uint8_t *accu_b, uint8_t predicate, const uint8_t *a, size_t _num_byte) { + uint8_t pr_u8 = (uint8_t) ((uint8_t) 0 - predicate); + for (size_t i = 0; i < _num_byte; i++) { + accu_b[i] ^= (a[i] & pr_u8); + } +} + +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_add(uint8_t *accu_b, const uint8_t *a, size_t _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + accu_b[i] ^= a[i]; + } +} + + +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_mul_scalar(uint8_t *a, uint8_t b, size_t _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + a[i] = PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256_mul(a[i], b); + } +} + +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_madd(uint8_t *accu_c, const uint8_t *a, uint8_t gf256_b, size_t _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + accu_c[i] ^= PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256_mul(a[i], gf256_b); + } +} + diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/blas.h b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/blas.h new file mode 100644 index 0000000000..41bd969cbd --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/blas.h @@ -0,0 +1,19 @@ +#ifndef _BLAS_H_ +#define _BLAS_H_ +/// @file blas.h +/// @brief Functions for implementing basic linear algebra functions. +/// + +#include "rainbow_config.h" +#include +#include + +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_predicated_add(uint8_t *accu_b, uint8_t predicate, const uint8_t *a, size_t _num_byte); +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_add(uint8_t *accu_b, const uint8_t *a, size_t _num_byte); + + +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_mul_scalar(uint8_t *a, uint8_t b, size_t _num_byte); +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_madd(uint8_t *accu_c, const uint8_t *a, uint8_t gf256_b, size_t _num_byte); + + +#endif // _BLAS_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/blas_comm.c b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/blas_comm.c new file mode 100644 index 0000000000..144576948c --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/blas_comm.c @@ -0,0 +1,144 @@ +/// @file blas_comm.c +/// @brief The standard implementations for blas_comm.h +/// + +#include "blas_comm.h" +#include "blas.h" +#include "gf.h" +#include "rainbow_config.h" + +#include +#include + +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_set_zero(uint8_t *b, unsigned int _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + b[i] = 0; + } +} +/// @brief get an element from GF(256) vector . +/// +/// @param[in] a - the input vector a. +/// @param[in] i - the index in the vector a. +/// @return the value of the element. +/// +uint8_t PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_get_ele(const uint8_t *a, unsigned int i) { + return a[i]; +} + +unsigned int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_is_zero(const uint8_t *a, unsigned int _num_byte) { + uint8_t r = 0; + while (_num_byte--) { + r |= a[0]; + a++; + } + return (0 == r); +} + +/// polynomial multplication +/// School boook +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_polymul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int _num) { + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_set_zero(c, _num * 2 - 1); + for (unsigned int i = 0; i < _num; i++) { + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_madd(c + i, a, b[i], _num); + } +} + +static void gf256mat_prod_ref(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b) { + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_set_zero(c, n_A_vec_byte); + for (unsigned int i = 0; i < n_A_width; i++) { + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_madd(c, matA, b[i], n_A_vec_byte); + matA += n_A_vec_byte; + } +} + +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256mat_mul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int len_vec) { + unsigned int n_vec_byte = len_vec; + for (unsigned int k = 0; k < len_vec; k++) { + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_set_zero(c, n_vec_byte); + const uint8_t *bk = b + n_vec_byte * k; + for (unsigned int i = 0; i < len_vec; i++) { + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_madd(c, a + n_vec_byte * i, bk[i], n_vec_byte); + } + c += n_vec_byte; + } +} + +static unsigned int gf256mat_gauss_elim_ref(uint8_t *mat, unsigned int h, unsigned int w) { + unsigned int r8 = 1; + + for (unsigned int i = 0; i < h; i++) { + uint8_t *ai = mat + w * i; + unsigned int skip_len_align4 = i & ((unsigned int)~0x3); + + for (unsigned int j = i + 1; j < h; j++) { + uint8_t *aj = mat + w * j; + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_predicated_add(ai + skip_len_align4, !PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256_is_nonzero(ai[i]), aj + skip_len_align4, w - skip_len_align4); + } + r8 &= PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256_is_nonzero(ai[i]); + uint8_t pivot = ai[i]; + pivot = PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256_inv(pivot); + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_mul_scalar(ai + skip_len_align4, pivot, w - skip_len_align4); + for (unsigned int j = 0; j < h; j++) { + if (i == j) { + continue; + } + uint8_t *aj = mat + w * j; + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_madd(aj + skip_len_align4, ai + skip_len_align4, aj[i], w - skip_len_align4); + } + } + + return r8; +} + +static unsigned int gf256mat_solve_linear_eq_ref(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n) { + uint8_t mat[64 * 64]; + for (unsigned int i = 0; i < n; i++) { + memcpy(mat + i * (n + 1), inp_mat + i * n, n); + mat[i * (n + 1) + n] = c_terms[i]; + } + unsigned int r8 = PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256mat_gauss_elim(mat, n, n + 1); + for (unsigned int i = 0; i < n; i++) { + sol[i] = mat[i * (n + 1) + n]; + } + return r8; +} + +static inline void gf256mat_submat(uint8_t *mat2, unsigned int w2, unsigned int st, const uint8_t *mat, unsigned int w, unsigned int h) { + for (unsigned int i = 0; i < h; i++) { + for (unsigned int j = 0; j < w2; j++) { + mat2[i * w2 + j] = mat[i * w + st + j]; + } + } +} + +unsigned int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256mat_inv(uint8_t *inv_a, const uint8_t *a, unsigned int H, uint8_t *buffer) { + uint8_t *aa = buffer; + for (unsigned int i = 0; i < H; i++) { + uint8_t *ai = aa + i * 2 * H; + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_set_zero(ai, 2 * H); + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_add(ai, a + i * H, H); + ai[H + i] = 1; + } + unsigned int r8 = PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256mat_gauss_elim(aa, H, 2 * H); + gf256mat_submat(inv_a, H, H, aa, 2 * H, H); + return r8; +} + + +// choosing the implementations depends on the macros _BLAS_AVX2_ and _BLAS_SSE + +#define gf256mat_prod_impl gf256mat_prod_ref +#define gf256mat_gauss_elim_impl gf256mat_gauss_elim_ref +#define gf256mat_solve_linear_eq_impl gf256mat_solve_linear_eq_ref +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256mat_prod(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b) { + gf256mat_prod_impl(c, matA, n_A_vec_byte, n_A_width, b); +} + +unsigned int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256mat_gauss_elim(uint8_t *mat, unsigned int h, unsigned int w) { + return gf256mat_gauss_elim_impl(mat, h, w); +} + +unsigned int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256mat_solve_linear_eq(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n) { + return gf256mat_solve_linear_eq_impl(sol, inp_mat, c_terms, n); +} + diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/blas_comm.h b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/blas_comm.h new file mode 100644 index 0000000000..96ac02d732 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/blas_comm.h @@ -0,0 +1,90 @@ +#ifndef _BLAS_COMM_H_ +#define _BLAS_COMM_H_ +/// @file blas_comm.h +/// @brief Common functions for linear algebra. +/// + +#include "rainbow_config.h" +#include + +/// @brief set a vector to 0. +/// +/// @param[in,out] b - the vector b. +/// @param[in] _num_byte - number of bytes for the vector b. +/// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_set_zero(uint8_t *b, unsigned int _num_byte); + +/// @brief get an element from GF(256) vector . +/// +/// @param[in] a - the input vector a. +/// @param[in] i - the index in the vector a. +/// @return the value of the element. +/// +uint8_t PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_get_ele(const uint8_t *a, unsigned int i); + +/// @brief check if a vector is 0. +/// +/// @param[in] a - the vector a. +/// @param[in] _num_byte - number of bytes for the vector a. +/// @return 1(true) if a is 0. 0(false) else. +/// +unsigned int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_is_zero(const uint8_t *a, unsigned int _num_byte); + +/// @brief polynomial multiplication: c = a*b +/// +/// @param[out] c - the output polynomial c +/// @param[in] a - the vector a. +/// @param[in] b - the vector b. +/// @param[in] _num - number of elements for the polynomials a and b. +/// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_polymul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int _num); + +/// @brief matrix-vector multiplication: c = matA * b , in GF(256) +/// +/// @param[out] c - the output vector c +/// @param[in] matA - a column-major matrix A. +/// @param[in] n_A_vec_byte - the size of column vectors in bytes. +/// @param[in] n_A_width - the width of matrix A. +/// @param[in] b - the vector b. +/// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256mat_prod(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b); + +/// @brief matrix-matrix multiplication: c = a * b , in GF(256) +/// +/// @param[out] c - the output matrix c +/// @param[in] c - a matrix a. +/// @param[in] b - a matrix b. +/// @param[in] len_vec - the length of column vectors. +/// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256mat_mul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int len_vec); + +/// @brief Gauss elimination for a matrix, in GF(256) +/// +/// @param[in,out] mat - the matrix. +/// @param[in] h - the height of the matrix. +/// @param[in] w - the width of the matrix. +/// @return 1(true) if success. 0(false) if the matrix is singular. +/// +unsigned int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256mat_gauss_elim(uint8_t *mat, unsigned int h, unsigned int w); + +/// @brief Solving linear equations, in GF(256) +/// +/// @param[out] sol - the solutions. +/// @param[in] inp_mat - the matrix parts of input equations. +/// @param[in] c_terms - the constant terms of the input equations. +/// @param[in] n - the number of equations. +/// @return 1(true) if success. 0(false) if the matrix is singular. +/// +unsigned int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256mat_solve_linear_eq(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n); + +/// @brief Computing the inverse matrix, in GF(256) +/// +/// @param[out] inv_a - the output of matrix a. +/// @param[in] a - a matrix a. +/// @param[in] H - height of matrix a, i.e., matrix a is an HxH matrix. +/// @param[in] buffer - The buffer for computations. it has to be as large as 2 input matrixes. +/// @return 1(true) if success. 0(false) if the matrix is singular. +/// +unsigned int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256mat_inv(uint8_t *inv_a, const uint8_t *a, unsigned int H, uint8_t *buffer); + +#endif // _BLAS_COMM_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/gf.c b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/gf.c new file mode 100644 index 0000000000..f0a05ccbdd --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/gf.c @@ -0,0 +1,91 @@ +#include "gf.h" + +//// gf4 := gf2[x]/x^2+x+1 +static inline uint8_t gf4_mul_2(uint8_t a) { + uint8_t r = (uint8_t)(a << 1); + r ^= (uint8_t)((a >> 1) * 7); + return r; +} + +static inline uint8_t gf4_mul(uint8_t a, uint8_t b) { + uint8_t r = (uint8_t)(a * (b & 1)); + return r ^ (uint8_t)(gf4_mul_2(a) * (b >> 1)); +} + +static inline uint8_t gf4_squ(uint8_t a) { + return a ^ (a >> 1); +} + +//// gf16 := gf4[y]/y^2+y+x +uint8_t PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf16_mul(uint8_t a, uint8_t b) { + uint8_t a0 = a & 3; + uint8_t a1 = (a >> 2); + uint8_t b0 = b & 3; + uint8_t b1 = (b >> 2); + uint8_t a0b0 = gf4_mul(a0, b0); + uint8_t a1b1 = gf4_mul(a1, b1); + uint8_t a0b1_a1b0 = gf4_mul(a0 ^ a1, b0 ^ b1) ^ a0b0 ^ a1b1; + uint8_t a1b1_x2 = gf4_mul_2(a1b1); + return (uint8_t)((a0b1_a1b0 ^ a1b1) << 2 ^ a0b0 ^ a1b1_x2); +} + +static inline uint8_t gf16_squ(uint8_t a) { + uint8_t a0 = a & 3; + uint8_t a1 = (a >> 2); + a1 = gf4_squ(a1); + uint8_t a1squ_x2 = gf4_mul_2(a1); + return (uint8_t)((a1 << 2) ^ a1squ_x2 ^ gf4_squ(a0)); +} + +uint8_t PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256_is_nonzero(uint8_t a) { + unsigned int a8 = a; + unsigned int r = ((unsigned int)0) - a8; + r >>= 8; + return r & 1; +} + +static inline uint8_t gf4_mul_3(uint8_t a) { + uint8_t msk = (uint8_t)((a - 2) >> 1); + return (uint8_t)((msk & ((int)a * 3)) | ((~msk) & ((int)a - 1))); +} +static inline uint8_t gf16_mul_8(uint8_t a) { + uint8_t a0 = a & 3; + uint8_t a1 = a >> 2; + return (uint8_t)((gf4_mul_2(a0 ^ a1) << 2) | gf4_mul_3(a1)); +} + +// gf256 := gf16[X]/X^2+X+xy +uint8_t PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256_mul(uint8_t a, uint8_t b) { + uint8_t a0 = a & 15; + uint8_t a1 = (a >> 4); + uint8_t b0 = b & 15; + uint8_t b1 = (b >> 4); + uint8_t a0b0 = PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf16_mul(a0, b0); + uint8_t a1b1 = PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf16_mul(a1, b1); + uint8_t a0b1_a1b0 = PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf16_mul(a0 ^ a1, b0 ^ b1) ^ a0b0 ^ a1b1; + uint8_t a1b1_x8 = gf16_mul_8(a1b1); + return (uint8_t)((a0b1_a1b0 ^ a1b1) << 4 ^ a0b0 ^ a1b1_x8); +} + +static inline uint8_t gf256_squ(uint8_t a) { + uint8_t a0 = a & 15; + uint8_t a1 = (a >> 4); + a1 = gf16_squ(a1); + uint8_t a1squ_x8 = gf16_mul_8(a1); + return (uint8_t)((a1 << 4) ^ a1squ_x8 ^ gf16_squ(a0)); +} + +uint8_t PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256_inv(uint8_t a) { + // 128+64+32+16+8+4+2 = 254 + uint8_t a2 = gf256_squ(a); + uint8_t a4 = gf256_squ(a2); + uint8_t a8 = gf256_squ(a4); + uint8_t a4_2 = PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256_mul(a4, a2); + uint8_t a8_4_2 = PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256_mul(a4_2, a8); + uint8_t a64_ = gf256_squ(a8_4_2); + a64_ = gf256_squ(a64_); + a64_ = gf256_squ(a64_); + uint8_t a64_2 = PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256_mul(a64_, a8_4_2); + uint8_t a128_ = gf256_squ(a64_2); + return PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256_mul(a2, a128_); +} diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/gf.h b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/gf.h new file mode 100644 index 0000000000..cf90f323a9 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/gf.h @@ -0,0 +1,19 @@ +#ifndef _GF16_H_ +#define _GF16_H_ + +#include "rainbow_config.h" +#include + +/// @file gf16.h +/// @brief Library for arithmetics in GF(16) and GF(256) +/// + +uint8_t PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf16_mul(uint8_t a, uint8_t b); + + +uint8_t PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256_is_nonzero(uint8_t a); +uint8_t PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256_inv(uint8_t a); +uint8_t PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256_mul(uint8_t a, uint8_t b); + + +#endif // _GF16_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/parallel_matrix_op.c b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/parallel_matrix_op.c new file mode 100644 index 0000000000..6a968627fa --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/parallel_matrix_op.c @@ -0,0 +1,183 @@ +/// @file parallel_matrix_op.c +/// @brief the standard implementations for functions in parallel_matrix_op.h +/// +/// the standard implementations for functions in parallel_matrix_op.h +/// + +#include "parallel_matrix_op.h" +#include "blas.h" +#include "blas_comm.h" + +/// +/// @brief Calculate the corresponding index in an array for an upper-triangle(UT) matrix. +/// +/// @param[in] i_row - the i-th row in an upper-triangle matrix. +/// @param[in] j_col - the j-th column in an upper-triangle matrix. +/// @param[in] dim - the dimension of the upper-triangle matrix, i.e., an dim x dim matrix. +/// @return the corresponding index in an array storage. +/// +unsigned int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_idx_of_trimat(unsigned int i_row, unsigned int j_col, unsigned int dim) { + return (dim + dim - i_row + 1) * i_row / 2 + j_col - i_row; +} + +/// +/// @brief Calculate the corresponding index in an array for an upper-triangle or lower-triangle matrix. +/// +/// @param[in] i_row - the i-th row in a triangle matrix. +/// @param[in] j_col - the j-th column in a triangle matrix. +/// @param[in] dim - the dimension of the triangle matrix, i.e., an dim x dim matrix. +/// @return the corresponding index in an array storage. +/// +static inline unsigned int idx_of_2trimat(unsigned int i_row, unsigned int j_col, unsigned int n_var) { + if (i_row > j_col) { + return PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_idx_of_trimat(j_col, i_row, n_var); + } + return PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_idx_of_trimat(i_row, j_col, n_var); +} + +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_UpperTrianglize(unsigned char *btriC, const unsigned char *bA, unsigned int Awidth, unsigned int size_batch) { + unsigned char *runningC = btriC; + unsigned int Aheight = Awidth; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < i; j++) { + unsigned int idx = PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_idx_of_trimat(j, i, Aheight); + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_add(btriC + idx * size_batch, bA + size_batch * (i * Awidth + j), size_batch); + } + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_add(runningC, bA + size_batch * (i * Awidth + i), size_batch * (Aheight - i)); + runningC += size_batch * (Aheight - i); + } +} + +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Awidth = Bheight; + unsigned int Aheight = Awidth; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + if (k < i) { + continue; + } + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_madd(bC, &btriA[(k - i) * size_batch], PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + btriA += (Aheight - i) * size_batch; + } +} + +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_trimatTr_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Aheight = Bheight; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + if (i < k) { + continue; + } + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_madd(bC, &btriA[size_batch * (PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_idx_of_trimat(k, i, Aheight))], PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_2trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Aheight = Bheight; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + if (i == k) { + continue; + } + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_madd(bC, &btriA[size_batch * (idx_of_2trimat(i, k, Aheight))], PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_matTr_madd_gf256(unsigned char *bC, const unsigned char *A_to_tr, unsigned int Aheight, unsigned int size_Acolvec, unsigned int Awidth, + const unsigned char *bB, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Atr_height = Awidth; + unsigned int Atr_width = Aheight; + for (unsigned int i = 0; i < Atr_height; i++) { + for (unsigned int j = 0; j < Atr_width; j++) { + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_madd(bC, &bB[j * Bwidth * size_batch], PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_get_ele(&A_to_tr[size_Acolvec * i], j), size_batch * Bwidth); + } + bC += size_batch * Bwidth; + } +} + +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_bmatTr_madd_gf256(unsigned char *bC, const unsigned char *bA_to_tr, unsigned int Awidth_before_tr, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + const unsigned char *bA = bA_to_tr; + unsigned int Aheight = Awidth_before_tr; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_madd(bC, &bA[size_batch * (i + k * Aheight)], PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_mat_madd_gf256(unsigned char *bC, const unsigned char *bA, unsigned int Aheight, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Awidth = Bheight; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_madd(bC, &bA[k * size_batch], PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + bA += (Awidth) * size_batch; + } +} + +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_quad_trimat_eval_gf256(unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned int dim, unsigned int size_batch) { + unsigned char tmp[256]; + + unsigned char _x[256]; + for (unsigned int i = 0; i < dim; i++) { + _x[i] = PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_get_ele(x, i); + } + + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_set_zero(y, size_batch); + for (unsigned int i = 0; i < dim; i++) { + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_set_zero(tmp, size_batch); + for (unsigned int j = i; j < dim; j++) { + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_madd(tmp, trimat, _x[j], size_batch); + trimat += size_batch; + } + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_madd(y, tmp, _x[i], size_batch); + } +} + +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_quad_recmat_eval_gf256(unsigned char *z, const unsigned char *y, unsigned int dim_y, const unsigned char *mat, + const unsigned char *x, unsigned dim_x, unsigned size_batch) { + unsigned char tmp[128]; + + unsigned char _x[128]; + for (unsigned int i = 0; i < dim_x; i++) { + _x[i] = PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_get_ele(x, i); + } + unsigned char _y[128]; + for (unsigned int i = 0; i < dim_y; i++) { + _y[i] = PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_get_ele(y, i); + } + + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_set_zero(z, size_batch); + for (unsigned int i = 0; i < dim_y; i++) { + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_set_zero(tmp, size_batch); + for (unsigned int j = 0; j < dim_x; j++) { + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_madd(tmp, mat, _x[j], size_batch); + mat += size_batch; + } + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_madd(z, tmp, _y[i], size_batch); + } +} + diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/parallel_matrix_op.h b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/parallel_matrix_op.h new file mode 100644 index 0000000000..62dd14049d --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/parallel_matrix_op.h @@ -0,0 +1,260 @@ +#ifndef _P_MATRIX_OP_H_ +#define _P_MATRIX_OP_H_ +/// @file parallel_matrix_op.h +/// @brief Librarys for operations of batched matrixes. +/// +/// + +//////////////// Section: triangle matrix <-> rectangle matrix /////////////////////////////////// + +/// +/// @brief Calculate the corresponding index in an array for an upper-triangle(UT) matrix. +/// +/// @param[in] i_row - the i-th row in an upper-triangle matrix. +/// @param[in] j_col - the j-th column in an upper-triangle matrix. +/// @param[in] dim - the dimension of the upper-triangle matrix, i.e., an dim x dim matrix. +/// @return the corresponding index in an array storage. +/// +unsigned int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_idx_of_trimat(unsigned int i_row, unsigned int j_col, unsigned int dim); + +/// +/// @brief Upper trianglize a rectangle matrix to the corresponding upper-trangle matrix. +/// +/// @param[out] btriC - the batched upper-trianglized matrix C. +/// @param[in] bA - a batched retangle matrix A. +/// @param[in] bwidth - the width of the batched matrix A, i.e., A is a Awidth x Awidth matrix. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_UpperTrianglize(unsigned char *btriC, const unsigned char *bA, unsigned int Awidth, unsigned int size_batch); + +//////////////////// Section: matrix multiplications /////////////////////////////// + +/// +/// @brief bC += btriA * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_trimat_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += btriA * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += btriA^Tr * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. A will be transposed while multiplying. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_trimatTr_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += btriA^Tr * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A, which will be transposed while multiplying. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_trimatTr_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += (btriA + btriA^Tr) *B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. The operand for multiplication is (btriA + btriA^Tr). +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_2trimat_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += (btriA + btriA^Tr) *B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. The operand for multiplication is (btriA + btriA^Tr). +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_2trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += A^Tr * bB , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] A_to_tr - a column-major matrix A. The operand for multiplication is A^Tr. +/// @param[in] Aheight - the height of A. +/// @param[in] size_Acolvec - the size of a column vector in A. +/// @param[in] Awidth - the width of A. +/// @param[in] bB - a batched matrix B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_matTr_madd_gf16(unsigned char *bC, + const unsigned char *A_to_tr, unsigned int Aheight, unsigned int size_Acolvec, unsigned int Awidth, + const unsigned char *bB, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += A^Tr * bB , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] A_to_tr - a column-major matrix A. The operand for multiplication is A^Tr. +/// @param[in] Aheight - the height of A. +/// @param[in] size_Acolvec - the size of a column vector in A. +/// @param[in] Awidth - the width of A. +/// @param[in] bB - a batched matrix B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_matTr_madd_gf256(unsigned char *bC, + const unsigned char *A_to_tr, unsigned int Aheight, unsigned int size_Acolvec, unsigned int Awidth, + const unsigned char *bB, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA^Tr * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA_to_tr - a batched matrix A. The operand for multiplication is (bA^Tr). +/// @param[in] Awidth_befor_tr - the width of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_bmatTr_madd_gf16(unsigned char *bC, const unsigned char *bA_to_tr, unsigned int Awidth_before_tr, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA^Tr * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA_to_tr - a batched matrix A. The operand for multiplication is (bA^Tr). +/// @param[in] Awidth_befor_tr - the width of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_bmatTr_madd_gf256(unsigned char *bC, const unsigned char *bA_to_tr, unsigned int Awidth_before_tr, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA - a batched matrix A. +/// @param[in] Aheigh - the height of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_mat_madd_gf16(unsigned char *bC, const unsigned char *bA, unsigned int Aheight, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA - a batched matrix A. +/// @param[in] Aheigh - the height of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_mat_madd_gf256(unsigned char *bC, const unsigned char *bA, unsigned int Aheight, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +//////////////////// Section: "quadratric" matrix evaluation /////////////////////////////// + +/// +/// @brief y = x^Tr * trimat * x , in GF(16) +/// +/// @param[out] y - the returned batched element y. +/// @param[in] trimat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim - the dimension of matrix trimat (and x). +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_quad_trimat_eval_gf16(unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned int dim, unsigned int size_batch); + +/// +/// @brief y = x^Tr * trimat * x , in GF(256) +/// +/// @param[out] y - the returned batched element y. +/// @param[in] trimat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim - the dimension of matrix trimat (and x). +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_quad_trimat_eval_gf256(unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned int dim, unsigned int size_batch); + +/// +/// @brief z = y^Tr * mat * x , in GF(16) +/// +/// @param[out] z - the returned batched element z. +/// @param[in] y - an input vector y. +/// @param[in] dim_y - the length of y. +/// @param[in] mat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim_x - the length of x. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_quad_recmat_eval_gf16(unsigned char *z, const unsigned char *y, unsigned int dim_y, + const unsigned char *mat, const unsigned char *x, unsigned int dim_x, unsigned int size_batch); + +/// +/// @brief z = y^Tr * mat * x , in GF(256) +/// +/// @param[out] z - the returned batched element z. +/// @param[in] y - an input vector y. +/// @param[in] dim_y - the length of y. +/// @param[in] mat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim_x - the length of x. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_quad_recmat_eval_gf256(unsigned char *z, const unsigned char *y, unsigned int dim_y, + const unsigned char *mat, const unsigned char *x, unsigned int dim_x, unsigned int size_batch); + +#endif // _P_MATRIX_OP_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/rainbow.c b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/rainbow.c new file mode 100644 index 0000000000..840a260338 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/rainbow.c @@ -0,0 +1,173 @@ +/// @file rainbow.c +/// @brief The standard implementations for functions in rainbow.h +/// + +#include "blas.h" +#include "parallel_matrix_op.h" +#include "rainbow.h" +#include "rainbow_blas.h" +#include "rainbow_config.h" +#include "rainbow_keypair.h" +#include "utils_hash.h" +#include "utils_prng.h" +#include +#include +#include + +#define MAX_ATTEMPT_FRMAT 128 + +int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_rainbow_sign(uint8_t *signature, const sk_t *sk, const uint8_t *_digest) { + uint8_t mat_l1[_O1 * _O1_BYTE]; + uint8_t mat_l2[_O2 * _O2_BYTE]; + uint8_t mat_buffer[2 * _MAX_O * _MAX_O_BYTE]; + + // setup PRNG + prng_t prng_sign; + uint8_t prng_preseed[LEN_SKSEED + _HASH_LEN]; + memcpy(prng_preseed, sk->sk_seed, LEN_SKSEED); + memcpy(prng_preseed + LEN_SKSEED, _digest, _HASH_LEN); // prng_preseed = sk_seed || digest + uint8_t prng_seed[_HASH_LEN]; + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_hash_msg(prng_seed, _HASH_LEN, prng_preseed, _HASH_LEN + LEN_SKSEED); + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_prng_set(&prng_sign, prng_seed, _HASH_LEN); // seed = H( sk_seed || digest ) + for (unsigned int i = 0; i < LEN_SKSEED + _HASH_LEN; i++) { + prng_preseed[i] ^= prng_preseed[i]; // clean + } + for (unsigned int i = 0; i < _HASH_LEN; i++) { + prng_seed[i] ^= prng_seed[i]; // clean + } + + // roll vinegars. + uint8_t vinegar[_V1_BYTE]; + unsigned int n_attempt = 0; + unsigned int l1_succ = 0; + while (!l1_succ) { + if (MAX_ATTEMPT_FRMAT <= n_attempt) { + break; + } + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_prng_gen(&prng_sign, vinegar, _V1_BYTE); // generating vinegars + gfmat_prod(mat_l1, sk->l1_F2, _O1 * _O1_BYTE, _V1, vinegar); // generating the linear equations for layer 1 + l1_succ = gfmat_inv(mat_l1, mat_l1, _O1, mat_buffer); // check if the linear equation solvable + n_attempt++; + } + + // Given the vinegars, pre-compute variables needed for layer 2 + uint8_t r_l1_F1[_O1_BYTE] = {0}; + uint8_t r_l2_F1[_O2_BYTE] = {0}; + batch_quad_trimat_eval(r_l1_F1, sk->l1_F1, vinegar, _V1, _O1_BYTE); + batch_quad_trimat_eval(r_l2_F1, sk->l2_F1, vinegar, _V1, _O2_BYTE); + uint8_t mat_l2_F3[_O2 * _O2_BYTE]; + uint8_t mat_l2_F2[_O1 * _O2_BYTE]; + gfmat_prod(mat_l2_F3, sk->l2_F3, _O2 * _O2_BYTE, _V1, vinegar); + gfmat_prod(mat_l2_F2, sk->l2_F2, _O1 * _O2_BYTE, _V1, vinegar); + + // Some local variables. + uint8_t _z[_PUB_M_BYTE]; + uint8_t y[_PUB_M_BYTE]; + uint8_t *x_v1 = vinegar; + uint8_t x_o1[_O1_BYTE]; + uint8_t x_o2[_O1_BYTE]; + + uint8_t digest_salt[_HASH_LEN + _SALT_BYTE]; + memcpy(digest_salt, _digest, _HASH_LEN); + uint8_t *salt = digest_salt + _HASH_LEN; + + uint8_t temp_o[_MAX_O_BYTE + 32] = {0}; + unsigned int succ = 0; + while (!succ) { + if (MAX_ATTEMPT_FRMAT <= n_attempt) { + break; + } + // The computation: H(digest||salt) --> z --S--> y --C-map--> x --T--> w + + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_prng_gen(&prng_sign, salt, _SALT_BYTE); // roll the salt + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_hash_msg(_z, _PUB_M_BYTE, digest_salt, _HASH_LEN + _SALT_BYTE); // H(digest||salt) + + // y = S^-1 * z + memcpy(y, _z, _PUB_M_BYTE); // identity part of S + gfmat_prod(temp_o, sk->s1, _O1_BYTE, _O2, _z + _O1_BYTE); + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_add(y, temp_o, _O1_BYTE); + + // Central Map: + // layer 1: calculate x_o1 + memcpy(temp_o, r_l1_F1, _O1_BYTE); + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_add(temp_o, y, _O1_BYTE); + gfmat_prod(x_o1, mat_l1, _O1_BYTE, _O1, temp_o); + + // layer 2: calculate x_o2 + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_set_zero(temp_o, _O2_BYTE); + gfmat_prod(temp_o, mat_l2_F2, _O2_BYTE, _O1, x_o1); // F2 + batch_quad_trimat_eval(mat_l2, sk->l2_F5, x_o1, _O1, _O2_BYTE); // F5 + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_add(temp_o, mat_l2, _O2_BYTE); + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_add(temp_o, r_l2_F1, _O2_BYTE); // F1 + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_add(temp_o, y + _O1_BYTE, _O2_BYTE); + + // generate the linear equations of the 2nd layer + gfmat_prod(mat_l2, sk->l2_F6, _O2 * _O2_BYTE, _O1, x_o1); // F6 + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_add(mat_l2, mat_l2_F3, _O2 * _O2_BYTE); // F3 + succ = gfmat_inv(mat_l2, mat_l2, _O2, mat_buffer); + gfmat_prod(x_o2, mat_l2, _O2_BYTE, _O2, temp_o); // solve l2 eqs + + n_attempt++; + }; + // w = T^-1 * y + uint8_t w[_PUB_N_BYTE]; + // identity part of T. + memcpy(w, x_v1, _V1_BYTE); + memcpy(w + _V1_BYTE, x_o1, _O1_BYTE); + memcpy(w + _V2_BYTE, x_o2, _O2_BYTE); + // Computing the t1 part. + gfmat_prod(y, sk->t1, _V1_BYTE, _O1, x_o1); + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_add(w, y, _V1_BYTE); + // Computing the t4 part. + gfmat_prod(y, sk->t4, _V1_BYTE, _O2, x_o2); + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_add(w, y, _V1_BYTE); + // Computing the t3 part. + gfmat_prod(y, sk->t3, _O1_BYTE, _O2, x_o2); + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_add(w + _V1_BYTE, y, _O1_BYTE); + + memset(signature, 0, _SIGNATURE_BYTE); // set the output 0 + // clean + memset(&prng_sign, 0, sizeof(prng_t)); + memset(vinegar, 0, _V1_BYTE); + memset(r_l1_F1, 0, _O1_BYTE); + memset(r_l2_F1, 0, _O2_BYTE); + memset(_z, 0, _PUB_M_BYTE); + memset(y, 0, _PUB_M_BYTE); + memset(x_o1, 0, _O1_BYTE); + memset(x_o2, 0, _O2_BYTE); + memset(temp_o, 0, sizeof(temp_o)); + + // return: copy w and salt to the signature. + if (MAX_ATTEMPT_FRMAT <= n_attempt) { + return -1; + } + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_add(signature, w, _PUB_N_BYTE); + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_add(signature + _PUB_N_BYTE, salt, _SALT_BYTE); + return 0; +} + +int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_rainbow_verify(const uint8_t *digest, const uint8_t *signature, const pk_t *pk) { + unsigned char digest_ck[_PUB_M_BYTE]; + // public_map( digest_ck , pk , signature ); Evaluating the quadratic public polynomials. + batch_quad_trimat_eval(digest_ck, pk->pk, signature, _PUB_N, _PUB_M_BYTE); + + unsigned char correct[_PUB_M_BYTE]; + unsigned char digest_salt[_HASH_LEN + _SALT_BYTE]; + memcpy(digest_salt, digest, _HASH_LEN); + memcpy(digest_salt + _HASH_LEN, signature + _PUB_N_BYTE, _SALT_BYTE); + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_hash_msg(correct, _PUB_M_BYTE, digest_salt, _HASH_LEN + _SALT_BYTE); // H( digest || salt ) + + // check consistancy. + unsigned char cc = 0; + for (unsigned int i = 0; i < _PUB_M_BYTE; i++) { + cc |= (digest_ck[i] ^ correct[i]); + } + return (0 == cc) ? 0 : -1; +} + + +int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_rainbow_verify_cyclic(const uint8_t *digest, const uint8_t *signature, const cpk_t *_pk) { + unsigned char pk[sizeof(pk_t) + 32]; + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_cpk_to_pk((pk_t *)pk, _pk); // generating classic public key. + return PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_rainbow_verify(digest, signature, (pk_t *)pk); +} diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/rainbow.h b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/rainbow.h new file mode 100644 index 0000000000..0835304111 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/rainbow.h @@ -0,0 +1,42 @@ +#ifndef _RAINBOW_H_ +#define _RAINBOW_H_ +/// @file rainbow.h +/// @brief APIs for rainbow. +/// + +#include "rainbow_config.h" +#include "rainbow_keypair.h" + +#include + +/// +/// @brief Signing function for classical secret key. +/// +/// @param[out] signature - the signature. +/// @param[in] sk - the secret key. +/// @param[in] digest - the digest. +/// +int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_rainbow_sign(uint8_t *signature, const sk_t *sk, const uint8_t *digest); + +/// +/// @brief Verifying function. +/// +/// @param[in] digest - the digest. +/// @param[in] signature - the signature. +/// @param[in] pk - the public key. +/// @return 0 for successful verified. -1 for failed verification. +/// +int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_rainbow_verify(const uint8_t *digest, const uint8_t *signature, const pk_t *pk); + + +/// +/// @brief Verifying function for cyclic public keys. +/// +/// @param[in] digest - the digest. +/// @param[in] signature - the signature. +/// @param[in] pk - the public key of cyclic rainbow. +/// @return 0 for successful verified. -1 for failed verification. +/// +int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_rainbow_verify_cyclic(const uint8_t *digest, const uint8_t *signature, const cpk_t *pk); + +#endif // _RAINBOW_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/rainbow_blas.h b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/rainbow_blas.h new file mode 100644 index 0000000000..e897cdb370 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/rainbow_blas.h @@ -0,0 +1,32 @@ +#ifndef _RAINBOW_BLAS_H_ +#define _RAINBOW_BLAS_H_ +/// @file rainbow_blas.h +/// @brief Defining the functions used in rainbow.c acconding to the definitions in rainbow_config.h +/// +/// Defining the functions used in rainbow.c acconding to the definitions in rainbow_config.h + +#include "blas.h" +#include "blas_comm.h" +#include "parallel_matrix_op.h" +#include "rainbow_config.h" + + +#define gfv_get_ele PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_get_ele +#define gfv_mul_scalar PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_mul_scalar +#define gfv_madd PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_madd + +#define gfmat_prod PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256mat_prod +#define gfmat_inv PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256mat_inv + +#define batch_trimat_madd PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_trimat_madd_gf256 +#define batch_trimatTr_madd PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_trimatTr_madd_gf256 +#define batch_2trimat_madd PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_2trimat_madd_gf256 +#define batch_matTr_madd PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_matTr_madd_gf256 +#define batch_bmatTr_madd PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_bmatTr_madd_gf256 +#define batch_mat_madd PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_mat_madd_gf256 + +#define batch_quad_trimat_eval PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_quad_trimat_eval_gf256 +#define batch_quad_recmat_eval PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_batch_quad_recmat_eval_gf256 + + +#endif // _RAINBOW_BLAS_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/rainbow_config.h b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/rainbow_config.h new file mode 100644 index 0000000000..b8bb361d69 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/rainbow_config.h @@ -0,0 +1,48 @@ +#ifndef _H_RAINBOW_CONFIG_H_ +#define _H_RAINBOW_CONFIG_H_ + +/// @file rainbow_config.h +/// @brief Defining the parameters of the Rainbow and the corresponding constants. +/// + +#define _GFSIZE 256 +#define _V1 68 +#define _O1 36 +#define _O2 36 +#define _MAX_O 36 +#define _HASH_LEN 48 + + +#define _V2 ((_V1) + (_O1)) + +/// size of N, in # of gf elements. +#define _PUB_N (_V1 + _O1 + _O2) + +/// size of M, in # gf elements. +#define _PUB_M (_O1 + _O2) + +/// size of variables, in # bytes. + +// GF256 +#define _V1_BYTE (_V1) +#define _V2_BYTE (_V2) +#define _O1_BYTE (_O1) +#define _O2_BYTE (_O2) +#define _MAX_O_BYTE (_MAX_O) +#define _PUB_N_BYTE (_PUB_N) +#define _PUB_M_BYTE (_PUB_M) + + +/// length of seed for public key, in # bytes +#define LEN_PKSEED 32 + +/// length of seed for secret key, in # bytes +#define LEN_SKSEED 32 + +/// length of salt for a signature, in # bytes +#define _SALT_BYTE 16 + +/// length of a signature +#define _SIGNATURE_BYTE (_PUB_N_BYTE + _SALT_BYTE) + +#endif // _H_RAINBOW_CONFIG_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/rainbow_keypair.c b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/rainbow_keypair.c new file mode 100644 index 0000000000..50450e00ee --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/rainbow_keypair.c @@ -0,0 +1,157 @@ +/// @file rainbow_keypair.c +/// @brief implementations of functions in rainbow_keypair.h +/// + +#include "rainbow_keypair.h" +#include "blas.h" +#include "blas_comm.h" +#include "rainbow_blas.h" +#include "rainbow_keypair_computation.h" +#include "utils_prng.h" +#include +#include +#include + +static void generate_S_T(unsigned char *s_and_t, prng_t *prng0) { + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_prng_gen(prng0, s_and_t, _O1_BYTE * _O2); // S1 + s_and_t += _O1_BYTE * _O2; + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_prng_gen(prng0, s_and_t, _V1_BYTE * _O1); // T1 + s_and_t += _V1_BYTE * _O1; + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_prng_gen(prng0, s_and_t, _V1_BYTE * _O2); // T2 + s_and_t += _V1_BYTE * _O2; + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_prng_gen(prng0, s_and_t, _O1_BYTE * _O2); // T3 +} + +static unsigned int generate_l1_F12(unsigned char *sk, prng_t *prng0) { + unsigned int n_byte_generated = 0; + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_prng_gen(prng0, sk, _O1_BYTE * N_TRIANGLE_TERMS(_V1)); // l1_F1 + sk += _O1_BYTE * N_TRIANGLE_TERMS(_V1); + n_byte_generated += _O1_BYTE * N_TRIANGLE_TERMS(_V1); + + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_prng_gen(prng0, sk, _O1_BYTE * _V1 * _O1); // l1_F2 + n_byte_generated += _O1_BYTE * _V1 * _O1; + return n_byte_generated; +} + +static unsigned int generate_l2_F12356(unsigned char *sk, prng_t *prng0) { + unsigned int n_byte_generated = 0; + + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * N_TRIANGLE_TERMS(_V1)); // l2_F1 + sk += _O2_BYTE * N_TRIANGLE_TERMS(_V1); + n_byte_generated += _O2_BYTE * N_TRIANGLE_TERMS(_V1); + + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * _V1 * _O1); // l2_F2 + sk += _O2_BYTE * _V1 * _O1; + n_byte_generated += _O2_BYTE * _V1 * _O1; + + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * _V1 * _O2); // l2_F3 + sk += _O2_BYTE * _V1 * _O1; + n_byte_generated += _O2_BYTE * _V1 * _O1; + + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * N_TRIANGLE_TERMS(_O1)); // l2_F5 + sk += _O2_BYTE * N_TRIANGLE_TERMS(_O1); + n_byte_generated += _O2_BYTE * N_TRIANGLE_TERMS(_O1); + + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * _O1 * _O2); // l2_F6 + n_byte_generated += _O2_BYTE * _O1 * _O2; + + return n_byte_generated; +} + +static void generate_B1_B2(unsigned char *sk, prng_t *prng0) { + sk += generate_l1_F12(sk, prng0); + generate_l2_F12356(sk, prng0); +} + +static void calculate_t4(unsigned char *t2_to_t4, const unsigned char *t1, const unsigned char *t3) { + // t4 = T_sk.t1 * T_sk.t3 - T_sk.t2 + unsigned char temp[_V1_BYTE + 32]; + unsigned char *t4 = t2_to_t4; + for (unsigned int i = 0; i < _O2; i++) { /// t3 width + gfmat_prod(temp, t1, _V1_BYTE, _O1, t3); + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_add(t4, temp, _V1_BYTE); + t4 += _V1_BYTE; + t3 += _O1_BYTE; + } +} + +static void obsfucate_l1_polys(unsigned char *l1_polys, const unsigned char *l2_polys, unsigned int n_terms, const unsigned char *s1) { + unsigned char temp[_O1_BYTE + 32]; + while (n_terms--) { + gfmat_prod(temp, s1, _O1_BYTE, _O2, l2_polys); + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_gf256v_add(l1_polys, temp, _O1_BYTE); + l1_polys += _O1_BYTE; + l2_polys += _O2_BYTE; + } +} + +/////////////////// Classic ////////////////////////////////// + + +///////////////////// Cyclic ////////////////////////////////// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_generate_keypair_cyclic(cpk_t *pk, sk_t *sk, const unsigned char *pk_seed, const unsigned char *sk_seed) { + memcpy(pk->pk_seed, pk_seed, LEN_PKSEED); + memcpy(sk->sk_seed, sk_seed, LEN_SKSEED); + + // prng for sk + prng_t prng; + prng_t *prng0 = &prng; + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_prng_set(prng0, sk_seed, LEN_SKSEED); + generate_S_T(sk->s1, prng0); // S,T: only a part of sk + + unsigned char t2[sizeof(sk->t4)]; + memcpy(t2, sk->t4, _V1_BYTE * _O2); // temporarily store t2 + calculate_t4(sk->t4, sk->t1, sk->t3); // t2 <- t4 + + // prng for pk + sk_t inst_Qs; + sk_t *Qs = &inst_Qs; + prng_t *prng1 = &prng; + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_prng_set(prng1, pk_seed, LEN_PKSEED); + generate_B1_B2(Qs->l1_F1, prng1); // generating l1_Q1, l1_Q2, l2_Q1, l2_Q2, l2_Q3, l2_Q5, l2_Q6 + obsfucate_l1_polys(Qs->l1_F1, Qs->l2_F1, N_TRIANGLE_TERMS(_V1), sk->s1); + obsfucate_l1_polys(Qs->l1_F2, Qs->l2_F2, _V1 * _O1, sk->s1); + // so far, the Qs contains l1_F1, l1_F2, l2_F1, l2_F2, l2_F3, l2_F5, l2_F6. + + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_calculate_F_from_Q(sk, Qs, sk); // calcuate the rest parts of secret key from Qs and S,T + + unsigned char t4[sizeof(sk->t4)]; + memcpy(t4, sk->t4, _V1_BYTE * _O2); // temporarily store t4 + memcpy(sk->t4, t2, _V1_BYTE * _O2); // restore t2 + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_calculate_Q_from_F_cyclic(pk, sk, sk); // calculate the rest parts of public key: l1_Q3, l1_Q5, l1_Q6, l1_Q9, l2_Q9 + memcpy(sk->t4, t4, _V1_BYTE * _O2); // restore t4 + + obsfucate_l1_polys(pk->l1_Q3, Qs->l2_F3, _V1 * _O2, sk->s1); + obsfucate_l1_polys(pk->l1_Q5, Qs->l2_F5, N_TRIANGLE_TERMS(_O1), sk->s1); + obsfucate_l1_polys(pk->l1_Q6, Qs->l2_F6, _O1 * _O2, sk->s1); + obsfucate_l1_polys(pk->l1_Q9, pk->l2_Q9, N_TRIANGLE_TERMS(_O2), sk->s1); + + // clean + memset(&prng, 0, sizeof(prng_t)); +} + + + +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_cpk_to_pk(pk_t *rpk, const cpk_t *cpk) { + // procedure: cpk_t --> extcpk_t --> pk_t + + // convert from cpk_t to extcpk_t + ext_cpk_t pk; + + // setup prng + prng_t prng0; + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_prng_set(&prng0, cpk->pk_seed, LEN_SKSEED); + + // generating parts of key with prng + generate_l1_F12(pk.l1_Q1, &prng0); + // copying parts of key from input. l1_Q3, l1_Q5, l1_Q6, l1_Q9 + memcpy(pk.l1_Q3, cpk->l1_Q3, _O1_BYTE * (_V1 * _O2 + N_TRIANGLE_TERMS(_O1) + _O1 * _O2 + N_TRIANGLE_TERMS(_O2))); + + // generating parts of key with prng + generate_l2_F12356(pk.l2_Q1, &prng0); + // copying parts of key from input: l2_Q9 + memcpy(pk.l2_Q9, cpk->l2_Q9, _O2_BYTE * N_TRIANGLE_TERMS(_O2)); + + // convert from extcpk_t to pk_t + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_extcpk_to_pk(rpk, &pk); +} diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/rainbow_keypair.h b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/rainbow_keypair.h new file mode 100644 index 0000000000..33f55e322a --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/rainbow_keypair.h @@ -0,0 +1,94 @@ +#ifndef _RAINBOW_KEYPAIR_H_ +#define _RAINBOW_KEYPAIR_H_ +/// @file rainbow_keypair.h +/// @brief Formats of key pairs and functions for generating key pairs. +/// Formats of key pairs and functions for generating key pairs. +/// + +#include "rainbow_config.h" + +#define N_TRIANGLE_TERMS(n_var) ((n_var) * ((n_var) + 1) / 2) + +/// @brief public key for classic rainbow +/// +/// public key for classic rainbow +/// +typedef struct rainbow_publickey { + unsigned char pk[(_PUB_M_BYTE)*N_TRIANGLE_TERMS(_PUB_N)]; +} pk_t; + +/// @brief secret key for classic rainbow +/// +/// secret key for classic rainbow +/// +typedef struct rainbow_secretkey { + /// + /// seed for generating secret key. + /// Generating S, T, and F for classic rainbow. + /// Generating S and T only for cyclic rainbow. + unsigned char sk_seed[LEN_SKSEED]; + + unsigned char s1[_O1_BYTE * _O2]; ///< part of S map + unsigned char t1[_V1_BYTE * _O1]; ///< part of T map + unsigned char t4[_V1_BYTE * _O2]; ///< part of T map + unsigned char t3[_O1_BYTE * _O2]; ///< part of T map + + unsigned char l1_F1[_O1_BYTE * N_TRIANGLE_TERMS(_V1)]; ///< part of C-map, F1, Layer1 + unsigned char l1_F2[_O1_BYTE * _V1 * _O1]; ///< part of C-map, F2, Layer1 + + unsigned char l2_F1[_O2_BYTE * N_TRIANGLE_TERMS(_V1)]; ///< part of C-map, F1, Layer2 + unsigned char l2_F2[_O2_BYTE * _V1 * _O1]; ///< part of C-map, F2, Layer2 + + unsigned char l2_F3[_O2_BYTE * _V1 * _O2]; ///< part of C-map, F3, Layer2 + unsigned char l2_F5[_O2_BYTE * N_TRIANGLE_TERMS(_O1)]; ///< part of C-map, F5, Layer2 + unsigned char l2_F6[_O2_BYTE * _O1 * _O2]; ///< part of C-map, F6, Layer2 +} sk_t; + +/// @brief public key for cyclic rainbow +/// +/// public key for cyclic rainbow +/// +typedef struct rainbow_publickey_cyclic { + unsigned char pk_seed[LEN_PKSEED]; ///< seed for generating l1_Q1,l1_Q2,l2_Q1,l2_Q2,l2_Q3,l2_Q5,l2_Q6 + + unsigned char l1_Q3[_O1_BYTE * _V1 * _O2]; ///< Q3, layer1 + unsigned char l1_Q5[_O1_BYTE * N_TRIANGLE_TERMS(_O1)]; ///< Q5, layer1 + unsigned char l1_Q6[_O1_BYTE * _O1 * _O2]; ///< Q6, layer1 + unsigned char l1_Q9[_O1_BYTE * N_TRIANGLE_TERMS(_O2)]; ///< Q9, layer1 + + unsigned char l2_Q9[_O2_BYTE * N_TRIANGLE_TERMS(_O2)]; ///< Q9, layer2 +} cpk_t; + +/// @brief compressed secret key for cyclic rainbow +/// +/// compressed secret key for cyclic rainbow +/// +typedef struct rainbow_secretkey_cyclic { + unsigned char pk_seed[LEN_PKSEED]; ///< seed for generating a part of public key. + unsigned char sk_seed[LEN_SKSEED]; ///< seed for generating a part of secret key. +} csk_t; + + +/// +/// @brief Generate key pairs for cyclic rainbow. +/// +/// @param[out] pk - the public key. +/// @param[out] sk - the secret key. +/// @param[in] pk_seed - seed for generating parts of public key. +/// @param[in] sk_seed - seed for generating secret key. +/// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_generate_keypair_cyclic(cpk_t *pk, sk_t *sk, const unsigned char *pk_seed, const unsigned char *sk_seed); + + + +//////////////////////////////////// + +/// +/// @brief converting formats of public keys : from cyclic version to classic key +/// +/// @param[out] pk - the classic public key. +/// @param[in] cpk - the cyclic public key. +/// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_cpk_to_pk(pk_t *pk, const cpk_t *cpk); + +#endif // _RAINBOW_KEYPAIR_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/rainbow_keypair_computation.c b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/rainbow_keypair_computation.c new file mode 100644 index 0000000000..ab38bca7b5 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/rainbow_keypair_computation.c @@ -0,0 +1,213 @@ +/// @file rainbow_keypair_computation.c +/// @brief Implementations for functions in rainbow_keypair_computation.h +/// + +#include "rainbow_keypair_computation.h" +#include "blas.h" +#include "blas_comm.h" +#include "rainbow_blas.h" +#include "rainbow_keypair.h" +#include +#include +#include + +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_extcpk_to_pk(pk_t *pk, const ext_cpk_t *cpk) { + const unsigned char *idx_l1 = cpk->l1_Q1; + const unsigned char *idx_l2 = cpk->l2_Q1; + for (unsigned int i = 0; i < _V1; i++) { + for (unsigned int j = i; j < _V1; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q2; + idx_l2 = cpk->l2_Q2; + for (unsigned int i = 0; i < _V1; i++) { + for (unsigned int j = _V1; j < _V1 + _O1; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q3; + idx_l2 = cpk->l2_Q3; + for (unsigned int i = 0; i < _V1; i++) { + for (unsigned int j = _V1 + _O1; j < _PUB_N; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q5; + idx_l2 = cpk->l2_Q5; + for (unsigned int i = _V1; i < _V1 + _O1; i++) { + for (unsigned int j = i; j < _V1 + _O1; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q6; + idx_l2 = cpk->l2_Q6; + for (unsigned int i = _V1; i < _V1 + _O1; i++) { + for (unsigned int j = _V1 + _O1; j < _PUB_N; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q9; + idx_l2 = cpk->l2_Q9; + for (unsigned int i = _V1 + _O1; i < _PUB_N; i++) { + for (unsigned int j = i; j < _PUB_N; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } +} + +static void calculate_F_from_Q_ref(sk_t *Fs, const sk_t *Qs, sk_t *Ts) { + // Layer 1 + // F_sk.l1_F1s[i] = Q_pk.l1_F1s[i] + memcpy(Fs->l1_F1, Qs->l1_F1, _O1_BYTE * N_TRIANGLE_TERMS(_V1)); + + // F_sk.l1_F2s[i] = ( Q_pk.l1_F1s[i] + Q_pk.l1_F1s[i].transpose() ) * T_sk.t1 + Q_pk.l1_F2s[i] + memcpy(Fs->l1_F2, Qs->l1_F2, _O1_BYTE * _V1 * _O1); + batch_2trimat_madd(Fs->l1_F2, Qs->l1_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O1_BYTE); + + /* + Layer 2 + computations: + + F_sk.l2_F1s[i] = Q_pk.l2_F1s[i] + + Q1_T1 = Q_pk.l2_F1s[i]*T_sk.t1 + F_sk.l2_F2s[i] = Q1_T1 + Q_pk.l2_F2s[i] + Q_pk.l2_F1s[i].transpose() * T_sk.t1 + F_sk.l2_F5s[i] = UT( t1_tr* ( Q1_T1 + Q_pk.l2_F2s[i] ) ) + Q_pk.l2_F5s[i] + + Q1_Q1T_T4 = (Q_pk.l2_F1s[i] + Q_pk.l2_F1s[i].transpose()) * t4 + #Q1_Q1T_T4 = Q1_Q1T * t4 + Q2_T3 = Q_pk.l2_F2s[i]*T_sk.t3 + F_sk.l2_F3s[i] = Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] + F_sk.l2_F6s[i] = t1_tr * ( Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] ) + + Q_pk.l2_F2s[i].transpose() * t4 + + (Q_pk.l2_F5s[i] + Q_pk.l2_F5s[i].transpose())*T_sk.t3 + Q_pk.l2_F6s[i] + + */ + memcpy(Fs->l2_F1, Qs->l2_F1, _O2_BYTE * N_TRIANGLE_TERMS(_V1)); // F_sk.l2_F1s[i] = Q_pk.l2_F1s[i] + + // F_sk.l2_F2s[i] = Q1_T1 + Q_pk.l2_F2s[i] + Q_pk.l2_F1s[i].transpose() * T_sk.t1 + // F_sk.l2_F5s[i] = UT( t1_tr* ( Q1_T1 + Q_pk.l2_F2s[i] ) ) + Q_pk.l2_F5s[i] + memcpy(Fs->l2_F2, Qs->l2_F2, _O2_BYTE * _V1 * _O1); + batch_trimat_madd(Fs->l2_F2, Qs->l2_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O2_BYTE); // Q1_T1+ Q2 + + unsigned char tempQ[_O1 * _O1 * _O2_BYTE + 32]; + memset(tempQ, 0, _O1 * _O1 * _O2_BYTE); + batch_matTr_madd(tempQ, Ts->t1, _V1, _V1_BYTE, _O1, Fs->l2_F2, _O1, _O2_BYTE); // t1_tr*(Q1_T1+Q2) + memcpy(Fs->l2_F5, Qs->l2_F5, _O2_BYTE * N_TRIANGLE_TERMS(_O1)); // F5 + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_UpperTrianglize(Fs->l2_F5, tempQ, _O1, _O2_BYTE); // UT( ... ) + + batch_trimatTr_madd(Fs->l2_F2, Qs->l2_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O2_BYTE); // F2 = Q1_T1 + Q2 + Q1^tr*t1 + + // Q1_Q1T_T4 = (Q_pk.l2_F1s[i] + Q_pk.l2_F1s[i].transpose()) * t4 + // Q2_T3 = Q_pk.l2_F2s[i]*T_sk.t3 + // F_sk.l2_F3s[i] = Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] + memcpy(Fs->l2_F3, Qs->l2_F3, _V1 * _O2 * _O2_BYTE); + batch_2trimat_madd(Fs->l2_F3, Qs->l2_F1, Ts->t4, _V1, _V1_BYTE, _O2, _O2_BYTE); // Q1_Q1T_T4 + batch_mat_madd(Fs->l2_F3, Qs->l2_F2, _V1, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // Q2_T3 + + // F_sk.l2_F6s[i] = t1_tr * ( Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] ) + // + Q_pk.l2_F2s[i].transpose() * t4 + // + (Q_pk.l2_F5s[i] + Q_pk.l2_F5s[i].transpose())*T_sk.t3 + Q_pk.l2_F6s[i] + memcpy(Fs->l2_F6, Qs->l2_F6, _O1 * _O2 * _O2_BYTE); + batch_matTr_madd(Fs->l2_F6, Ts->t1, _V1, _V1_BYTE, _O1, Fs->l2_F3, _O2, _O2_BYTE); // t1_tr * ( Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] ) + batch_2trimat_madd(Fs->l2_F6, Qs->l2_F5, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // (Q_pk.l2_F5s[i] + Q_pk.l2_F5s[i].transpose())*T_sk.t3 + batch_bmatTr_madd(Fs->l2_F6, Qs->l2_F2, _O1, Ts->t4, _V1, _V1_BYTE, _O2, _O2_BYTE); +} + +static void calculate_Q_from_F_cyclic_ref(cpk_t *Qs, const sk_t *Fs, const sk_t *Ts) { + // Layer 1: Computing Q5, Q3, Q6, Q9 + + // Q_pk.l1_F5s[i] = UT( T1tr* (F1 * T1 + F2) ) + const unsigned char *t2 = Ts->t4; + sk_t tempQ; + memcpy(tempQ.l1_F2, Fs->l1_F2, _O1_BYTE * _V1 * _O1); + batch_trimat_madd(tempQ.l1_F2, Fs->l1_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O1_BYTE); // F1*T1 + F2 + memset(tempQ.l2_F1, 0, sizeof(tempQ.l2_F1)); + memset(tempQ.l2_F2, 0, sizeof(tempQ.l2_F2)); + batch_matTr_madd(tempQ.l2_F1, Ts->t1, _V1, _V1_BYTE, _O1, tempQ.l1_F2, _O1, _O1_BYTE); // T1tr*(F1*T1 + F2) + memset(Qs->l1_Q5, 0, _O1_BYTE * N_TRIANGLE_TERMS(_O1)); + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_UpperTrianglize(Qs->l1_Q5, tempQ.l2_F1, _O1, _O1_BYTE); // UT( ... ) // Q5 + + /* + F1_T2 = F1 * t2 + F2_T3 = F2 * t3 + F1_F1T_T2 + F2_T3 = F1_T2 + F2_T3 + F1tr * t2 + Q_pk.l1_F3s[i] = F1_F1T_T2 + F2_T3 + Q_pk.l1_F6s[i] = T1tr* ( F1_F1T_T2 + F2_T3 ) + F2tr * t2 + Q_pk.l1_F9s[i] = UT( T2tr* ( F1_T2 + F2_T3 ) ) + */ + memset(Qs->l1_Q3, 0, _O1_BYTE * _V1 * _O2); + memset(Qs->l1_Q6, 0, _O1_BYTE * _O1 * _O2); + memset(Qs->l1_Q9, 0, _O1_BYTE * N_TRIANGLE_TERMS(_O2)); + + batch_trimat_madd(Qs->l1_Q3, Fs->l1_F1, t2, _V1, _V1_BYTE, _O2, _O1_BYTE); // F1*T2 + batch_mat_madd(Qs->l1_Q3, Fs->l1_F2, _V1, Ts->t3, _O1, _O1_BYTE, _O2, _O1_BYTE); // F1_T2 + F2_T3 + + memset(tempQ.l1_F2, 0, _O1_BYTE * _V1 * _O2); // should be F3. assuming: _O1 >= _O2 + batch_matTr_madd(tempQ.l1_F2, t2, _V1, _V1_BYTE, _O2, Qs->l1_Q3, _O2, _O1_BYTE); // T2tr * ( F1_T2 + F2_T3 ) + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_UpperTrianglize(Qs->l1_Q9, tempQ.l1_F2, _O2, _O1_BYTE); // Q9 + + batch_trimatTr_madd(Qs->l1_Q3, Fs->l1_F1, t2, _V1, _V1_BYTE, _O2, _O1_BYTE); // F1_F1T_T2 + F2_T3 // Q3 + + batch_bmatTr_madd(Qs->l1_Q6, Fs->l1_F2, _O1, t2, _V1, _V1_BYTE, _O2, _O1_BYTE); // F2tr*T2 + batch_matTr_madd(Qs->l1_Q6, Ts->t1, _V1, _V1_BYTE, _O1, Qs->l1_Q3, _O2, _O1_BYTE); // Q6 + /* + Layer 2 + Computing Q9: + + F1_T2 = F1 * t2 + F2_T3 = F2 * t3 + Q9 = UT( T2tr*( F1*T2 + F2*T3 + F3 ) + T3tr*( F5*T3 + F6 ) ) + */ + sk_t tempQ2; + memcpy(tempQ2.l2_F3, Fs->l2_F3, _O2_BYTE * _V1 * _O2); /// F3 actually. + batch_trimat_madd(tempQ2.l2_F3, Fs->l2_F1, t2, _V1, _V1_BYTE, _O2, _O2_BYTE); // F1*T2 + F3 + batch_mat_madd(tempQ2.l2_F3, Fs->l2_F2, _V1, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // F1_T2 + F2_T3 + F3 + + memset(tempQ.l2_F3, 0, _O2_BYTE * _V1 * _O2); + batch_matTr_madd(tempQ.l2_F3, t2, _V1, _V1_BYTE, _O2, tempQ2.l2_F3, _O2, _O2_BYTE); // T2tr * ( ..... ) + + memcpy(tempQ.l2_F6, Fs->l2_F6, _O2_BYTE * _O1 * _O2); + batch_trimat_madd(tempQ.l2_F6, Fs->l2_F5, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // F5*T3 + F6 + + batch_matTr_madd(tempQ.l2_F3, Ts->t3, _O1, _O1_BYTE, _O2, tempQ.l2_F6, _O2, _O2_BYTE); // T2tr*( ..... ) + T3tr*( ..... ) + memset(Qs->l2_Q9, 0, _O2_BYTE * N_TRIANGLE_TERMS(_O2)); + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_UpperTrianglize(Qs->l2_Q9, tempQ.l2_F3, _O2, _O2_BYTE); // Q9 +} + +// Choosing implementations depends on the macros: _BLAS_SSE_ and _BLAS_AVX2_ +#define calculate_F_from_Q_impl calculate_F_from_Q_ref +#define calculate_Q_from_F_cyclic_impl calculate_Q_from_F_cyclic_ref + +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_calculate_F_from_Q(sk_t *Fs, const sk_t *Qs, sk_t *Ts) { + calculate_F_from_Q_impl(Fs, Qs, Ts); +} + +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_calculate_Q_from_F_cyclic(cpk_t *Qs, const sk_t *Fs, const sk_t *Ts) { + calculate_Q_from_F_cyclic_impl(Qs, Fs, Ts); +} diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/rainbow_keypair_computation.h b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/rainbow_keypair_computation.h new file mode 100644 index 0000000000..6e6eeef979 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/rainbow_keypair_computation.h @@ -0,0 +1,71 @@ +#ifndef _RAINBOW_KEYPAIR_COMP_H_ +#define _RAINBOW_KEYPAIR_COMP_H_ +/// @file rainbow_keypair_computation.h +/// @brief Functions for calculating pk/sk while generating keys. +/// +/// Defining an internal structure of public key. +/// Functions for calculating pk/sk for key generation. +/// + +#include "rainbow_keypair.h" + +/// @brief The (internal use) public key for rainbow +/// +/// The (internal use) public key for rainbow. The public +/// polynomials are divided into l1_Q1, l1_Q2, ... l1_Q9, +/// l2_Q1, .... , l2_Q9. +/// +typedef struct rainbow_extend_publickey { + unsigned char l1_Q1[_O1_BYTE * N_TRIANGLE_TERMS(_V1)]; + unsigned char l1_Q2[_O1_BYTE * _V1 * _O1]; + unsigned char l1_Q3[_O1_BYTE * _V1 * _O2]; + unsigned char l1_Q5[_O1_BYTE * N_TRIANGLE_TERMS(_O1)]; + unsigned char l1_Q6[_O1_BYTE * _O1 * _O2]; + unsigned char l1_Q9[_O1_BYTE * N_TRIANGLE_TERMS(_O2)]; + + unsigned char l2_Q1[_O2_BYTE * N_TRIANGLE_TERMS(_V1)]; + unsigned char l2_Q2[_O2_BYTE * _V1 * _O1]; + unsigned char l2_Q3[_O2_BYTE * _V1 * _O2]; + unsigned char l2_Q5[_O2_BYTE * N_TRIANGLE_TERMS(_O1)]; + unsigned char l2_Q6[_O2_BYTE * _O1 * _O2]; + unsigned char l2_Q9[_O2_BYTE * N_TRIANGLE_TERMS(_O2)]; +} ext_cpk_t; + +/// +/// @brief converting formats of public keys : from ext_cpk_t version to pk_t +/// +/// @param[out] pk - the classic public key. +/// @param[in] cpk - the internel public key. +/// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_extcpk_to_pk(pk_t *pk, const ext_cpk_t *cpk); +///////////////////////////////////////////////// + +/// +/// @brief Computing public key from secret key +/// +/// @param[out] Qs - the public key +/// @param[in] Fs - parts of the secret key: l1_F1, l1_F2, l2_F1, l2_F2, l2_F3, l2_F5, l2_F6 +/// @param[in] Ts - parts of the secret key: T1, T4, T3 +/// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_calculate_Q_from_F(ext_cpk_t *Qs, const sk_t *Fs, const sk_t *Ts); + + +/// +/// @brief Computing parts of the sk from parts of pk and sk +/// +/// @param[out] Fs - parts of the sk: l1_F1, l1_F2, l2_F1, l2_F2, l2_F3, l2_F5, l2_F6 +/// @param[in] Qs - parts of the pk: l1_Q1, l1_Q2, l2_Q1, l2_Q2, l2_Q3, l2_Q5, l2_Q6 +/// @param[in] Ts - parts of the sk: T1, T4, T3 +/// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_calculate_F_from_Q(sk_t *Fs, const sk_t *Qs, sk_t *Ts); + +/// +/// @brief Computing parts of the pk from the secret key +/// +/// @param[out] Qs - parts of the pk: l1_Q3, l1_Q5, l2_Q6, l1_Q9, l2_Q9 +/// @param[in] Fs - parts of the sk: l1_F1, l1_F2, l2_F1, l2_F2, l2_F3, l2_F5, l2_F6 +/// @param[in] Ts - parts of the sk: T1, T4, T3 +/// +void PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_calculate_Q_from_F_cyclic(cpk_t *Qs, const sk_t *Fs, const sk_t *Ts); + +#endif // _RAINBOW_KEYPAIR_COMP_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/sign.c b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/sign.c new file mode 100644 index 0000000000..72a6ca39b2 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/sign.c @@ -0,0 +1,76 @@ +/// @file sign.c +/// @brief the implementations for functions in api.h +/// +/// + +#include "api.h" +#include "rainbow.h" +#include "rainbow_config.h" +#include "rainbow_keypair.h" +#include "randombytes.h" +#include "utils_hash.h" +#include +#include + +int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { + unsigned char sk_seed[LEN_SKSEED] = {0}; + randombytes(sk_seed, LEN_SKSEED); + + unsigned char pk_seed[LEN_PKSEED] = {0}; + randombytes(pk_seed, LEN_PKSEED); + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_generate_keypair_cyclic((cpk_t *)pk, (sk_t *)sk, pk_seed, sk_seed); + return 0; +} + +int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { + unsigned char digest[_HASH_LEN]; + + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_hash_msg(digest, _HASH_LEN, m, mlen); + + memcpy(sm, m, mlen); + smlen[0] = mlen + _SIGNATURE_BYTE; + + return PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_rainbow_sign(sm + mlen, (const sk_t *)sk, digest); +} + +int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { + int rc; + if (_SIGNATURE_BYTE > smlen) { + rc = -1; + } else { + *mlen = smlen - _SIGNATURE_BYTE; + + unsigned char digest[_HASH_LEN]; + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_hash_msg(digest, _HASH_LEN, sm, *mlen); + + rc = PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_rainbow_verify_cyclic(digest, sm + mlen[0], (const cpk_t *)pk); + } + if (!rc) { + memmove(m, sm, smlen - _SIGNATURE_BYTE); + } else { // bad signature + *mlen = (size_t) -1; + memset(m, 0, smlen); + } + return rc; +} + +int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_crypto_sign_signature( + uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + unsigned char digest[_HASH_LEN]; + + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_hash_msg(digest, _HASH_LEN, m, mlen); + *siglen = _SIGNATURE_BYTE; + return PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_rainbow_sign(sig, (const sk_t *)sk, digest); +} + +int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_crypto_sign_verify( + const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + if (siglen != _SIGNATURE_BYTE) { + return -1; + } + unsigned char digest[_HASH_LEN]; + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_hash_msg(digest, _HASH_LEN, m, mlen); + return PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_rainbow_verify_cyclic(digest, sig, (const cpk_t *)pk); +} diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/utils_hash.c b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/utils_hash.c new file mode 100644 index 0000000000..4219df7589 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/utils_hash.c @@ -0,0 +1,50 @@ +/// @file utils_hash.c +/// @brief the adapter for SHA2 families. +/// +/// + +#include "utils_hash.h" +#include "rainbow_config.h" +#include "sha2.h" + +static inline int _hash(unsigned char *digest, const unsigned char *m, size_t mlen) { + sha384(digest, m, mlen); + return 0; +} + +static inline int expand_hash(unsigned char *digest, size_t n_digest, const unsigned char *hash) { + if (_HASH_LEN >= n_digest) { + for (size_t i = 0; i < n_digest; i++) { + digest[i] = hash[i]; + } + return 0; + } + for (size_t i = 0; i < _HASH_LEN; i++) { + digest[i] = hash[i]; + } + n_digest -= _HASH_LEN; + + while (_HASH_LEN <= n_digest) { + _hash(digest + _HASH_LEN, digest, _HASH_LEN); + + n_digest -= _HASH_LEN; + digest += _HASH_LEN; + } + unsigned char temp[_HASH_LEN]; + if (n_digest) { + _hash(temp, digest, _HASH_LEN); + for (size_t i = 0; i < n_digest; i++) { + digest[_HASH_LEN + i] = temp[i]; + } + } + return 0; +} + +int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_hash_msg(unsigned char *digest, + size_t len_digest, + const unsigned char *m, + size_t mlen) { + unsigned char buf[_HASH_LEN]; + _hash(buf, m, mlen); + return expand_hash(digest, len_digest, buf); +} diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/utils_hash.h b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/utils_hash.h new file mode 100644 index 0000000000..24231e349b --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/utils_hash.h @@ -0,0 +1,11 @@ +#ifndef _UTILS_HASH_H_ +#define _UTILS_HASH_H_ +/// @file utils_hash.h +/// @brief the interface for adapting hash functions. +/// + +#include + +int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_hash_msg(unsigned char *digest, size_t len_digest, const unsigned char *m, size_t mlen); + +#endif // _UTILS_HASH_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/utils_prng.c b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/utils_prng.c new file mode 100644 index 0000000000..9367e03753 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/utils_prng.c @@ -0,0 +1,97 @@ +/// @file utils_prng.c +/// @brief The implementation of PRNG related functions. +/// + +#include "utils_prng.h" +#include "aes.h" +#include "randombytes.h" +#include "utils_hash.h" +#include +#include + +static void prng_update(const unsigned char *provided_data, + unsigned char *Key, + unsigned char *V) { + unsigned char temp[48]; + aes256ctx ctx; + aes256_keyexp(&ctx, Key); + for (int i = 0; i < 3; i++) { + //increment V + for (int j = 15; j >= 0; j--) { + if (V[j] == 0xff) { + V[j] = 0x00; + } else { + V[j]++; + break; + } + } + aes256_ecb(temp + 16 * i, V, 1, &ctx); + } + if (provided_data != NULL) { + for (int i = 0; i < 48; i++) { + temp[i] ^= provided_data[i]; + } + } + aes256_ctx_release(&ctx); + memcpy(Key, temp, 32); + memcpy(V, temp + 32, 16); +} +static void randombytes_init_with_state(prng_t *state, + unsigned char *entropy_input_48bytes) { + memset(state->Key, 0x00, 32); + memset(state->V, 0x00, 16); + prng_update(entropy_input_48bytes, state->Key, state->V); +} + +static int randombytes_with_state(prng_t *state, + unsigned char *x, + size_t xlen) { + + unsigned char block[16]; + int i = 0; + + aes256ctx ctx; + aes256_keyexp(&ctx, state->Key); + + while (xlen > 0) { + //increment V + for (int j = 15; j >= 0; j--) { + if (state->V[j] == 0xff) { + state->V[j] = 0x00; + } else { + state->V[j]++; + break; + } + } + aes256_ecb(block, state->V, 1, &ctx); + if (xlen > 15) { + memcpy(x + i, block, 16); + i += 16; + xlen -= 16; + } else { + memcpy(x + i, block, xlen); + xlen = 0; + } + } + aes256_ctx_release(&ctx); + prng_update(NULL, state->Key, state->V); + return 0; +} + +int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_prng_set(prng_t *ctx, const void *prng_seed, unsigned long prng_seedlen) { + unsigned char seed[48]; + if (prng_seedlen >= 48) { + memcpy(seed, prng_seed, 48); + } else { + memcpy(seed, prng_seed, prng_seedlen); + PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_hash_msg(seed + prng_seedlen, 48 - (unsigned)prng_seedlen, (const unsigned char *)prng_seed, prng_seedlen); + } + + randombytes_init_with_state(ctx, seed); + + return 0; +} + +int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_prng_gen(prng_t *ctx, unsigned char *out, unsigned long outlen) { + return randombytes_with_state(ctx, out, outlen); +} diff --git a/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/utils_prng.h b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/utils_prng.h new file mode 100644 index 0000000000..403a42309a --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIIIc-cyclic_clean/utils_prng.h @@ -0,0 +1,18 @@ +#ifndef _UTILS_PRNG_H_ +#define _UTILS_PRNG_H_ +/// @file utils_prng.h +/// @brief the interface for adapting PRNG functions. +/// +/// + +#include "randombytes.h" + +typedef struct { + unsigned char Key[32]; + unsigned char V[16]; +} prng_t; + +int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_prng_set(prng_t *ctx, const void *prng_seed, unsigned long prng_seedlen); +int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_prng_gen(prng_t *ctx, unsigned char *out, unsigned long outlen); + +#endif // _UTILS_PRNG_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-classic_clean/LICENSE b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/LICENSE new file mode 100644 index 0000000000..cb00a6e354 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/LICENSE @@ -0,0 +1,8 @@ +`Software implementation of Rainbow for NIST R2 submission' by Ming-Shing Chen + +To the extent possible under law, the person who associated CC0 with +`Software implementation of Rainbow for NIST R2 submission' has waived all copyright and related or neighboring rights +to `Software implementation of Rainbow for NIST R2 submission'. + +You should have received a copy of the CC0 legalcode along with this +work. If not, see . diff --git a/src/sig/rainbow/pqclean_rainbowIa-classic_clean/api.h b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/api.h new file mode 100644 index 0000000000..f4447b7537 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/api.h @@ -0,0 +1,32 @@ +#ifndef PQCLEAN_RAINBOWIACLASSIC_CLEAN_API_H +#define PQCLEAN_RAINBOWIACLASSIC_CLEAN_API_H + +#include +#include + +#define PQCLEAN_RAINBOWIACLASSIC_CLEAN_CRYPTO_SECRETKEYBYTES 92960 +#define PQCLEAN_RAINBOWIACLASSIC_CLEAN_CRYPTO_PUBLICKEYBYTES 148992 +#define PQCLEAN_RAINBOWIACLASSIC_CLEAN_CRYPTO_BYTES 64 +#define PQCLEAN_RAINBOWIACLASSIC_CLEAN_CRYPTO_ALGNAME "RAINBOW(16,32,32,32) - classic" + +int PQCLEAN_RAINBOWIACLASSIC_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + + +int PQCLEAN_RAINBOWIACLASSIC_CLEAN_crypto_sign_signature( + uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +int PQCLEAN_RAINBOWIACLASSIC_CLEAN_crypto_sign_verify( + const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +int PQCLEAN_RAINBOWIACLASSIC_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +int PQCLEAN_RAINBOWIACLASSIC_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + + +#endif diff --git a/src/sig/rainbow/pqclean_rainbowIa-classic_clean/blas.c b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/blas.c new file mode 100644 index 0000000000..835ef68a88 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/blas.c @@ -0,0 +1,43 @@ +#include "blas.h" +#include "gf.h" + +#include + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_predicated_add(uint8_t *accu_b, uint8_t predicate, const uint8_t *a, size_t _num_byte) { + uint8_t pr_u8 = (uint8_t) ((uint8_t) 0 - predicate); + for (size_t i = 0; i < _num_byte; i++) { + accu_b[i] ^= (a[i] & pr_u8); + } +} + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_add(uint8_t *accu_b, const uint8_t *a, size_t _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + accu_b[i] ^= a[i]; + } +} + + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_mul_scalar(uint8_t *a, uint8_t gf16_b, size_t _num_byte) { + uint8_t tmp; + for (size_t i = 0; i < _num_byte; i++) { + tmp = PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16_mul(a[i] & 0xF, gf16_b); + tmp |= (uint8_t) (PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16_mul(a[i] >> 4, gf16_b) << 4); + a[i] = tmp; + } +} + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_madd(uint8_t *accu_c, const uint8_t *a, uint8_t gf16_b, size_t _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + accu_c[i] ^= PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16_mul(a[i] & 0xF, gf16_b); + accu_c[i] ^= (uint8_t) (PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16_mul(a[i] >> 4, gf16_b) << 4); + } +} + +uint8_t PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_dot(const uint8_t *a, const uint8_t *b, size_t _num_byte) { + uint8_t r = 0; + for (size_t i = 0; i < _num_byte; i++) { + r ^= PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16_mul(a[i], b[i]); + } + return r; +} + diff --git a/src/sig/rainbow/pqclean_rainbowIa-classic_clean/blas.h b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/blas.h new file mode 100644 index 0000000000..11970b648d --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/blas.h @@ -0,0 +1,20 @@ +#ifndef _BLAS_H_ +#define _BLAS_H_ +/// @file blas.h +/// @brief Functions for implementing basic linear algebra functions. +/// + +#include "rainbow_config.h" +#include +#include + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_predicated_add(uint8_t *accu_b, uint8_t predicate, const uint8_t *a, size_t _num_byte); +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_add(uint8_t *accu_b, const uint8_t *a, size_t _num_byte); + + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_madd(uint8_t *accu_c, const uint8_t *a, uint8_t gf16_b, size_t _num_byte); +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_mul_scalar(uint8_t *a, uint8_t gf16_b, size_t _num_byte); +uint8_t PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_dot(const uint8_t *a, const uint8_t *b, size_t _num_byte); + + +#endif // _BLAS_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-classic_clean/blas_comm.c b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/blas_comm.c new file mode 100644 index 0000000000..b2193b63c6 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/blas_comm.c @@ -0,0 +1,152 @@ +/// @file blas_comm.c +/// @brief The standard implementations for blas_comm.h +/// + +#include "blas_comm.h" +#include "blas.h" +#include "gf.h" +#include "rainbow_config.h" + +#include +#include + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_set_zero(uint8_t *b, unsigned int _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + b[i] = 0; + } +} + +/// @brief get an element from GF(16) vector . +/// +/// @param[in] a - the input vector a. +/// @param[in] i - the index in the vector a. +/// @return the value of the element. +/// +uint8_t PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_get_ele(const uint8_t *a, unsigned int i) { + uint8_t r = a[i >> 1]; + uint8_t r0 = r & 0xf; + uint8_t r1 = r >> 4; + uint8_t m = (uint8_t)(-((int8_t)i & 1)); + return (uint8_t)((r1 & m) | ((~m) & r0)); +} + +/// @brief set an element for a GF(16) vector . +/// +/// @param[in,out] a - the vector a. +/// @param[in] i - the index in the vector a. +/// @param[in] v - the value for the i-th element in vector a. +/// @return the value of the element. +/// +static uint8_t PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_set_ele(uint8_t *a, unsigned int i, uint8_t v) { + uint8_t m = (uint8_t)(0xf ^ (-((int8_t)i & 1))); /// 1--> 0xf0 , 0--> 0x0f + uint8_t ai_remaining = (uint8_t)(a[i >> 1] & (~m)); /// erase + a[i >> 1] = (uint8_t)(ai_remaining | (m & (v << 4)) | (m & v & 0xf)); /// set + return v; +} + +static void gf16mat_prod_ref(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b) { + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_set_zero(c, n_A_vec_byte); + for (unsigned int i = 0; i < n_A_width; i++) { + uint8_t bb = PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_get_ele(b, i); + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_madd(c, matA, bb, n_A_vec_byte); + matA += n_A_vec_byte; + } +} + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16mat_mul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int len_vec) { + unsigned int n_vec_byte = (len_vec + 1) / 2; + for (unsigned int k = 0; k < len_vec; k++) { + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_set_zero(c, n_vec_byte); + const uint8_t *bk = b + n_vec_byte * k; + for (unsigned int i = 0; i < len_vec; i++) { + uint8_t bb = PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_get_ele(bk, i); + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_madd(c, a + n_vec_byte * i, bb, n_vec_byte); + } + c += n_vec_byte; + } +} + +static unsigned int gf16mat_gauss_elim_ref(uint8_t *mat, unsigned int h, unsigned int w) { + unsigned int n_w_byte = (w + 1) / 2; + unsigned int r8 = 1; + for (unsigned int i = 0; i < h; i++) { + unsigned int offset_byte = i >> 1; + uint8_t *ai = mat + n_w_byte * i; + for (unsigned int j = i + 1; j < h; j++) { + uint8_t *aj = mat + n_w_byte * j; + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_predicated_add(ai + offset_byte, !PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16_is_nonzero(PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_get_ele(ai, i)), aj + offset_byte, n_w_byte - offset_byte); + } + uint8_t pivot = PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_get_ele(ai, i); + r8 &= PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16_is_nonzero(pivot); + pivot = PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16_inv(pivot); + offset_byte = (i + 1) >> 1; + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_mul_scalar(ai + offset_byte, pivot, n_w_byte - offset_byte); + for (unsigned int j = 0; j < h; j++) { + if (i == j) { + continue; + } + uint8_t *aj = mat + n_w_byte * j; + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_madd(aj + offset_byte, ai + offset_byte, PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_get_ele(aj, i), n_w_byte - offset_byte); + } + } + return r8; +} + +static unsigned int gf16mat_solve_linear_eq_ref(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n) { + uint8_t mat[64 * 33]; + unsigned int n_byte = (n + 1) >> 1; + for (unsigned int i = 0; i < n; i++) { + memcpy(mat + i * (n_byte + 1), inp_mat + i * n_byte, n_byte); + mat[i * (n_byte + 1) + n_byte] = PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_get_ele(c_terms, i); + } + unsigned int r8 = PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16mat_gauss_elim(mat, n, n + 2); + for (unsigned int i = 0; i < n; i++) { + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_set_ele(sol, i, mat[i * (n_byte + 1) + n_byte]); + } + return r8; +} + +static inline void gf16mat_submat(uint8_t *mat2, unsigned int w2, unsigned int st, const uint8_t *mat, unsigned int w, unsigned int h) { + unsigned int n_byte_w1 = (w + 1) / 2; + unsigned int n_byte_w2 = (w2 + 1) / 2; + unsigned int st_2 = st / 2; + for (unsigned int i = 0; i < h; i++) { + for (unsigned int j = 0; j < n_byte_w2; j++) { + mat2[i * n_byte_w2 + j] = mat[i * n_byte_w1 + st_2 + j]; + } + } +} + +unsigned int PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16mat_inv(uint8_t *inv_a, const uint8_t *a, unsigned int H, uint8_t *buffer) { + unsigned int n_w_byte = (H + 1) / 2; + + uint8_t *aa = buffer; + for (unsigned int i = 0; i < H; i++) { + uint8_t *ai = aa + i * 2 * n_w_byte; + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_set_zero(ai, 2 * n_w_byte); + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_add(ai, a + i * n_w_byte, n_w_byte); + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_set_ele(ai + n_w_byte, i, 1); + } + unsigned int r8 = PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16mat_gauss_elim(aa, H, 2 * H); + gf16mat_submat(inv_a, H, H, aa, 2 * H, H); + return r8; +} + +// choosing the implementations depends on the macros _BLAS_AVX2_ and _BLAS_SSE + +#define gf16mat_prod_impl gf16mat_prod_ref +#define gf16mat_gauss_elim_impl gf16mat_gauss_elim_ref +#define gf16mat_solve_linear_eq_impl gf16mat_solve_linear_eq_ref + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16mat_prod(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b) { + gf16mat_prod_impl(c, matA, n_A_vec_byte, n_A_width, b); +} + +unsigned int PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16mat_gauss_elim(uint8_t *mat, unsigned int h, unsigned int w) { + return gf16mat_gauss_elim_impl(mat, h, w); +} + +unsigned int PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16mat_solve_linear_eq(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n) { + return gf16mat_solve_linear_eq_impl(sol, inp_mat, c_terms, n); +} + diff --git a/src/sig/rainbow/pqclean_rainbowIa-classic_clean/blas_comm.h b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/blas_comm.h new file mode 100644 index 0000000000..9cbe8ff1e8 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/blas_comm.h @@ -0,0 +1,74 @@ +#ifndef _BLAS_COMM_H_ +#define _BLAS_COMM_H_ +/// @file blas_comm.h +/// @brief Common functions for linear algebra. +/// + +#include "rainbow_config.h" +#include + +/// @brief set a vector to 0. +/// +/// @param[in,out] b - the vector b. +/// @param[in] _num_byte - number of bytes for the vector b. +/// +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_set_zero(uint8_t *b, unsigned int _num_byte); + +/// @brief get an element from GF(16) vector . +/// +/// @param[in] a - the input vector a. +/// @param[in] i - the index in the vector a. +/// @return the value of the element. +/// +uint8_t PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_get_ele(const uint8_t *a, unsigned int i); + +/// @brief matrix-matrix multiplication: c = a * b , in GF(16) +/// +/// @param[out] c - the output matrix c +/// @param[in] c - a matrix a. +/// @param[in] b - a matrix b. +/// @param[in] len_vec - the length of column vectors. +/// +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16mat_mul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int len_vec); + +/// @brief Gauss elimination for a matrix, in GF(16) +/// +/// @param[in,out] mat - the matrix. +/// @param[in] h - the height of the matrix. +/// @param[in] w - the width of the matrix. +/// @return 1(true) if success. 0(false) if the matrix is singular. +/// +unsigned int PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16mat_gauss_elim(uint8_t *mat, unsigned int h, unsigned int w); + +/// @brief Solving linear equations, in GF(16) +/// +/// @param[out] sol - the solutions. +/// @param[in] inp_mat - the matrix parts of input equations. +/// @param[in] c_terms - the constant terms of the input equations. +/// @param[in] n - the number of equations. +/// @return 1(true) if success. 0(false) if the matrix is singular. +/// +unsigned int PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16mat_solve_linear_eq(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n); + +/// @brief Computing the inverse matrix, in GF(16) +/// +/// @param[out] inv_a - the output of matrix a. +/// @param[in] a - a matrix a. +/// @param[in] H - height of matrix a, i.e., matrix a is an HxH matrix. +/// @param[in] buffer - The buffer for computations. it has to be as large as 2 input matrixes. +/// @return 1(true) if success. 0(false) if the matrix is singular. +/// +unsigned int PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16mat_inv(uint8_t *inv_a, const uint8_t *a, unsigned int H, uint8_t *buffer); + +/// @brief matrix-vector multiplication: c = matA * b , in GF(16) +/// +/// @param[out] c - the output vector c +/// @param[in] matA - a column-major matrix A. +/// @param[in] n_A_vec_byte - the size of column vectors in bytes. +/// @param[in] n_A_width - the width of matrix A. +/// @param[in] b - the vector b. +/// +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16mat_prod(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b); + + +#endif // _BLAS_COMM_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-classic_clean/gf.c b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/gf.c new file mode 100644 index 0000000000..ec080f98cc --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/gf.c @@ -0,0 +1,54 @@ +#include "gf.h" + +//// gf4 := gf2[x]/x^2+x+1 +static inline uint8_t gf4_mul_2(uint8_t a) { + uint8_t r = (uint8_t)(a << 1); + r ^= (uint8_t)((a >> 1) * 7); + return r; +} + +static inline uint8_t gf4_mul(uint8_t a, uint8_t b) { + uint8_t r = (uint8_t)(a * (b & 1)); + return r ^ (uint8_t)(gf4_mul_2(a) * (b >> 1)); +} + +static inline uint8_t gf4_squ(uint8_t a) { + return a ^ (a >> 1); +} + +//// gf16 := gf4[y]/y^2+y+x +uint8_t PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16_mul(uint8_t a, uint8_t b) { + uint8_t a0 = a & 3; + uint8_t a1 = (a >> 2); + uint8_t b0 = b & 3; + uint8_t b1 = (b >> 2); + uint8_t a0b0 = gf4_mul(a0, b0); + uint8_t a1b1 = gf4_mul(a1, b1); + uint8_t a0b1_a1b0 = gf4_mul(a0 ^ a1, b0 ^ b1) ^ a0b0 ^ a1b1; + uint8_t a1b1_x2 = gf4_mul_2(a1b1); + return (uint8_t)((a0b1_a1b0 ^ a1b1) << 2 ^ a0b0 ^ a1b1_x2); +} + +static inline uint8_t gf16_squ(uint8_t a) { + uint8_t a0 = a & 3; + uint8_t a1 = (a >> 2); + a1 = gf4_squ(a1); + uint8_t a1squ_x2 = gf4_mul_2(a1); + return (uint8_t)((a1 << 2) ^ a1squ_x2 ^ gf4_squ(a0)); +} + +uint8_t PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16_is_nonzero(uint8_t a) { + unsigned int a4 = a & 0xf; + unsigned int r = ((unsigned int)0) - a4; + r >>= 4; + return r & 1; +} + +uint8_t PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16_inv(uint8_t a) { + uint8_t a2 = gf16_squ(a); + uint8_t a4 = gf16_squ(a2); + uint8_t a8 = gf16_squ(a4); + uint8_t a6 = PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16_mul(a4, a2); + return PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16_mul(a8, a6); +} + diff --git a/src/sig/rainbow/pqclean_rainbowIa-classic_clean/gf.h b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/gf.h new file mode 100644 index 0000000000..f9c98a8e52 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/gf.h @@ -0,0 +1,18 @@ +#ifndef _GF16_H_ +#define _GF16_H_ + +#include "rainbow_config.h" +#include + +/// @file gf16.h +/// @brief Library for arithmetics in GF(16) and GF(256) +/// + +uint8_t PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16_mul(uint8_t a, uint8_t b); + + +uint8_t PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16_is_nonzero(uint8_t a); +uint8_t PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16_inv(uint8_t a); + + +#endif // _GF16_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-classic_clean/parallel_matrix_op.c b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/parallel_matrix_op.c new file mode 100644 index 0000000000..fc8c720749 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/parallel_matrix_op.c @@ -0,0 +1,182 @@ +/// @file parallel_matrix_op.c +/// @brief the standard implementations for functions in parallel_matrix_op.h +/// +/// the standard implementations for functions in parallel_matrix_op.h +/// + +#include "parallel_matrix_op.h" +#include "blas.h" +#include "blas_comm.h" + +/// +/// @brief Calculate the corresponding index in an array for an upper-triangle(UT) matrix. +/// +/// @param[in] i_row - the i-th row in an upper-triangle matrix. +/// @param[in] j_col - the j-th column in an upper-triangle matrix. +/// @param[in] dim - the dimension of the upper-triangle matrix, i.e., an dim x dim matrix. +/// @return the corresponding index in an array storage. +/// +unsigned int PQCLEAN_RAINBOWIACLASSIC_CLEAN_idx_of_trimat(unsigned int i_row, unsigned int j_col, unsigned int dim) { + return (dim + dim - i_row + 1) * i_row / 2 + j_col - i_row; +} + +/// +/// @brief Calculate the corresponding index in an array for an upper-triangle or lower-triangle matrix. +/// +/// @param[in] i_row - the i-th row in a triangle matrix. +/// @param[in] j_col - the j-th column in a triangle matrix. +/// @param[in] dim - the dimension of the triangle matrix, i.e., an dim x dim matrix. +/// @return the corresponding index in an array storage. +/// +static inline unsigned int idx_of_2trimat(unsigned int i_row, unsigned int j_col, unsigned int n_var) { + if (i_row > j_col) { + return PQCLEAN_RAINBOWIACLASSIC_CLEAN_idx_of_trimat(j_col, i_row, n_var); + } + return PQCLEAN_RAINBOWIACLASSIC_CLEAN_idx_of_trimat(i_row, j_col, n_var); +} + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_UpperTrianglize(unsigned char *btriC, const unsigned char *bA, unsigned int Awidth, unsigned int size_batch) { + unsigned char *runningC = btriC; + unsigned int Aheight = Awidth; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < i; j++) { + unsigned int idx = PQCLEAN_RAINBOWIACLASSIC_CLEAN_idx_of_trimat(j, i, Aheight); + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_add(btriC + idx * size_batch, bA + size_batch * (i * Awidth + j), size_batch); + } + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_add(runningC, bA + size_batch * (i * Awidth + i), size_batch * (Aheight - i)); + runningC += size_batch * (Aheight - i); + } +} + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_trimat_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Awidth = Bheight; + unsigned int Aheight = Awidth; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + if (k < i) { + continue; + } + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_madd(bC, &btriA[(k - i) * size_batch], PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + btriA += (Aheight - i) * size_batch; + } +} + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_trimatTr_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Aheight = Bheight; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + if (i < k) { + continue; + } + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_madd(bC, &btriA[size_batch * (PQCLEAN_RAINBOWIACLASSIC_CLEAN_idx_of_trimat(k, i, Aheight))], PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_2trimat_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Aheight = Bheight; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + if (i == k) { + continue; + } + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_madd(bC, &btriA[size_batch * (idx_of_2trimat(i, k, Aheight))], PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_matTr_madd_gf16(unsigned char *bC, const unsigned char *A_to_tr, unsigned int Aheight, unsigned int size_Acolvec, unsigned int Awidth, + const unsigned char *bB, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Atr_height = Awidth; + unsigned int Atr_width = Aheight; + for (unsigned int i = 0; i < Atr_height; i++) { + for (unsigned int j = 0; j < Atr_width; j++) { + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_madd(bC, &bB[j * Bwidth * size_batch], PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_get_ele(&A_to_tr[size_Acolvec * i], j), size_batch * Bwidth); + } + bC += size_batch * Bwidth; + } +} + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_bmatTr_madd_gf16(unsigned char *bC, const unsigned char *bA_to_tr, unsigned int Awidth_before_tr, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + const unsigned char *bA = bA_to_tr; + unsigned int Aheight = Awidth_before_tr; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_madd(bC, &bA[size_batch * (i + k * Aheight)], PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_mat_madd_gf16(unsigned char *bC, const unsigned char *bA, unsigned int Aheight, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Awidth = Bheight; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_madd(bC, &bA[k * size_batch], PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + bA += (Awidth) * size_batch; + } +} + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_quad_recmat_eval_gf16(unsigned char *z, const unsigned char *y, unsigned int dim_y, const unsigned char *mat, + const unsigned char *x, unsigned int dim_x, unsigned int size_batch) { + unsigned char tmp[128]; + + unsigned char _x[128]; + for (unsigned int i = 0; i < dim_x; i++) { + _x[i] = PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_get_ele(x, i); + } + unsigned char _y[128]; + for (unsigned int i = 0; i < dim_y; i++) { + _y[i] = PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_get_ele(y, i); + } + + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_set_zero(z, size_batch); + for (unsigned int i = 0; i < dim_y; i++) { + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_set_zero(tmp, size_batch); + for (unsigned int j = 0; j < dim_x; j++) { + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_madd(tmp, mat, _x[j], size_batch); + mat += size_batch; + } + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_madd(z, tmp, _y[i], size_batch); + } +} + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_quad_trimat_eval_gf16(unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned int dim, unsigned int size_batch) { + unsigned char tmp[256]; + + unsigned char _x[256]; + for (unsigned int i = 0; i < dim; i++) { + _x[i] = PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_get_ele(x, i); + } + + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_set_zero(y, size_batch); + for (unsigned int i = 0; i < dim; i++) { + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_set_zero(tmp, size_batch); + for (unsigned int j = i; j < dim; j++) { + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_madd(tmp, trimat, _x[j], size_batch); + trimat += size_batch; + } + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_madd(y, tmp, _x[i], size_batch); + } +} diff --git a/src/sig/rainbow/pqclean_rainbowIa-classic_clean/parallel_matrix_op.h b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/parallel_matrix_op.h new file mode 100644 index 0000000000..b9f8b8c5af --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/parallel_matrix_op.h @@ -0,0 +1,260 @@ +#ifndef _P_MATRIX_OP_H_ +#define _P_MATRIX_OP_H_ +/// @file parallel_matrix_op.h +/// @brief Librarys for operations of batched matrixes. +/// +/// + +//////////////// Section: triangle matrix <-> rectangle matrix /////////////////////////////////// + +/// +/// @brief Calculate the corresponding index in an array for an upper-triangle(UT) matrix. +/// +/// @param[in] i_row - the i-th row in an upper-triangle matrix. +/// @param[in] j_col - the j-th column in an upper-triangle matrix. +/// @param[in] dim - the dimension of the upper-triangle matrix, i.e., an dim x dim matrix. +/// @return the corresponding index in an array storage. +/// +unsigned int PQCLEAN_RAINBOWIACLASSIC_CLEAN_idx_of_trimat(unsigned int i_row, unsigned int j_col, unsigned int dim); + +/// +/// @brief Upper trianglize a rectangle matrix to the corresponding upper-trangle matrix. +/// +/// @param[out] btriC - the batched upper-trianglized matrix C. +/// @param[in] bA - a batched retangle matrix A. +/// @param[in] bwidth - the width of the batched matrix A, i.e., A is a Awidth x Awidth matrix. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_UpperTrianglize(unsigned char *btriC, const unsigned char *bA, unsigned int Awidth, unsigned int size_batch); + +//////////////////// Section: matrix multiplications /////////////////////////////// + +/// +/// @brief bC += btriA * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_trimat_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += btriA * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += btriA^Tr * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. A will be transposed while multiplying. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_trimatTr_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += btriA^Tr * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A, which will be transposed while multiplying. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_trimatTr_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += (btriA + btriA^Tr) *B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. The operand for multiplication is (btriA + btriA^Tr). +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_2trimat_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += (btriA + btriA^Tr) *B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. The operand for multiplication is (btriA + btriA^Tr). +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_2trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += A^Tr * bB , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] A_to_tr - a column-major matrix A. The operand for multiplication is A^Tr. +/// @param[in] Aheight - the height of A. +/// @param[in] size_Acolvec - the size of a column vector in A. +/// @param[in] Awidth - the width of A. +/// @param[in] bB - a batched matrix B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_matTr_madd_gf16(unsigned char *bC, + const unsigned char *A_to_tr, unsigned int Aheight, unsigned int size_Acolvec, unsigned int Awidth, + const unsigned char *bB, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += A^Tr * bB , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] A_to_tr - a column-major matrix A. The operand for multiplication is A^Tr. +/// @param[in] Aheight - the height of A. +/// @param[in] size_Acolvec - the size of a column vector in A. +/// @param[in] Awidth - the width of A. +/// @param[in] bB - a batched matrix B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_matTr_madd_gf256(unsigned char *bC, + const unsigned char *A_to_tr, unsigned int Aheight, unsigned int size_Acolvec, unsigned int Awidth, + const unsigned char *bB, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA^Tr * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA_to_tr - a batched matrix A. The operand for multiplication is (bA^Tr). +/// @param[in] Awidth_befor_tr - the width of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_bmatTr_madd_gf16(unsigned char *bC, const unsigned char *bA_to_tr, unsigned int Awidth_before_tr, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA^Tr * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA_to_tr - a batched matrix A. The operand for multiplication is (bA^Tr). +/// @param[in] Awidth_befor_tr - the width of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_bmatTr_madd_gf256(unsigned char *bC, const unsigned char *bA_to_tr, unsigned int Awidth_before_tr, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA - a batched matrix A. +/// @param[in] Aheigh - the height of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_mat_madd_gf16(unsigned char *bC, const unsigned char *bA, unsigned int Aheight, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA - a batched matrix A. +/// @param[in] Aheigh - the height of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_mat_madd_gf256(unsigned char *bC, const unsigned char *bA, unsigned int Aheight, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +//////////////////// Section: "quadratric" matrix evaluation /////////////////////////////// + +/// +/// @brief y = x^Tr * trimat * x , in GF(16) +/// +/// @param[out] y - the returned batched element y. +/// @param[in] trimat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim - the dimension of matrix trimat (and x). +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_quad_trimat_eval_gf16(unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned int dim, unsigned int size_batch); + +/// +/// @brief y = x^Tr * trimat * x , in GF(256) +/// +/// @param[out] y - the returned batched element y. +/// @param[in] trimat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim - the dimension of matrix trimat (and x). +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_quad_trimat_eval_gf256(unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned int dim, unsigned int size_batch); + +/// +/// @brief z = y^Tr * mat * x , in GF(16) +/// +/// @param[out] z - the returned batched element z. +/// @param[in] y - an input vector y. +/// @param[in] dim_y - the length of y. +/// @param[in] mat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim_x - the length of x. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_quad_recmat_eval_gf16(unsigned char *z, const unsigned char *y, unsigned int dim_y, + const unsigned char *mat, const unsigned char *x, unsigned int dim_x, unsigned int size_batch); + +/// +/// @brief z = y^Tr * mat * x , in GF(256) +/// +/// @param[out] z - the returned batched element z. +/// @param[in] y - an input vector y. +/// @param[in] dim_y - the length of y. +/// @param[in] mat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim_x - the length of x. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_quad_recmat_eval_gf256(unsigned char *z, const unsigned char *y, unsigned int dim_y, + const unsigned char *mat, const unsigned char *x, unsigned int dim_x, unsigned int size_batch); + +#endif // _P_MATRIX_OP_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-classic_clean/rainbow.c b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/rainbow.c new file mode 100644 index 0000000000..3ffd0c1cde --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/rainbow.c @@ -0,0 +1,168 @@ +/// @file rainbow.c +/// @brief The standard implementations for functions in rainbow.h +/// + +#include "blas.h" +#include "parallel_matrix_op.h" +#include "rainbow.h" +#include "rainbow_blas.h" +#include "rainbow_config.h" +#include "rainbow_keypair.h" +#include "utils_hash.h" +#include "utils_prng.h" +#include +#include +#include + +#define MAX_ATTEMPT_FRMAT 128 + +int PQCLEAN_RAINBOWIACLASSIC_CLEAN_rainbow_sign(uint8_t *signature, const sk_t *sk, const uint8_t *_digest) { + uint8_t mat_l1[_O1 * _O1_BYTE]; + uint8_t mat_l2[_O2 * _O2_BYTE]; + uint8_t mat_buffer[2 * _MAX_O * _MAX_O_BYTE]; + + // setup PRNG + prng_t prng_sign; + uint8_t prng_preseed[LEN_SKSEED + _HASH_LEN]; + memcpy(prng_preseed, sk->sk_seed, LEN_SKSEED); + memcpy(prng_preseed + LEN_SKSEED, _digest, _HASH_LEN); // prng_preseed = sk_seed || digest + uint8_t prng_seed[_HASH_LEN]; + PQCLEAN_RAINBOWIACLASSIC_CLEAN_hash_msg(prng_seed, _HASH_LEN, prng_preseed, _HASH_LEN + LEN_SKSEED); + PQCLEAN_RAINBOWIACLASSIC_CLEAN_prng_set(&prng_sign, prng_seed, _HASH_LEN); // seed = H( sk_seed || digest ) + for (unsigned int i = 0; i < LEN_SKSEED + _HASH_LEN; i++) { + prng_preseed[i] ^= prng_preseed[i]; // clean + } + for (unsigned int i = 0; i < _HASH_LEN; i++) { + prng_seed[i] ^= prng_seed[i]; // clean + } + + // roll vinegars. + uint8_t vinegar[_V1_BYTE]; + unsigned int n_attempt = 0; + unsigned int l1_succ = 0; + while (!l1_succ) { + if (MAX_ATTEMPT_FRMAT <= n_attempt) { + break; + } + PQCLEAN_RAINBOWIACLASSIC_CLEAN_prng_gen(&prng_sign, vinegar, _V1_BYTE); // generating vinegars + gfmat_prod(mat_l1, sk->l1_F2, _O1 * _O1_BYTE, _V1, vinegar); // generating the linear equations for layer 1 + l1_succ = gfmat_inv(mat_l1, mat_l1, _O1, mat_buffer); // check if the linear equation solvable + n_attempt++; + } + + // Given the vinegars, pre-compute variables needed for layer 2 + uint8_t r_l1_F1[_O1_BYTE] = {0}; + uint8_t r_l2_F1[_O2_BYTE] = {0}; + batch_quad_trimat_eval(r_l1_F1, sk->l1_F1, vinegar, _V1, _O1_BYTE); + batch_quad_trimat_eval(r_l2_F1, sk->l2_F1, vinegar, _V1, _O2_BYTE); + uint8_t mat_l2_F3[_O2 * _O2_BYTE]; + uint8_t mat_l2_F2[_O1 * _O2_BYTE]; + gfmat_prod(mat_l2_F3, sk->l2_F3, _O2 * _O2_BYTE, _V1, vinegar); + gfmat_prod(mat_l2_F2, sk->l2_F2, _O1 * _O2_BYTE, _V1, vinegar); + + // Some local variables. + uint8_t _z[_PUB_M_BYTE]; + uint8_t y[_PUB_M_BYTE]; + uint8_t *x_v1 = vinegar; + uint8_t x_o1[_O1_BYTE]; + uint8_t x_o2[_O1_BYTE]; + + uint8_t digest_salt[_HASH_LEN + _SALT_BYTE]; + memcpy(digest_salt, _digest, _HASH_LEN); + uint8_t *salt = digest_salt + _HASH_LEN; + + uint8_t temp_o[_MAX_O_BYTE + 32] = {0}; + unsigned int succ = 0; + while (!succ) { + if (MAX_ATTEMPT_FRMAT <= n_attempt) { + break; + } + // The computation: H(digest||salt) --> z --S--> y --C-map--> x --T--> w + + PQCLEAN_RAINBOWIACLASSIC_CLEAN_prng_gen(&prng_sign, salt, _SALT_BYTE); // roll the salt + PQCLEAN_RAINBOWIACLASSIC_CLEAN_hash_msg(_z, _PUB_M_BYTE, digest_salt, _HASH_LEN + _SALT_BYTE); // H(digest||salt) + + // y = S^-1 * z + memcpy(y, _z, _PUB_M_BYTE); // identity part of S + gfmat_prod(temp_o, sk->s1, _O1_BYTE, _O2, _z + _O1_BYTE); + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_add(y, temp_o, _O1_BYTE); + + // Central Map: + // layer 1: calculate x_o1 + memcpy(temp_o, r_l1_F1, _O1_BYTE); + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_add(temp_o, y, _O1_BYTE); + gfmat_prod(x_o1, mat_l1, _O1_BYTE, _O1, temp_o); + + // layer 2: calculate x_o2 + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_set_zero(temp_o, _O2_BYTE); + gfmat_prod(temp_o, mat_l2_F2, _O2_BYTE, _O1, x_o1); // F2 + batch_quad_trimat_eval(mat_l2, sk->l2_F5, x_o1, _O1, _O2_BYTE); // F5 + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_add(temp_o, mat_l2, _O2_BYTE); + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_add(temp_o, r_l2_F1, _O2_BYTE); // F1 + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_add(temp_o, y + _O1_BYTE, _O2_BYTE); + + // generate the linear equations of the 2nd layer + gfmat_prod(mat_l2, sk->l2_F6, _O2 * _O2_BYTE, _O1, x_o1); // F6 + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_add(mat_l2, mat_l2_F3, _O2 * _O2_BYTE); // F3 + succ = gfmat_inv(mat_l2, mat_l2, _O2, mat_buffer); + gfmat_prod(x_o2, mat_l2, _O2_BYTE, _O2, temp_o); // solve l2 eqs + + n_attempt++; + }; + // w = T^-1 * y + uint8_t w[_PUB_N_BYTE]; + // identity part of T. + memcpy(w, x_v1, _V1_BYTE); + memcpy(w + _V1_BYTE, x_o1, _O1_BYTE); + memcpy(w + _V2_BYTE, x_o2, _O2_BYTE); + // Computing the t1 part. + gfmat_prod(y, sk->t1, _V1_BYTE, _O1, x_o1); + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_add(w, y, _V1_BYTE); + // Computing the t4 part. + gfmat_prod(y, sk->t4, _V1_BYTE, _O2, x_o2); + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_add(w, y, _V1_BYTE); + // Computing the t3 part. + gfmat_prod(y, sk->t3, _O1_BYTE, _O2, x_o2); + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_add(w + _V1_BYTE, y, _O1_BYTE); + + memset(signature, 0, _SIGNATURE_BYTE); // set the output 0 + // clean + memset(&prng_sign, 0, sizeof(prng_t)); + memset(vinegar, 0, _V1_BYTE); + memset(r_l1_F1, 0, _O1_BYTE); + memset(r_l2_F1, 0, _O2_BYTE); + memset(_z, 0, _PUB_M_BYTE); + memset(y, 0, _PUB_M_BYTE); + memset(x_o1, 0, _O1_BYTE); + memset(x_o2, 0, _O2_BYTE); + memset(temp_o, 0, sizeof(temp_o)); + + // return: copy w and salt to the signature. + if (MAX_ATTEMPT_FRMAT <= n_attempt) { + return -1; + } + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_add(signature, w, _PUB_N_BYTE); + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_add(signature + _PUB_N_BYTE, salt, _SALT_BYTE); + return 0; +} + +int PQCLEAN_RAINBOWIACLASSIC_CLEAN_rainbow_verify(const uint8_t *digest, const uint8_t *signature, const pk_t *pk) { + unsigned char digest_ck[_PUB_M_BYTE]; + // public_map( digest_ck , pk , signature ); Evaluating the quadratic public polynomials. + batch_quad_trimat_eval(digest_ck, pk->pk, signature, _PUB_N, _PUB_M_BYTE); + + unsigned char correct[_PUB_M_BYTE]; + unsigned char digest_salt[_HASH_LEN + _SALT_BYTE]; + memcpy(digest_salt, digest, _HASH_LEN); + memcpy(digest_salt + _HASH_LEN, signature + _PUB_N_BYTE, _SALT_BYTE); + PQCLEAN_RAINBOWIACLASSIC_CLEAN_hash_msg(correct, _PUB_M_BYTE, digest_salt, _HASH_LEN + _SALT_BYTE); // H( digest || salt ) + + // check consistancy. + unsigned char cc = 0; + for (unsigned int i = 0; i < _PUB_M_BYTE; i++) { + cc |= (digest_ck[i] ^ correct[i]); + } + return (0 == cc) ? 0 : -1; +} + + diff --git a/src/sig/rainbow/pqclean_rainbowIa-classic_clean/rainbow.h b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/rainbow.h new file mode 100644 index 0000000000..7cf8e077e6 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/rainbow.h @@ -0,0 +1,33 @@ +#ifndef _RAINBOW_H_ +#define _RAINBOW_H_ +/// @file rainbow.h +/// @brief APIs for rainbow. +/// + +#include "rainbow_config.h" +#include "rainbow_keypair.h" + +#include + +/// +/// @brief Signing function for classical secret key. +/// +/// @param[out] signature - the signature. +/// @param[in] sk - the secret key. +/// @param[in] digest - the digest. +/// +int PQCLEAN_RAINBOWIACLASSIC_CLEAN_rainbow_sign(uint8_t *signature, const sk_t *sk, const uint8_t *digest); + +/// +/// @brief Verifying function. +/// +/// @param[in] digest - the digest. +/// @param[in] signature - the signature. +/// @param[in] pk - the public key. +/// @return 0 for successful verified. -1 for failed verification. +/// +int PQCLEAN_RAINBOWIACLASSIC_CLEAN_rainbow_verify(const uint8_t *digest, const uint8_t *signature, const pk_t *pk); + + + +#endif // _RAINBOW_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-classic_clean/rainbow_blas.h b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/rainbow_blas.h new file mode 100644 index 0000000000..20af8f1658 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/rainbow_blas.h @@ -0,0 +1,32 @@ +#ifndef _RAINBOW_BLAS_H_ +#define _RAINBOW_BLAS_H_ +/// @file rainbow_blas.h +/// @brief Defining the functions used in rainbow.c acconding to the definitions in rainbow_config.h +/// +/// Defining the functions used in rainbow.c acconding to the definitions in rainbow_config.h + +#include "blas.h" +#include "blas_comm.h" +#include "parallel_matrix_op.h" +#include "rainbow_config.h" + + +#define gfv_get_ele PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_get_ele +#define gfv_mul_scalar PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_mul_scalar +#define gfv_madd PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16v_madd + +#define gfmat_prod PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16mat_prod +#define gfmat_inv PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16mat_inv + +#define batch_trimat_madd PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_trimat_madd_gf16 +#define batch_trimatTr_madd PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_trimatTr_madd_gf16 +#define batch_2trimat_madd PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_2trimat_madd_gf16 +#define batch_matTr_madd PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_matTr_madd_gf16 +#define batch_bmatTr_madd PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_bmatTr_madd_gf16 +#define batch_mat_madd PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_mat_madd_gf16 + +#define batch_quad_trimat_eval PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_quad_trimat_eval_gf16 +#define batch_quad_recmat_eval PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_quad_recmat_eval_gf16 + + +#endif // _RAINBOW_BLAS_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-classic_clean/rainbow_config.h b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/rainbow_config.h new file mode 100644 index 0000000000..3607536831 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/rainbow_config.h @@ -0,0 +1,49 @@ +#ifndef _H_RAINBOW_CONFIG_H_ +#define _H_RAINBOW_CONFIG_H_ + +/// @file rainbow_config.h +/// @brief Defining the parameters of the Rainbow and the corresponding constants. +/// + +#define _USE_GF16 +#define _GFSIZE 16 +#define _V1 32 +#define _O1 32 +#define _O2 32 +#define _MAX_O 32 +#define _HASH_LEN 32 + + +#define _V2 ((_V1) + (_O1)) + +/// size of N, in # of gf elements. +#define _PUB_N (_V1 + _O1 + _O2) + +/// size of M, in # gf elements. +#define _PUB_M (_O1 + _O2) + +/// size of variables, in # bytes. + +// GF16 +#define _V1_BYTE (_V1 / 2) +#define _V2_BYTE (_V2 / 2) +#define _O1_BYTE (_O1 / 2) +#define _O2_BYTE (_O2 / 2) +#define _MAX_O_BYTE (_MAX_O / 2) +#define _PUB_N_BYTE (_PUB_N / 2) +#define _PUB_M_BYTE (_PUB_M / 2) + + +/// length of seed for public key, in # bytes +#define LEN_PKSEED 32 + +/// length of seed for secret key, in # bytes +#define LEN_SKSEED 32 + +/// length of salt for a signature, in # bytes +#define _SALT_BYTE 16 + +/// length of a signature +#define _SIGNATURE_BYTE (_PUB_N_BYTE + _SALT_BYTE) + +#endif // _H_RAINBOW_CONFIG_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-classic_clean/rainbow_keypair.c b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/rainbow_keypair.c new file mode 100644 index 0000000000..c7b395fcd7 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/rainbow_keypair.c @@ -0,0 +1,126 @@ +/// @file rainbow_keypair.c +/// @brief implementations of functions in rainbow_keypair.h +/// + +#include "rainbow_keypair.h" +#include "blas.h" +#include "blas_comm.h" +#include "rainbow_blas.h" +#include "rainbow_keypair_computation.h" +#include "utils_prng.h" +#include +#include +#include + +static void generate_S_T(unsigned char *s_and_t, prng_t *prng0) { + PQCLEAN_RAINBOWIACLASSIC_CLEAN_prng_gen(prng0, s_and_t, _O1_BYTE * _O2); // S1 + s_and_t += _O1_BYTE * _O2; + PQCLEAN_RAINBOWIACLASSIC_CLEAN_prng_gen(prng0, s_and_t, _V1_BYTE * _O1); // T1 + s_and_t += _V1_BYTE * _O1; + PQCLEAN_RAINBOWIACLASSIC_CLEAN_prng_gen(prng0, s_and_t, _V1_BYTE * _O2); // T2 + s_and_t += _V1_BYTE * _O2; + PQCLEAN_RAINBOWIACLASSIC_CLEAN_prng_gen(prng0, s_and_t, _O1_BYTE * _O2); // T3 +} + +static unsigned int generate_l1_F12(unsigned char *sk, prng_t *prng0) { + unsigned int n_byte_generated = 0; + PQCLEAN_RAINBOWIACLASSIC_CLEAN_prng_gen(prng0, sk, _O1_BYTE * N_TRIANGLE_TERMS(_V1)); // l1_F1 + sk += _O1_BYTE * N_TRIANGLE_TERMS(_V1); + n_byte_generated += _O1_BYTE * N_TRIANGLE_TERMS(_V1); + + PQCLEAN_RAINBOWIACLASSIC_CLEAN_prng_gen(prng0, sk, _O1_BYTE * _V1 * _O1); // l1_F2 + n_byte_generated += _O1_BYTE * _V1 * _O1; + return n_byte_generated; +} + +static unsigned int generate_l2_F12356(unsigned char *sk, prng_t *prng0) { + unsigned int n_byte_generated = 0; + + PQCLEAN_RAINBOWIACLASSIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * N_TRIANGLE_TERMS(_V1)); // l2_F1 + sk += _O2_BYTE * N_TRIANGLE_TERMS(_V1); + n_byte_generated += _O2_BYTE * N_TRIANGLE_TERMS(_V1); + + PQCLEAN_RAINBOWIACLASSIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * _V1 * _O1); // l2_F2 + sk += _O2_BYTE * _V1 * _O1; + n_byte_generated += _O2_BYTE * _V1 * _O1; + + PQCLEAN_RAINBOWIACLASSIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * _V1 * _O2); // l2_F3 + sk += _O2_BYTE * _V1 * _O1; + n_byte_generated += _O2_BYTE * _V1 * _O1; + + PQCLEAN_RAINBOWIACLASSIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * N_TRIANGLE_TERMS(_O1)); // l2_F5 + sk += _O2_BYTE * N_TRIANGLE_TERMS(_O1); + n_byte_generated += _O2_BYTE * N_TRIANGLE_TERMS(_O1); + + PQCLEAN_RAINBOWIACLASSIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * _O1 * _O2); // l2_F6 + n_byte_generated += _O2_BYTE * _O1 * _O2; + + return n_byte_generated; +} + +static void generate_B1_B2(unsigned char *sk, prng_t *prng0) { + sk += generate_l1_F12(sk, prng0); + generate_l2_F12356(sk, prng0); +} + +static void calculate_t4(unsigned char *t2_to_t4, const unsigned char *t1, const unsigned char *t3) { + // t4 = T_sk.t1 * T_sk.t3 - T_sk.t2 + unsigned char temp[_V1_BYTE + 32]; + unsigned char *t4 = t2_to_t4; + for (unsigned int i = 0; i < _O2; i++) { /// t3 width + gfmat_prod(temp, t1, _V1_BYTE, _O1, t3); + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_add(t4, temp, _V1_BYTE); + t4 += _V1_BYTE; + t3 += _O1_BYTE; + } +} + +static void obsfucate_l1_polys(unsigned char *l1_polys, const unsigned char *l2_polys, unsigned int n_terms, const unsigned char *s1) { + unsigned char temp[_O1_BYTE + 32]; + while (n_terms--) { + gfmat_prod(temp, s1, _O1_BYTE, _O2, l2_polys); + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_add(l1_polys, temp, _O1_BYTE); + l1_polys += _O1_BYTE; + l2_polys += _O2_BYTE; + } +} + +/////////////////// Classic ////////////////////////////////// + +static void _generate_secretkey(sk_t *sk, const unsigned char *sk_seed) { + memcpy(sk->sk_seed, sk_seed, LEN_SKSEED); + + // set up prng + prng_t prng0; + PQCLEAN_RAINBOWIACLASSIC_CLEAN_prng_set(&prng0, sk_seed, LEN_SKSEED); + + // generating secret key with prng. + generate_S_T(sk->s1, &prng0); + generate_B1_B2(sk->l1_F1, &prng0); + + // clean prng + memset(&prng0, 0, sizeof(prng_t)); +} + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_generate_keypair(pk_t *rpk, sk_t *sk, const unsigned char *sk_seed) { + _generate_secretkey(sk, sk_seed); + + // set up a temporary structure ext_cpk_t for calculating public key. + ext_cpk_t pk; + + PQCLEAN_RAINBOWIACLASSIC_CLEAN_calculate_Q_from_F(&pk, sk, sk); // compute the public key in ext_cpk_t format. + calculate_t4(sk->t4, sk->t1, sk->t3); + + obsfucate_l1_polys(pk.l1_Q1, pk.l2_Q1, N_TRIANGLE_TERMS(_V1), sk->s1); + obsfucate_l1_polys(pk.l1_Q2, pk.l2_Q2, _V1 * _O1, sk->s1); + obsfucate_l1_polys(pk.l1_Q3, pk.l2_Q3, _V1 * _O2, sk->s1); + obsfucate_l1_polys(pk.l1_Q5, pk.l2_Q5, N_TRIANGLE_TERMS(_O1), sk->s1); + obsfucate_l1_polys(pk.l1_Q6, pk.l2_Q6, _O1 * _O2, sk->s1); + obsfucate_l1_polys(pk.l1_Q9, pk.l2_Q9, N_TRIANGLE_TERMS(_O2), sk->s1); + // so far, the pk contains the full pk but in ext_cpk_t format. + + PQCLEAN_RAINBOWIACLASSIC_CLEAN_extcpk_to_pk(rpk, &pk); // convert the public key from ext_cpk_t to pk_t. +} + + + diff --git a/src/sig/rainbow/pqclean_rainbowIa-classic_clean/rainbow_keypair.h b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/rainbow_keypair.h new file mode 100644 index 0000000000..f614f06469 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/rainbow_keypair.h @@ -0,0 +1,61 @@ +#ifndef _RAINBOW_KEYPAIR_H_ +#define _RAINBOW_KEYPAIR_H_ +/// @file rainbow_keypair.h +/// @brief Formats of key pairs and functions for generating key pairs. +/// Formats of key pairs and functions for generating key pairs. +/// + +#include "rainbow_config.h" + +#define N_TRIANGLE_TERMS(n_var) ((n_var) * ((n_var) + 1) / 2) + +/// @brief public key for classic rainbow +/// +/// public key for classic rainbow +/// +typedef struct rainbow_publickey { + unsigned char pk[(_PUB_M_BYTE)*N_TRIANGLE_TERMS(_PUB_N)]; +} pk_t; + +/// @brief secret key for classic rainbow +/// +/// secret key for classic rainbow +/// +typedef struct rainbow_secretkey { + /// + /// seed for generating secret key. + /// Generating S, T, and F for classic rainbow. + /// Generating S and T only for cyclic rainbow. + unsigned char sk_seed[LEN_SKSEED]; + + unsigned char s1[_O1_BYTE * _O2]; ///< part of S map + unsigned char t1[_V1_BYTE * _O1]; ///< part of T map + unsigned char t4[_V1_BYTE * _O2]; ///< part of T map + unsigned char t3[_O1_BYTE * _O2]; ///< part of T map + + unsigned char l1_F1[_O1_BYTE * N_TRIANGLE_TERMS(_V1)]; ///< part of C-map, F1, Layer1 + unsigned char l1_F2[_O1_BYTE * _V1 * _O1]; ///< part of C-map, F2, Layer1 + + unsigned char l2_F1[_O2_BYTE * N_TRIANGLE_TERMS(_V1)]; ///< part of C-map, F1, Layer2 + unsigned char l2_F2[_O2_BYTE * _V1 * _O1]; ///< part of C-map, F2, Layer2 + + unsigned char l2_F3[_O2_BYTE * _V1 * _O2]; ///< part of C-map, F3, Layer2 + unsigned char l2_F5[_O2_BYTE * N_TRIANGLE_TERMS(_O1)]; ///< part of C-map, F5, Layer2 + unsigned char l2_F6[_O2_BYTE * _O1 * _O2]; ///< part of C-map, F6, Layer2 +} sk_t; + + +/// +/// @brief Generate key pairs for classic rainbow. +/// +/// @param[out] pk - the public key. +/// @param[out] sk - the secret key. +/// @param[in] sk_seed - seed for generating the secret key. +/// +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_generate_keypair(pk_t *pk, sk_t *sk, const unsigned char *sk_seed); + + + + + +#endif // _RAINBOW_KEYPAIR_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-classic_clean/rainbow_keypair_computation.c b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/rainbow_keypair_computation.c new file mode 100644 index 0000000000..88ad49bd76 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/rainbow_keypair_computation.c @@ -0,0 +1,189 @@ +/// @file rainbow_keypair_computation.c +/// @brief Implementations for functions in rainbow_keypair_computation.h +/// + +#include "rainbow_keypair_computation.h" +#include "blas.h" +#include "blas_comm.h" +#include "rainbow_blas.h" +#include "rainbow_keypair.h" +#include +#include +#include + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_extcpk_to_pk(pk_t *pk, const ext_cpk_t *cpk) { + const unsigned char *idx_l1 = cpk->l1_Q1; + const unsigned char *idx_l2 = cpk->l2_Q1; + for (unsigned int i = 0; i < _V1; i++) { + for (unsigned int j = i; j < _V1; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIACLASSIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q2; + idx_l2 = cpk->l2_Q2; + for (unsigned int i = 0; i < _V1; i++) { + for (unsigned int j = _V1; j < _V1 + _O1; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIACLASSIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q3; + idx_l2 = cpk->l2_Q3; + for (unsigned int i = 0; i < _V1; i++) { + for (unsigned int j = _V1 + _O1; j < _PUB_N; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIACLASSIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q5; + idx_l2 = cpk->l2_Q5; + for (unsigned int i = _V1; i < _V1 + _O1; i++) { + for (unsigned int j = i; j < _V1 + _O1; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIACLASSIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q6; + idx_l2 = cpk->l2_Q6; + for (unsigned int i = _V1; i < _V1 + _O1; i++) { + for (unsigned int j = _V1 + _O1; j < _PUB_N; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIACLASSIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q9; + idx_l2 = cpk->l2_Q9; + for (unsigned int i = _V1 + _O1; i < _PUB_N; i++) { + for (unsigned int j = i; j < _PUB_N; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIACLASSIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } +} + +static void calculate_Q_from_F_ref(ext_cpk_t *Qs, const sk_t *Fs, const sk_t *Ts) { + /* + Layer 1 + Computing : + Q_pk.l1_F1s[i] = F_sk.l1_F1s[i] + + Q_pk.l1_F2s[i] = (F1* T1 + F2) + F1tr * t1 + Q_pk.l1_F5s[i] = UT( T1tr* (F1 * T1 + F2) ) + */ + const unsigned char *t2 = Ts->t4; + + memcpy(Qs->l1_Q1, Fs->l1_F1, _O1_BYTE * N_TRIANGLE_TERMS(_V1)); + + memcpy(Qs->l1_Q2, Fs->l1_F2, _O1_BYTE * _V1 * _O1); + batch_trimat_madd(Qs->l1_Q2, Fs->l1_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O1_BYTE); // F1*T1 + F2 + + memset(Qs->l1_Q3, 0, _O1_BYTE * _V1 * _O2); + memset(Qs->l1_Q5, 0, _O1_BYTE * N_TRIANGLE_TERMS(_O1)); + memset(Qs->l1_Q6, 0, _O1_BYTE * _O1 * _O2); + memset(Qs->l1_Q9, 0, _O1_BYTE * N_TRIANGLE_TERMS(_O2)); + + // l1_Q5 : _O1_BYTE * _O1 * _O1 + // l1_Q9 : _O1_BYTE * _O2 * _O2 + // l2_Q5 : _O2_BYTE * _V1 * _O1 + // l2_Q9 : _O2_BYTE * _V1 * _O2 + + unsigned char tempQ[_O1_BYTE * _O1 * _O1 + 32]; + + memset(tempQ, 0, _O1_BYTE * _O1 * _O1); // l1_Q5 + batch_matTr_madd(tempQ, Ts->t1, _V1, _V1_BYTE, _O1, Qs->l1_Q2, _O1, _O1_BYTE); // t1_tr*(F1*T1 + F2) + PQCLEAN_RAINBOWIACLASSIC_CLEAN_UpperTrianglize(Qs->l1_Q5, tempQ, _O1, _O1_BYTE); // UT( ... ) // Q5 + + batch_trimatTr_madd(Qs->l1_Q2, Fs->l1_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O1_BYTE); // Q2 + /* + Computing: + F1_T2 = F1 * t2 + F2_T3 = F2 * t3 + F1_F1T_T2 + F2_T3 = F1_T2 + F2_T3 + F1tr * t2 + Q_pk.l1_F3s[i] = F1_F1T_T2 + F2_T3 + Q_pk.l1_F6s[i] = T1tr* ( F1_F1T_T2 + F2_T3 ) + F2tr * t2 + Q_pk.l1_F9s[i] = UT( T2tr* ( F1_T2 + F2_T3 ) ) + */ + batch_trimat_madd(Qs->l1_Q3, Fs->l1_F1, t2, _V1, _V1_BYTE, _O2, _O1_BYTE); // F1*T2 + batch_mat_madd(Qs->l1_Q3, Fs->l1_F2, _V1, Ts->t3, _O1, _O1_BYTE, _O2, _O1_BYTE); // F1_T2 + F2_T3 + + memset(tempQ, 0, _O1_BYTE * _O2 * _O2); // l1_Q9 + batch_matTr_madd(tempQ, t2, _V1, _V1_BYTE, _O2, Qs->l1_Q3, _O2, _O1_BYTE); // T2tr * ( F1_T2 + F2_T3 ) + PQCLEAN_RAINBOWIACLASSIC_CLEAN_UpperTrianglize(Qs->l1_Q9, tempQ, _O2, _O1_BYTE); // Q9 + + batch_trimatTr_madd(Qs->l1_Q3, Fs->l1_F1, t2, _V1, _V1_BYTE, _O2, _O1_BYTE); // F1_F1T_T2 + F2_T3 // Q3 + + batch_bmatTr_madd(Qs->l1_Q6, Fs->l1_F2, _O1, t2, _V1, _V1_BYTE, _O2, _O1_BYTE); // F2tr*T2 + batch_matTr_madd(Qs->l1_Q6, Ts->t1, _V1, _V1_BYTE, _O1, Qs->l1_Q3, _O2, _O1_BYTE); // Q6 + + /* + layer 2 + Computing: + Q1 = F1 + Q2 = F1_F1T*T1 + F2 + Q5 = UT( T1tr( F1*T1 + F2 ) + F5 ) + */ + memcpy(Qs->l2_Q1, Fs->l2_F1, _O2_BYTE * N_TRIANGLE_TERMS(_V1)); + + memcpy(Qs->l2_Q2, Fs->l2_F2, _O2_BYTE * _V1 * _O1); + batch_trimat_madd(Qs->l2_Q2, Fs->l2_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O2_BYTE); // F1*T1 + F2 + + memcpy(Qs->l2_Q5, Fs->l2_F5, _O2_BYTE * N_TRIANGLE_TERMS(_O1)); + memset(tempQ, 0, _O2_BYTE * _O1 * _O1); // l2_Q5 + batch_matTr_madd(tempQ, Ts->t1, _V1, _V1_BYTE, _O1, Qs->l2_Q2, _O1, _O2_BYTE); // t1_tr*(F1*T1 + F2) + PQCLEAN_RAINBOWIACLASSIC_CLEAN_UpperTrianglize(Qs->l2_Q5, tempQ, _O1, _O2_BYTE); // UT( ... ) // Q5 + + batch_trimatTr_madd(Qs->l2_Q2, Fs->l2_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O2_BYTE); // Q2 + + /* + Computing: + F1_T2 = F1 * t2 + F2_T3 = F2 * t3 + F1_F1T_T2 + F2_T3 = F1_T2 + F2_T3 + F1tr * t2 + + Q3 = F1_F1T*T2 + F2*T3 + F3 + Q9 = UT( T2tr*( F1*T2 + F2*T3 + F3 ) + T3tr*( F5*T3 + F6 ) ) + Q6 = T1tr*( F1_F1T*T2 + F2*T3 + F3 ) + F2Tr*T2 + F5_F5T*T3 + F6 + */ + memcpy(Qs->l2_Q3, Fs->l2_F3, _O2_BYTE * _V1 * _O2); + batch_trimat_madd(Qs->l2_Q3, Fs->l2_F1, t2, _V1, _V1_BYTE, _O2, _O2_BYTE); // F1*T2 + F3 + batch_mat_madd(Qs->l2_Q3, Fs->l2_F2, _V1, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // F1_T2 + F2_T3 + F3 + + memset(tempQ, 0, _O2_BYTE * _O2 * _O2); // l2_Q9 + batch_matTr_madd(tempQ, t2, _V1, _V1_BYTE, _O2, Qs->l2_Q3, _O2, _O2_BYTE); // T2tr * ( ..... ) + + memcpy(Qs->l2_Q6, Fs->l2_F6, _O2_BYTE * _O1 * _O2); + + batch_trimat_madd(Qs->l2_Q6, Fs->l2_F5, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // F5*T3 + F6 + batch_matTr_madd(tempQ, Ts->t3, _O1, _O1_BYTE, _O2, Qs->l2_Q6, _O2, _O2_BYTE); // T2tr*( ..... ) + T3tr*( ..... ) + memset(Qs->l2_Q9, 0, _O2_BYTE * N_TRIANGLE_TERMS(_O2)); + PQCLEAN_RAINBOWIACLASSIC_CLEAN_UpperTrianglize(Qs->l2_Q9, tempQ, _O2, _O2_BYTE); // Q9 + + batch_trimatTr_madd(Qs->l2_Q3, Fs->l2_F1, t2, _V1, _V1_BYTE, _O2, _O2_BYTE); // F1_F1T_T2 + F2_T3 + F3 // Q3 + + batch_bmatTr_madd(Qs->l2_Q6, Fs->l2_F2, _O1, t2, _V1, _V1_BYTE, _O2, _O2_BYTE); // F5*T3 + F6 + F2tr*T2 + batch_trimatTr_madd(Qs->l2_Q6, Fs->l2_F5, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // F2tr*T2 + F5_F5T*T3 + F6 + batch_matTr_madd(Qs->l2_Q6, Ts->t1, _V1, _V1_BYTE, _O1, Qs->l2_Q3, _O2, _O2_BYTE); // Q6 +} +#define calculate_Q_from_F_impl calculate_Q_from_F_ref +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_calculate_Q_from_F(ext_cpk_t *Qs, const sk_t *Fs, const sk_t *Ts) { + calculate_Q_from_F_impl(Qs, Fs, Ts); +} diff --git a/src/sig/rainbow/pqclean_rainbowIa-classic_clean/rainbow_keypair_computation.h b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/rainbow_keypair_computation.h new file mode 100644 index 0000000000..7f8b96d23a --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/rainbow_keypair_computation.h @@ -0,0 +1,53 @@ +#ifndef _RAINBOW_KEYPAIR_COMP_H_ +#define _RAINBOW_KEYPAIR_COMP_H_ +/// @file rainbow_keypair_computation.h +/// @brief Functions for calculating pk/sk while generating keys. +/// +/// Defining an internal structure of public key. +/// Functions for calculating pk/sk for key generation. +/// + +#include "rainbow_keypair.h" + +/// @brief The (internal use) public key for rainbow +/// +/// The (internal use) public key for rainbow. The public +/// polynomials are divided into l1_Q1, l1_Q2, ... l1_Q9, +/// l2_Q1, .... , l2_Q9. +/// +typedef struct rainbow_extend_publickey { + unsigned char l1_Q1[_O1_BYTE * N_TRIANGLE_TERMS(_V1)]; + unsigned char l1_Q2[_O1_BYTE * _V1 * _O1]; + unsigned char l1_Q3[_O1_BYTE * _V1 * _O2]; + unsigned char l1_Q5[_O1_BYTE * N_TRIANGLE_TERMS(_O1)]; + unsigned char l1_Q6[_O1_BYTE * _O1 * _O2]; + unsigned char l1_Q9[_O1_BYTE * N_TRIANGLE_TERMS(_O2)]; + + unsigned char l2_Q1[_O2_BYTE * N_TRIANGLE_TERMS(_V1)]; + unsigned char l2_Q2[_O2_BYTE * _V1 * _O1]; + unsigned char l2_Q3[_O2_BYTE * _V1 * _O2]; + unsigned char l2_Q5[_O2_BYTE * N_TRIANGLE_TERMS(_O1)]; + unsigned char l2_Q6[_O2_BYTE * _O1 * _O2]; + unsigned char l2_Q9[_O2_BYTE * N_TRIANGLE_TERMS(_O2)]; +} ext_cpk_t; + +/// +/// @brief converting formats of public keys : from ext_cpk_t version to pk_t +/// +/// @param[out] pk - the classic public key. +/// @param[in] cpk - the internel public key. +/// +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_extcpk_to_pk(pk_t *pk, const ext_cpk_t *cpk); +///////////////////////////////////////////////// + +/// +/// @brief Computing public key from secret key +/// +/// @param[out] Qs - the public key +/// @param[in] Fs - parts of the secret key: l1_F1, l1_F2, l2_F1, l2_F2, l2_F3, l2_F5, l2_F6 +/// @param[in] Ts - parts of the secret key: T1, T4, T3 +/// +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_calculate_Q_from_F(ext_cpk_t *Qs, const sk_t *Fs, const sk_t *Ts); + + +#endif // _RAINBOW_KEYPAIR_COMP_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-classic_clean/sign.c b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/sign.c new file mode 100644 index 0000000000..ad0647a92b --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/sign.c @@ -0,0 +1,74 @@ +/// @file sign.c +/// @brief the implementations for functions in api.h +/// +/// + +#include "api.h" +#include "rainbow.h" +#include "rainbow_config.h" +#include "rainbow_keypair.h" +#include "randombytes.h" +#include "utils_hash.h" +#include +#include + +int PQCLEAN_RAINBOWIACLASSIC_CLEAN_crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { + unsigned char sk_seed[LEN_SKSEED] = {0}; + randombytes(sk_seed, LEN_SKSEED); + + PQCLEAN_RAINBOWIACLASSIC_CLEAN_generate_keypair((pk_t *)pk, (sk_t *)sk, sk_seed); + return 0; +} + +int PQCLEAN_RAINBOWIACLASSIC_CLEAN_crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { + unsigned char digest[_HASH_LEN]; + + PQCLEAN_RAINBOWIACLASSIC_CLEAN_hash_msg(digest, _HASH_LEN, m, mlen); + + memcpy(sm, m, mlen); + smlen[0] = mlen + _SIGNATURE_BYTE; + + return PQCLEAN_RAINBOWIACLASSIC_CLEAN_rainbow_sign(sm + mlen, (const sk_t *)sk, digest); +} + +int PQCLEAN_RAINBOWIACLASSIC_CLEAN_crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { + int rc; + if (_SIGNATURE_BYTE > smlen) { + rc = -1; + } else { + *mlen = smlen - _SIGNATURE_BYTE; + + unsigned char digest[_HASH_LEN]; + PQCLEAN_RAINBOWIACLASSIC_CLEAN_hash_msg(digest, _HASH_LEN, sm, *mlen); + + rc = PQCLEAN_RAINBOWIACLASSIC_CLEAN_rainbow_verify(digest, sm + mlen[0], (const pk_t *)pk); + } + if (!rc) { + memmove(m, sm, smlen - _SIGNATURE_BYTE); + } else { // bad signature + *mlen = (size_t) -1; + memset(m, 0, smlen); + } + return rc; +} + +int PQCLEAN_RAINBOWIACLASSIC_CLEAN_crypto_sign_signature( + uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + unsigned char digest[_HASH_LEN]; + + PQCLEAN_RAINBOWIACLASSIC_CLEAN_hash_msg(digest, _HASH_LEN, m, mlen); + *siglen = _SIGNATURE_BYTE; + return PQCLEAN_RAINBOWIACLASSIC_CLEAN_rainbow_sign(sig, (const sk_t *)sk, digest); +} + +int PQCLEAN_RAINBOWIACLASSIC_CLEAN_crypto_sign_verify( + const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + if (siglen != _SIGNATURE_BYTE) { + return -1; + } + unsigned char digest[_HASH_LEN]; + PQCLEAN_RAINBOWIACLASSIC_CLEAN_hash_msg(digest, _HASH_LEN, m, mlen); + return PQCLEAN_RAINBOWIACLASSIC_CLEAN_rainbow_verify(digest, sig, (const pk_t *)pk); +} diff --git a/src/sig/rainbow/pqclean_rainbowIa-classic_clean/utils_hash.c b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/utils_hash.c new file mode 100644 index 0000000000..052f53c87d --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/utils_hash.c @@ -0,0 +1,50 @@ +/// @file utils_hash.c +/// @brief the adapter for SHA2 families. +/// +/// + +#include "utils_hash.h" +#include "rainbow_config.h" +#include "sha2.h" + +static inline int _hash(unsigned char *digest, const unsigned char *m, size_t mlen) { + sha256(digest, m, mlen); + return 0; +} + +static inline int expand_hash(unsigned char *digest, size_t n_digest, const unsigned char *hash) { + if (_HASH_LEN >= n_digest) { + for (size_t i = 0; i < n_digest; i++) { + digest[i] = hash[i]; + } + return 0; + } + for (size_t i = 0; i < _HASH_LEN; i++) { + digest[i] = hash[i]; + } + n_digest -= _HASH_LEN; + + while (_HASH_LEN <= n_digest) { + _hash(digest + _HASH_LEN, digest, _HASH_LEN); + + n_digest -= _HASH_LEN; + digest += _HASH_LEN; + } + unsigned char temp[_HASH_LEN]; + if (n_digest) { + _hash(temp, digest, _HASH_LEN); + for (size_t i = 0; i < n_digest; i++) { + digest[_HASH_LEN + i] = temp[i]; + } + } + return 0; +} + +int PQCLEAN_RAINBOWIACLASSIC_CLEAN_hash_msg(unsigned char *digest, + size_t len_digest, + const unsigned char *m, + size_t mlen) { + unsigned char buf[_HASH_LEN]; + _hash(buf, m, mlen); + return expand_hash(digest, len_digest, buf); +} diff --git a/src/sig/rainbow/pqclean_rainbowIa-classic_clean/utils_hash.h b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/utils_hash.h new file mode 100644 index 0000000000..da190bac35 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/utils_hash.h @@ -0,0 +1,11 @@ +#ifndef _UTILS_HASH_H_ +#define _UTILS_HASH_H_ +/// @file utils_hash.h +/// @brief the interface for adapting hash functions. +/// + +#include + +int PQCLEAN_RAINBOWIACLASSIC_CLEAN_hash_msg(unsigned char *digest, size_t len_digest, const unsigned char *m, size_t mlen); + +#endif // _UTILS_HASH_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-classic_clean/utils_prng.c b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/utils_prng.c new file mode 100644 index 0000000000..fdfbe10b59 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/utils_prng.c @@ -0,0 +1,97 @@ +/// @file utils_prng.c +/// @brief The implementation of PRNG related functions. +/// + +#include "utils_prng.h" +#include "aes.h" +#include "randombytes.h" +#include "utils_hash.h" +#include +#include + +static void prng_update(const unsigned char *provided_data, + unsigned char *Key, + unsigned char *V) { + unsigned char temp[48]; + aes256ctx ctx; + aes256_keyexp(&ctx, Key); + for (int i = 0; i < 3; i++) { + //increment V + for (int j = 15; j >= 0; j--) { + if (V[j] == 0xff) { + V[j] = 0x00; + } else { + V[j]++; + break; + } + } + aes256_ecb(temp + 16 * i, V, 1, &ctx); + } + if (provided_data != NULL) { + for (int i = 0; i < 48; i++) { + temp[i] ^= provided_data[i]; + } + } + aes256_ctx_release(&ctx); + memcpy(Key, temp, 32); + memcpy(V, temp + 32, 16); +} +static void randombytes_init_with_state(prng_t *state, + unsigned char *entropy_input_48bytes) { + memset(state->Key, 0x00, 32); + memset(state->V, 0x00, 16); + prng_update(entropy_input_48bytes, state->Key, state->V); +} + +static int randombytes_with_state(prng_t *state, + unsigned char *x, + size_t xlen) { + + unsigned char block[16]; + int i = 0; + + aes256ctx ctx; + aes256_keyexp(&ctx, state->Key); + + while (xlen > 0) { + //increment V + for (int j = 15; j >= 0; j--) { + if (state->V[j] == 0xff) { + state->V[j] = 0x00; + } else { + state->V[j]++; + break; + } + } + aes256_ecb(block, state->V, 1, &ctx); + if (xlen > 15) { + memcpy(x + i, block, 16); + i += 16; + xlen -= 16; + } else { + memcpy(x + i, block, xlen); + xlen = 0; + } + } + aes256_ctx_release(&ctx); + prng_update(NULL, state->Key, state->V); + return 0; +} + +int PQCLEAN_RAINBOWIACLASSIC_CLEAN_prng_set(prng_t *ctx, const void *prng_seed, unsigned long prng_seedlen) { + unsigned char seed[48]; + if (prng_seedlen >= 48) { + memcpy(seed, prng_seed, 48); + } else { + memcpy(seed, prng_seed, prng_seedlen); + PQCLEAN_RAINBOWIACLASSIC_CLEAN_hash_msg(seed + prng_seedlen, 48 - (unsigned)prng_seedlen, (const unsigned char *)prng_seed, prng_seedlen); + } + + randombytes_init_with_state(ctx, seed); + + return 0; +} + +int PQCLEAN_RAINBOWIACLASSIC_CLEAN_prng_gen(prng_t *ctx, unsigned char *out, unsigned long outlen) { + return randombytes_with_state(ctx, out, outlen); +} diff --git a/src/sig/rainbow/pqclean_rainbowIa-classic_clean/utils_prng.h b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/utils_prng.h new file mode 100644 index 0000000000..0c1a5323ae --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-classic_clean/utils_prng.h @@ -0,0 +1,18 @@ +#ifndef _UTILS_PRNG_H_ +#define _UTILS_PRNG_H_ +/// @file utils_prng.h +/// @brief the interface for adapting PRNG functions. +/// +/// + +#include "randombytes.h" + +typedef struct { + unsigned char Key[32]; + unsigned char V[16]; +} prng_t; + +int PQCLEAN_RAINBOWIACLASSIC_CLEAN_prng_set(prng_t *ctx, const void *prng_seed, unsigned long prng_seedlen); +int PQCLEAN_RAINBOWIACLASSIC_CLEAN_prng_gen(prng_t *ctx, unsigned char *out, unsigned long outlen); + +#endif // _UTILS_PRNG_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/LICENSE b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/LICENSE new file mode 100644 index 0000000000..cb00a6e354 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/LICENSE @@ -0,0 +1,8 @@ +`Software implementation of Rainbow for NIST R2 submission' by Ming-Shing Chen + +To the extent possible under law, the person who associated CC0 with +`Software implementation of Rainbow for NIST R2 submission' has waived all copyright and related or neighboring rights +to `Software implementation of Rainbow for NIST R2 submission'. + +You should have received a copy of the CC0 legalcode along with this +work. If not, see . diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/api.h b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/api.h new file mode 100644 index 0000000000..6d2f6c21f5 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/api.h @@ -0,0 +1,32 @@ +#ifndef PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_API_H +#define PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_API_H + +#include +#include + +#define PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_CRYPTO_SECRETKEYBYTES 64 +#define PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_CRYPTO_PUBLICKEYBYTES 58144 +#define PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_CRYPTO_BYTES 64 +#define PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_CRYPTO_ALGNAME "RAINBOW(16,32,32,32) - cyclic compressed" + +int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + + +int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_crypto_sign_signature( + uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_crypto_sign_verify( + const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + + +#endif diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/blas.c b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/blas.c new file mode 100644 index 0000000000..4acac4e769 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/blas.c @@ -0,0 +1,43 @@ +#include "blas.h" +#include "gf.h" + +#include + +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_predicated_add(uint8_t *accu_b, uint8_t predicate, const uint8_t *a, size_t _num_byte) { + uint8_t pr_u8 = (uint8_t) ((uint8_t) 0 - predicate); + for (size_t i = 0; i < _num_byte; i++) { + accu_b[i] ^= (a[i] & pr_u8); + } +} + +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_add(uint8_t *accu_b, const uint8_t *a, size_t _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + accu_b[i] ^= a[i]; + } +} + + +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_mul_scalar(uint8_t *a, uint8_t gf16_b, size_t _num_byte) { + uint8_t tmp; + for (size_t i = 0; i < _num_byte; i++) { + tmp = PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16_mul(a[i] & 0xF, gf16_b); + tmp |= (uint8_t) (PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16_mul(a[i] >> 4, gf16_b) << 4); + a[i] = tmp; + } +} + +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_madd(uint8_t *accu_c, const uint8_t *a, uint8_t gf16_b, size_t _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + accu_c[i] ^= PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16_mul(a[i] & 0xF, gf16_b); + accu_c[i] ^= (uint8_t) (PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16_mul(a[i] >> 4, gf16_b) << 4); + } +} + +uint8_t PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_dot(const uint8_t *a, const uint8_t *b, size_t _num_byte) { + uint8_t r = 0; + for (size_t i = 0; i < _num_byte; i++) { + r ^= PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16_mul(a[i], b[i]); + } + return r; +} + diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/blas.h b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/blas.h new file mode 100644 index 0000000000..b2d36f3a03 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/blas.h @@ -0,0 +1,20 @@ +#ifndef _BLAS_H_ +#define _BLAS_H_ +/// @file blas.h +/// @brief Functions for implementing basic linear algebra functions. +/// + +#include "rainbow_config.h" +#include +#include + +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_predicated_add(uint8_t *accu_b, uint8_t predicate, const uint8_t *a, size_t _num_byte); +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_add(uint8_t *accu_b, const uint8_t *a, size_t _num_byte); + + +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_madd(uint8_t *accu_c, const uint8_t *a, uint8_t gf16_b, size_t _num_byte); +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_mul_scalar(uint8_t *a, uint8_t gf16_b, size_t _num_byte); +uint8_t PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_dot(const uint8_t *a, const uint8_t *b, size_t _num_byte); + + +#endif // _BLAS_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/blas_comm.c b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/blas_comm.c new file mode 100644 index 0000000000..0bbc845ec6 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/blas_comm.c @@ -0,0 +1,152 @@ +/// @file blas_comm.c +/// @brief The standard implementations for blas_comm.h +/// + +#include "blas_comm.h" +#include "blas.h" +#include "gf.h" +#include "rainbow_config.h" + +#include +#include + +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_set_zero(uint8_t *b, unsigned int _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + b[i] = 0; + } +} + +/// @brief get an element from GF(16) vector . +/// +/// @param[in] a - the input vector a. +/// @param[in] i - the index in the vector a. +/// @return the value of the element. +/// +uint8_t PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_get_ele(const uint8_t *a, unsigned int i) { + uint8_t r = a[i >> 1]; + uint8_t r0 = r & 0xf; + uint8_t r1 = r >> 4; + uint8_t m = (uint8_t)(-((int8_t)i & 1)); + return (uint8_t)((r1 & m) | ((~m) & r0)); +} + +/// @brief set an element for a GF(16) vector . +/// +/// @param[in,out] a - the vector a. +/// @param[in] i - the index in the vector a. +/// @param[in] v - the value for the i-th element in vector a. +/// @return the value of the element. +/// +static uint8_t PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_set_ele(uint8_t *a, unsigned int i, uint8_t v) { + uint8_t m = (uint8_t)(0xf ^ (-((int8_t)i & 1))); /// 1--> 0xf0 , 0--> 0x0f + uint8_t ai_remaining = (uint8_t)(a[i >> 1] & (~m)); /// erase + a[i >> 1] = (uint8_t)(ai_remaining | (m & (v << 4)) | (m & v & 0xf)); /// set + return v; +} + +static void gf16mat_prod_ref(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b) { + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_set_zero(c, n_A_vec_byte); + for (unsigned int i = 0; i < n_A_width; i++) { + uint8_t bb = PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_get_ele(b, i); + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_madd(c, matA, bb, n_A_vec_byte); + matA += n_A_vec_byte; + } +} + +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16mat_mul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int len_vec) { + unsigned int n_vec_byte = (len_vec + 1) / 2; + for (unsigned int k = 0; k < len_vec; k++) { + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_set_zero(c, n_vec_byte); + const uint8_t *bk = b + n_vec_byte * k; + for (unsigned int i = 0; i < len_vec; i++) { + uint8_t bb = PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_get_ele(bk, i); + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_madd(c, a + n_vec_byte * i, bb, n_vec_byte); + } + c += n_vec_byte; + } +} + +static unsigned int gf16mat_gauss_elim_ref(uint8_t *mat, unsigned int h, unsigned int w) { + unsigned int n_w_byte = (w + 1) / 2; + unsigned int r8 = 1; + for (unsigned int i = 0; i < h; i++) { + unsigned int offset_byte = i >> 1; + uint8_t *ai = mat + n_w_byte * i; + for (unsigned int j = i + 1; j < h; j++) { + uint8_t *aj = mat + n_w_byte * j; + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_predicated_add(ai + offset_byte, !PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16_is_nonzero(PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_get_ele(ai, i)), aj + offset_byte, n_w_byte - offset_byte); + } + uint8_t pivot = PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_get_ele(ai, i); + r8 &= PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16_is_nonzero(pivot); + pivot = PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16_inv(pivot); + offset_byte = (i + 1) >> 1; + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_mul_scalar(ai + offset_byte, pivot, n_w_byte - offset_byte); + for (unsigned int j = 0; j < h; j++) { + if (i == j) { + continue; + } + uint8_t *aj = mat + n_w_byte * j; + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_madd(aj + offset_byte, ai + offset_byte, PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_get_ele(aj, i), n_w_byte - offset_byte); + } + } + return r8; +} + +static unsigned int gf16mat_solve_linear_eq_ref(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n) { + uint8_t mat[64 * 33]; + unsigned int n_byte = (n + 1) >> 1; + for (unsigned int i = 0; i < n; i++) { + memcpy(mat + i * (n_byte + 1), inp_mat + i * n_byte, n_byte); + mat[i * (n_byte + 1) + n_byte] = PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_get_ele(c_terms, i); + } + unsigned int r8 = PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16mat_gauss_elim(mat, n, n + 2); + for (unsigned int i = 0; i < n; i++) { + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_set_ele(sol, i, mat[i * (n_byte + 1) + n_byte]); + } + return r8; +} + +static inline void gf16mat_submat(uint8_t *mat2, unsigned int w2, unsigned int st, const uint8_t *mat, unsigned int w, unsigned int h) { + unsigned int n_byte_w1 = (w + 1) / 2; + unsigned int n_byte_w2 = (w2 + 1) / 2; + unsigned int st_2 = st / 2; + for (unsigned int i = 0; i < h; i++) { + for (unsigned int j = 0; j < n_byte_w2; j++) { + mat2[i * n_byte_w2 + j] = mat[i * n_byte_w1 + st_2 + j]; + } + } +} + +unsigned int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16mat_inv(uint8_t *inv_a, const uint8_t *a, unsigned int H, uint8_t *buffer) { + unsigned int n_w_byte = (H + 1) / 2; + + uint8_t *aa = buffer; + for (unsigned int i = 0; i < H; i++) { + uint8_t *ai = aa + i * 2 * n_w_byte; + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_set_zero(ai, 2 * n_w_byte); + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_add(ai, a + i * n_w_byte, n_w_byte); + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_set_ele(ai + n_w_byte, i, 1); + } + unsigned int r8 = PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16mat_gauss_elim(aa, H, 2 * H); + gf16mat_submat(inv_a, H, H, aa, 2 * H, H); + return r8; +} + +// choosing the implementations depends on the macros _BLAS_AVX2_ and _BLAS_SSE + +#define gf16mat_prod_impl gf16mat_prod_ref +#define gf16mat_gauss_elim_impl gf16mat_gauss_elim_ref +#define gf16mat_solve_linear_eq_impl gf16mat_solve_linear_eq_ref + +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16mat_prod(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b) { + gf16mat_prod_impl(c, matA, n_A_vec_byte, n_A_width, b); +} + +unsigned int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16mat_gauss_elim(uint8_t *mat, unsigned int h, unsigned int w) { + return gf16mat_gauss_elim_impl(mat, h, w); +} + +unsigned int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16mat_solve_linear_eq(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n) { + return gf16mat_solve_linear_eq_impl(sol, inp_mat, c_terms, n); +} + diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/blas_comm.h b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/blas_comm.h new file mode 100644 index 0000000000..bf0131b7f2 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/blas_comm.h @@ -0,0 +1,74 @@ +#ifndef _BLAS_COMM_H_ +#define _BLAS_COMM_H_ +/// @file blas_comm.h +/// @brief Common functions for linear algebra. +/// + +#include "rainbow_config.h" +#include + +/// @brief set a vector to 0. +/// +/// @param[in,out] b - the vector b. +/// @param[in] _num_byte - number of bytes for the vector b. +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_set_zero(uint8_t *b, unsigned int _num_byte); + +/// @brief get an element from GF(16) vector . +/// +/// @param[in] a - the input vector a. +/// @param[in] i - the index in the vector a. +/// @return the value of the element. +/// +uint8_t PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_get_ele(const uint8_t *a, unsigned int i); + +/// @brief matrix-matrix multiplication: c = a * b , in GF(16) +/// +/// @param[out] c - the output matrix c +/// @param[in] c - a matrix a. +/// @param[in] b - a matrix b. +/// @param[in] len_vec - the length of column vectors. +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16mat_mul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int len_vec); + +/// @brief Gauss elimination for a matrix, in GF(16) +/// +/// @param[in,out] mat - the matrix. +/// @param[in] h - the height of the matrix. +/// @param[in] w - the width of the matrix. +/// @return 1(true) if success. 0(false) if the matrix is singular. +/// +unsigned int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16mat_gauss_elim(uint8_t *mat, unsigned int h, unsigned int w); + +/// @brief Solving linear equations, in GF(16) +/// +/// @param[out] sol - the solutions. +/// @param[in] inp_mat - the matrix parts of input equations. +/// @param[in] c_terms - the constant terms of the input equations. +/// @param[in] n - the number of equations. +/// @return 1(true) if success. 0(false) if the matrix is singular. +/// +unsigned int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16mat_solve_linear_eq(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n); + +/// @brief Computing the inverse matrix, in GF(16) +/// +/// @param[out] inv_a - the output of matrix a. +/// @param[in] a - a matrix a. +/// @param[in] H - height of matrix a, i.e., matrix a is an HxH matrix. +/// @param[in] buffer - The buffer for computations. it has to be as large as 2 input matrixes. +/// @return 1(true) if success. 0(false) if the matrix is singular. +/// +unsigned int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16mat_inv(uint8_t *inv_a, const uint8_t *a, unsigned int H, uint8_t *buffer); + +/// @brief matrix-vector multiplication: c = matA * b , in GF(16) +/// +/// @param[out] c - the output vector c +/// @param[in] matA - a column-major matrix A. +/// @param[in] n_A_vec_byte - the size of column vectors in bytes. +/// @param[in] n_A_width - the width of matrix A. +/// @param[in] b - the vector b. +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16mat_prod(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b); + + +#endif // _BLAS_COMM_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/gf.c b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/gf.c new file mode 100644 index 0000000000..4eb7f7d9e0 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/gf.c @@ -0,0 +1,54 @@ +#include "gf.h" + +//// gf4 := gf2[x]/x^2+x+1 +static inline uint8_t gf4_mul_2(uint8_t a) { + uint8_t r = (uint8_t)(a << 1); + r ^= (uint8_t)((a >> 1) * 7); + return r; +} + +static inline uint8_t gf4_mul(uint8_t a, uint8_t b) { + uint8_t r = (uint8_t)(a * (b & 1)); + return r ^ (uint8_t)(gf4_mul_2(a) * (b >> 1)); +} + +static inline uint8_t gf4_squ(uint8_t a) { + return a ^ (a >> 1); +} + +//// gf16 := gf4[y]/y^2+y+x +uint8_t PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16_mul(uint8_t a, uint8_t b) { + uint8_t a0 = a & 3; + uint8_t a1 = (a >> 2); + uint8_t b0 = b & 3; + uint8_t b1 = (b >> 2); + uint8_t a0b0 = gf4_mul(a0, b0); + uint8_t a1b1 = gf4_mul(a1, b1); + uint8_t a0b1_a1b0 = gf4_mul(a0 ^ a1, b0 ^ b1) ^ a0b0 ^ a1b1; + uint8_t a1b1_x2 = gf4_mul_2(a1b1); + return (uint8_t)((a0b1_a1b0 ^ a1b1) << 2 ^ a0b0 ^ a1b1_x2); +} + +static inline uint8_t gf16_squ(uint8_t a) { + uint8_t a0 = a & 3; + uint8_t a1 = (a >> 2); + a1 = gf4_squ(a1); + uint8_t a1squ_x2 = gf4_mul_2(a1); + return (uint8_t)((a1 << 2) ^ a1squ_x2 ^ gf4_squ(a0)); +} + +uint8_t PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16_is_nonzero(uint8_t a) { + unsigned int a4 = a & 0xf; + unsigned int r = ((unsigned int)0) - a4; + r >>= 4; + return r & 1; +} + +uint8_t PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16_inv(uint8_t a) { + uint8_t a2 = gf16_squ(a); + uint8_t a4 = gf16_squ(a2); + uint8_t a8 = gf16_squ(a4); + uint8_t a6 = PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16_mul(a4, a2); + return PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16_mul(a8, a6); +} + diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/gf.h b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/gf.h new file mode 100644 index 0000000000..5c3000823d --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/gf.h @@ -0,0 +1,18 @@ +#ifndef _GF16_H_ +#define _GF16_H_ + +#include "rainbow_config.h" +#include + +/// @file gf16.h +/// @brief Library for arithmetics in GF(16) and GF(256) +/// + +uint8_t PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16_mul(uint8_t a, uint8_t b); + + +uint8_t PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16_is_nonzero(uint8_t a); +uint8_t PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16_inv(uint8_t a); + + +#endif // _GF16_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/parallel_matrix_op.c b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/parallel_matrix_op.c new file mode 100644 index 0000000000..7083c961f8 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/parallel_matrix_op.c @@ -0,0 +1,182 @@ +/// @file parallel_matrix_op.c +/// @brief the standard implementations for functions in parallel_matrix_op.h +/// +/// the standard implementations for functions in parallel_matrix_op.h +/// + +#include "parallel_matrix_op.h" +#include "blas.h" +#include "blas_comm.h" + +/// +/// @brief Calculate the corresponding index in an array for an upper-triangle(UT) matrix. +/// +/// @param[in] i_row - the i-th row in an upper-triangle matrix. +/// @param[in] j_col - the j-th column in an upper-triangle matrix. +/// @param[in] dim - the dimension of the upper-triangle matrix, i.e., an dim x dim matrix. +/// @return the corresponding index in an array storage. +/// +unsigned int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_idx_of_trimat(unsigned int i_row, unsigned int j_col, unsigned int dim) { + return (dim + dim - i_row + 1) * i_row / 2 + j_col - i_row; +} + +/// +/// @brief Calculate the corresponding index in an array for an upper-triangle or lower-triangle matrix. +/// +/// @param[in] i_row - the i-th row in a triangle matrix. +/// @param[in] j_col - the j-th column in a triangle matrix. +/// @param[in] dim - the dimension of the triangle matrix, i.e., an dim x dim matrix. +/// @return the corresponding index in an array storage. +/// +static inline unsigned int idx_of_2trimat(unsigned int i_row, unsigned int j_col, unsigned int n_var) { + if (i_row > j_col) { + return PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_idx_of_trimat(j_col, i_row, n_var); + } + return PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_idx_of_trimat(i_row, j_col, n_var); +} + +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_UpperTrianglize(unsigned char *btriC, const unsigned char *bA, unsigned int Awidth, unsigned int size_batch) { + unsigned char *runningC = btriC; + unsigned int Aheight = Awidth; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < i; j++) { + unsigned int idx = PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_idx_of_trimat(j, i, Aheight); + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_add(btriC + idx * size_batch, bA + size_batch * (i * Awidth + j), size_batch); + } + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_add(runningC, bA + size_batch * (i * Awidth + i), size_batch * (Aheight - i)); + runningC += size_batch * (Aheight - i); + } +} + +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_trimat_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Awidth = Bheight; + unsigned int Aheight = Awidth; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + if (k < i) { + continue; + } + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_madd(bC, &btriA[(k - i) * size_batch], PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + btriA += (Aheight - i) * size_batch; + } +} + +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_trimatTr_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Aheight = Bheight; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + if (i < k) { + continue; + } + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_madd(bC, &btriA[size_batch * (PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_idx_of_trimat(k, i, Aheight))], PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_2trimat_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Aheight = Bheight; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + if (i == k) { + continue; + } + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_madd(bC, &btriA[size_batch * (idx_of_2trimat(i, k, Aheight))], PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_matTr_madd_gf16(unsigned char *bC, const unsigned char *A_to_tr, unsigned int Aheight, unsigned int size_Acolvec, unsigned int Awidth, + const unsigned char *bB, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Atr_height = Awidth; + unsigned int Atr_width = Aheight; + for (unsigned int i = 0; i < Atr_height; i++) { + for (unsigned int j = 0; j < Atr_width; j++) { + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_madd(bC, &bB[j * Bwidth * size_batch], PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_get_ele(&A_to_tr[size_Acolvec * i], j), size_batch * Bwidth); + } + bC += size_batch * Bwidth; + } +} + +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_bmatTr_madd_gf16(unsigned char *bC, const unsigned char *bA_to_tr, unsigned int Awidth_before_tr, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + const unsigned char *bA = bA_to_tr; + unsigned int Aheight = Awidth_before_tr; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_madd(bC, &bA[size_batch * (i + k * Aheight)], PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_mat_madd_gf16(unsigned char *bC, const unsigned char *bA, unsigned int Aheight, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Awidth = Bheight; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_madd(bC, &bA[k * size_batch], PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + bA += (Awidth) * size_batch; + } +} + +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_quad_recmat_eval_gf16(unsigned char *z, const unsigned char *y, unsigned int dim_y, const unsigned char *mat, + const unsigned char *x, unsigned int dim_x, unsigned int size_batch) { + unsigned char tmp[128]; + + unsigned char _x[128]; + for (unsigned int i = 0; i < dim_x; i++) { + _x[i] = PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_get_ele(x, i); + } + unsigned char _y[128]; + for (unsigned int i = 0; i < dim_y; i++) { + _y[i] = PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_get_ele(y, i); + } + + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_set_zero(z, size_batch); + for (unsigned int i = 0; i < dim_y; i++) { + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_set_zero(tmp, size_batch); + for (unsigned int j = 0; j < dim_x; j++) { + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_madd(tmp, mat, _x[j], size_batch); + mat += size_batch; + } + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_madd(z, tmp, _y[i], size_batch); + } +} + +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_quad_trimat_eval_gf16(unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned int dim, unsigned int size_batch) { + unsigned char tmp[256]; + + unsigned char _x[256]; + for (unsigned int i = 0; i < dim; i++) { + _x[i] = PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_get_ele(x, i); + } + + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_set_zero(y, size_batch); + for (unsigned int i = 0; i < dim; i++) { + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_set_zero(tmp, size_batch); + for (unsigned int j = i; j < dim; j++) { + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_madd(tmp, trimat, _x[j], size_batch); + trimat += size_batch; + } + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_madd(y, tmp, _x[i], size_batch); + } +} diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/parallel_matrix_op.h b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/parallel_matrix_op.h new file mode 100644 index 0000000000..00c40ed78c --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/parallel_matrix_op.h @@ -0,0 +1,260 @@ +#ifndef _P_MATRIX_OP_H_ +#define _P_MATRIX_OP_H_ +/// @file parallel_matrix_op.h +/// @brief Librarys for operations of batched matrixes. +/// +/// + +//////////////// Section: triangle matrix <-> rectangle matrix /////////////////////////////////// + +/// +/// @brief Calculate the corresponding index in an array for an upper-triangle(UT) matrix. +/// +/// @param[in] i_row - the i-th row in an upper-triangle matrix. +/// @param[in] j_col - the j-th column in an upper-triangle matrix. +/// @param[in] dim - the dimension of the upper-triangle matrix, i.e., an dim x dim matrix. +/// @return the corresponding index in an array storage. +/// +unsigned int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_idx_of_trimat(unsigned int i_row, unsigned int j_col, unsigned int dim); + +/// +/// @brief Upper trianglize a rectangle matrix to the corresponding upper-trangle matrix. +/// +/// @param[out] btriC - the batched upper-trianglized matrix C. +/// @param[in] bA - a batched retangle matrix A. +/// @param[in] bwidth - the width of the batched matrix A, i.e., A is a Awidth x Awidth matrix. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_UpperTrianglize(unsigned char *btriC, const unsigned char *bA, unsigned int Awidth, unsigned int size_batch); + +//////////////////// Section: matrix multiplications /////////////////////////////// + +/// +/// @brief bC += btriA * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_trimat_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += btriA * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += btriA^Tr * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. A will be transposed while multiplying. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_trimatTr_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += btriA^Tr * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A, which will be transposed while multiplying. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_trimatTr_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += (btriA + btriA^Tr) *B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. The operand for multiplication is (btriA + btriA^Tr). +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_2trimat_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += (btriA + btriA^Tr) *B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. The operand for multiplication is (btriA + btriA^Tr). +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_2trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += A^Tr * bB , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] A_to_tr - a column-major matrix A. The operand for multiplication is A^Tr. +/// @param[in] Aheight - the height of A. +/// @param[in] size_Acolvec - the size of a column vector in A. +/// @param[in] Awidth - the width of A. +/// @param[in] bB - a batched matrix B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_matTr_madd_gf16(unsigned char *bC, + const unsigned char *A_to_tr, unsigned int Aheight, unsigned int size_Acolvec, unsigned int Awidth, + const unsigned char *bB, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += A^Tr * bB , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] A_to_tr - a column-major matrix A. The operand for multiplication is A^Tr. +/// @param[in] Aheight - the height of A. +/// @param[in] size_Acolvec - the size of a column vector in A. +/// @param[in] Awidth - the width of A. +/// @param[in] bB - a batched matrix B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_matTr_madd_gf256(unsigned char *bC, + const unsigned char *A_to_tr, unsigned int Aheight, unsigned int size_Acolvec, unsigned int Awidth, + const unsigned char *bB, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA^Tr * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA_to_tr - a batched matrix A. The operand for multiplication is (bA^Tr). +/// @param[in] Awidth_befor_tr - the width of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_bmatTr_madd_gf16(unsigned char *bC, const unsigned char *bA_to_tr, unsigned int Awidth_before_tr, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA^Tr * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA_to_tr - a batched matrix A. The operand for multiplication is (bA^Tr). +/// @param[in] Awidth_befor_tr - the width of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_bmatTr_madd_gf256(unsigned char *bC, const unsigned char *bA_to_tr, unsigned int Awidth_before_tr, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA - a batched matrix A. +/// @param[in] Aheigh - the height of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_mat_madd_gf16(unsigned char *bC, const unsigned char *bA, unsigned int Aheight, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA - a batched matrix A. +/// @param[in] Aheigh - the height of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_mat_madd_gf256(unsigned char *bC, const unsigned char *bA, unsigned int Aheight, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +//////////////////// Section: "quadratric" matrix evaluation /////////////////////////////// + +/// +/// @brief y = x^Tr * trimat * x , in GF(16) +/// +/// @param[out] y - the returned batched element y. +/// @param[in] trimat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim - the dimension of matrix trimat (and x). +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_quad_trimat_eval_gf16(unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned int dim, unsigned int size_batch); + +/// +/// @brief y = x^Tr * trimat * x , in GF(256) +/// +/// @param[out] y - the returned batched element y. +/// @param[in] trimat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim - the dimension of matrix trimat (and x). +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_quad_trimat_eval_gf256(unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned int dim, unsigned int size_batch); + +/// +/// @brief z = y^Tr * mat * x , in GF(16) +/// +/// @param[out] z - the returned batched element z. +/// @param[in] y - an input vector y. +/// @param[in] dim_y - the length of y. +/// @param[in] mat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim_x - the length of x. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_quad_recmat_eval_gf16(unsigned char *z, const unsigned char *y, unsigned int dim_y, + const unsigned char *mat, const unsigned char *x, unsigned int dim_x, unsigned int size_batch); + +/// +/// @brief z = y^Tr * mat * x , in GF(256) +/// +/// @param[out] z - the returned batched element z. +/// @param[in] y - an input vector y. +/// @param[in] dim_y - the length of y. +/// @param[in] mat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim_x - the length of x. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_quad_recmat_eval_gf256(unsigned char *z, const unsigned char *y, unsigned int dim_y, + const unsigned char *mat, const unsigned char *x, unsigned int dim_x, unsigned int size_batch); + +#endif // _P_MATRIX_OP_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/rainbow.c b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/rainbow.c new file mode 100644 index 0000000000..c25cabacc9 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/rainbow.c @@ -0,0 +1,179 @@ +/// @file rainbow.c +/// @brief The standard implementations for functions in rainbow.h +/// + +#include "blas.h" +#include "parallel_matrix_op.h" +#include "rainbow.h" +#include "rainbow_blas.h" +#include "rainbow_config.h" +#include "rainbow_keypair.h" +#include "utils_hash.h" +#include "utils_prng.h" +#include +#include +#include + +#define MAX_ATTEMPT_FRMAT 128 + +int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_rainbow_sign(uint8_t *signature, const sk_t *sk, const uint8_t *_digest) { + uint8_t mat_l1[_O1 * _O1_BYTE]; + uint8_t mat_l2[_O2 * _O2_BYTE]; + uint8_t mat_buffer[2 * _MAX_O * _MAX_O_BYTE]; + + // setup PRNG + prng_t prng_sign; + uint8_t prng_preseed[LEN_SKSEED + _HASH_LEN]; + memcpy(prng_preseed, sk->sk_seed, LEN_SKSEED); + memcpy(prng_preseed + LEN_SKSEED, _digest, _HASH_LEN); // prng_preseed = sk_seed || digest + uint8_t prng_seed[_HASH_LEN]; + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_hash_msg(prng_seed, _HASH_LEN, prng_preseed, _HASH_LEN + LEN_SKSEED); + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_prng_set(&prng_sign, prng_seed, _HASH_LEN); // seed = H( sk_seed || digest ) + for (unsigned int i = 0; i < LEN_SKSEED + _HASH_LEN; i++) { + prng_preseed[i] ^= prng_preseed[i]; // clean + } + for (unsigned int i = 0; i < _HASH_LEN; i++) { + prng_seed[i] ^= prng_seed[i]; // clean + } + + // roll vinegars. + uint8_t vinegar[_V1_BYTE]; + unsigned int n_attempt = 0; + unsigned int l1_succ = 0; + while (!l1_succ) { + if (MAX_ATTEMPT_FRMAT <= n_attempt) { + break; + } + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_prng_gen(&prng_sign, vinegar, _V1_BYTE); // generating vinegars + gfmat_prod(mat_l1, sk->l1_F2, _O1 * _O1_BYTE, _V1, vinegar); // generating the linear equations for layer 1 + l1_succ = gfmat_inv(mat_l1, mat_l1, _O1, mat_buffer); // check if the linear equation solvable + n_attempt++; + } + + // Given the vinegars, pre-compute variables needed for layer 2 + uint8_t r_l1_F1[_O1_BYTE] = {0}; + uint8_t r_l2_F1[_O2_BYTE] = {0}; + batch_quad_trimat_eval(r_l1_F1, sk->l1_F1, vinegar, _V1, _O1_BYTE); + batch_quad_trimat_eval(r_l2_F1, sk->l2_F1, vinegar, _V1, _O2_BYTE); + uint8_t mat_l2_F3[_O2 * _O2_BYTE]; + uint8_t mat_l2_F2[_O1 * _O2_BYTE]; + gfmat_prod(mat_l2_F3, sk->l2_F3, _O2 * _O2_BYTE, _V1, vinegar); + gfmat_prod(mat_l2_F2, sk->l2_F2, _O1 * _O2_BYTE, _V1, vinegar); + + // Some local variables. + uint8_t _z[_PUB_M_BYTE]; + uint8_t y[_PUB_M_BYTE]; + uint8_t *x_v1 = vinegar; + uint8_t x_o1[_O1_BYTE]; + uint8_t x_o2[_O1_BYTE]; + + uint8_t digest_salt[_HASH_LEN + _SALT_BYTE]; + memcpy(digest_salt, _digest, _HASH_LEN); + uint8_t *salt = digest_salt + _HASH_LEN; + + uint8_t temp_o[_MAX_O_BYTE + 32] = {0}; + unsigned int succ = 0; + while (!succ) { + if (MAX_ATTEMPT_FRMAT <= n_attempt) { + break; + } + // The computation: H(digest||salt) --> z --S--> y --C-map--> x --T--> w + + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_prng_gen(&prng_sign, salt, _SALT_BYTE); // roll the salt + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_hash_msg(_z, _PUB_M_BYTE, digest_salt, _HASH_LEN + _SALT_BYTE); // H(digest||salt) + + // y = S^-1 * z + memcpy(y, _z, _PUB_M_BYTE); // identity part of S + gfmat_prod(temp_o, sk->s1, _O1_BYTE, _O2, _z + _O1_BYTE); + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_add(y, temp_o, _O1_BYTE); + + // Central Map: + // layer 1: calculate x_o1 + memcpy(temp_o, r_l1_F1, _O1_BYTE); + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_add(temp_o, y, _O1_BYTE); + gfmat_prod(x_o1, mat_l1, _O1_BYTE, _O1, temp_o); + + // layer 2: calculate x_o2 + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_set_zero(temp_o, _O2_BYTE); + gfmat_prod(temp_o, mat_l2_F2, _O2_BYTE, _O1, x_o1); // F2 + batch_quad_trimat_eval(mat_l2, sk->l2_F5, x_o1, _O1, _O2_BYTE); // F5 + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_add(temp_o, mat_l2, _O2_BYTE); + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_add(temp_o, r_l2_F1, _O2_BYTE); // F1 + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_add(temp_o, y + _O1_BYTE, _O2_BYTE); + + // generate the linear equations of the 2nd layer + gfmat_prod(mat_l2, sk->l2_F6, _O2 * _O2_BYTE, _O1, x_o1); // F6 + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_add(mat_l2, mat_l2_F3, _O2 * _O2_BYTE); // F3 + succ = gfmat_inv(mat_l2, mat_l2, _O2, mat_buffer); + gfmat_prod(x_o2, mat_l2, _O2_BYTE, _O2, temp_o); // solve l2 eqs + + n_attempt++; + }; + // w = T^-1 * y + uint8_t w[_PUB_N_BYTE]; + // identity part of T. + memcpy(w, x_v1, _V1_BYTE); + memcpy(w + _V1_BYTE, x_o1, _O1_BYTE); + memcpy(w + _V2_BYTE, x_o2, _O2_BYTE); + // Computing the t1 part. + gfmat_prod(y, sk->t1, _V1_BYTE, _O1, x_o1); + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_add(w, y, _V1_BYTE); + // Computing the t4 part. + gfmat_prod(y, sk->t4, _V1_BYTE, _O2, x_o2); + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_add(w, y, _V1_BYTE); + // Computing the t3 part. + gfmat_prod(y, sk->t3, _O1_BYTE, _O2, x_o2); + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_add(w + _V1_BYTE, y, _O1_BYTE); + + memset(signature, 0, _SIGNATURE_BYTE); // set the output 0 + // clean + memset(&prng_sign, 0, sizeof(prng_t)); + memset(vinegar, 0, _V1_BYTE); + memset(r_l1_F1, 0, _O1_BYTE); + memset(r_l2_F1, 0, _O2_BYTE); + memset(_z, 0, _PUB_M_BYTE); + memset(y, 0, _PUB_M_BYTE); + memset(x_o1, 0, _O1_BYTE); + memset(x_o2, 0, _O2_BYTE); + memset(temp_o, 0, sizeof(temp_o)); + + // return: copy w and salt to the signature. + if (MAX_ATTEMPT_FRMAT <= n_attempt) { + return -1; + } + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_add(signature, w, _PUB_N_BYTE); + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_add(signature + _PUB_N_BYTE, salt, _SALT_BYTE); + return 0; +} + +int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_rainbow_verify(const uint8_t *digest, const uint8_t *signature, const pk_t *pk) { + unsigned char digest_ck[_PUB_M_BYTE]; + // public_map( digest_ck , pk , signature ); Evaluating the quadratic public polynomials. + batch_quad_trimat_eval(digest_ck, pk->pk, signature, _PUB_N, _PUB_M_BYTE); + + unsigned char correct[_PUB_M_BYTE]; + unsigned char digest_salt[_HASH_LEN + _SALT_BYTE]; + memcpy(digest_salt, digest, _HASH_LEN); + memcpy(digest_salt + _HASH_LEN, signature + _PUB_N_BYTE, _SALT_BYTE); + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_hash_msg(correct, _PUB_M_BYTE, digest_salt, _HASH_LEN + _SALT_BYTE); // H( digest || salt ) + + // check consistancy. + unsigned char cc = 0; + for (unsigned int i = 0; i < _PUB_M_BYTE; i++) { + cc |= (digest_ck[i] ^ correct[i]); + } + return (0 == cc) ? 0 : -1; +} + +/////////////// cyclic version /////////////////////////// +int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_rainbow_sign_cyclic(uint8_t *signature, const csk_t *csk, const uint8_t *digest) { + unsigned char sk[sizeof(sk_t) + 32]; + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_generate_secretkey_cyclic((sk_t *)sk, csk->pk_seed, csk->sk_seed); // generating classic secret key. + return PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_rainbow_sign(signature, (sk_t *)sk, digest); +} + +int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_rainbow_verify_cyclic(const uint8_t *digest, const uint8_t *signature, const cpk_t *_pk) { + unsigned char pk[sizeof(pk_t) + 32]; + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_cpk_to_pk((pk_t *)pk, _pk); // generating classic public key. + return PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_rainbow_verify(digest, signature, (pk_t *)pk); +} diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/rainbow.h b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/rainbow.h new file mode 100644 index 0000000000..691125303a --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/rainbow.h @@ -0,0 +1,50 @@ +#ifndef _RAINBOW_H_ +#define _RAINBOW_H_ +/// @file rainbow.h +/// @brief APIs for rainbow. +/// + +#include "rainbow_config.h" +#include "rainbow_keypair.h" + +#include + +/// +/// @brief Signing function for classical secret key. +/// +/// @param[out] signature - the signature. +/// @param[in] sk - the secret key. +/// @param[in] digest - the digest. +/// +int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_rainbow_sign(uint8_t *signature, const sk_t *sk, const uint8_t *digest); + +/// +/// @brief Verifying function. +/// +/// @param[in] digest - the digest. +/// @param[in] signature - the signature. +/// @param[in] pk - the public key. +/// @return 0 for successful verified. -1 for failed verification. +/// +int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_rainbow_verify(const uint8_t *digest, const uint8_t *signature, const pk_t *pk); + +/// +/// @brief Signing function for compressed secret key of the cyclic rainbow. +/// +/// @param[out] signature - the signature. +/// @param[in] sk - the compressed secret key. +/// @param[in] digest - the digest. +/// +int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_rainbow_sign_cyclic(uint8_t *signature, const csk_t *sk, const uint8_t *digest); + +/// +/// @brief Verifying function for cyclic public keys. +/// +/// @param[in] digest - the digest. +/// @param[in] signature - the signature. +/// @param[in] pk - the public key of cyclic rainbow. +/// @return 0 for successful verified. -1 for failed verification. +/// +int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_rainbow_verify_cyclic(const uint8_t *digest, const uint8_t *signature, const cpk_t *pk); + +#endif // _RAINBOW_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/rainbow_blas.h b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/rainbow_blas.h new file mode 100644 index 0000000000..2c3aee206e --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/rainbow_blas.h @@ -0,0 +1,32 @@ +#ifndef _RAINBOW_BLAS_H_ +#define _RAINBOW_BLAS_H_ +/// @file rainbow_blas.h +/// @brief Defining the functions used in rainbow.c acconding to the definitions in rainbow_config.h +/// +/// Defining the functions used in rainbow.c acconding to the definitions in rainbow_config.h + +#include "blas.h" +#include "blas_comm.h" +#include "parallel_matrix_op.h" +#include "rainbow_config.h" + + +#define gfv_get_ele PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_get_ele +#define gfv_mul_scalar PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_mul_scalar +#define gfv_madd PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16v_madd + +#define gfmat_prod PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16mat_prod +#define gfmat_inv PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf16mat_inv + +#define batch_trimat_madd PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_trimat_madd_gf16 +#define batch_trimatTr_madd PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_trimatTr_madd_gf16 +#define batch_2trimat_madd PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_2trimat_madd_gf16 +#define batch_matTr_madd PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_matTr_madd_gf16 +#define batch_bmatTr_madd PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_bmatTr_madd_gf16 +#define batch_mat_madd PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_mat_madd_gf16 + +#define batch_quad_trimat_eval PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_quad_trimat_eval_gf16 +#define batch_quad_recmat_eval PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_batch_quad_recmat_eval_gf16 + + +#endif // _RAINBOW_BLAS_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/rainbow_config.h b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/rainbow_config.h new file mode 100644 index 0000000000..3607536831 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/rainbow_config.h @@ -0,0 +1,49 @@ +#ifndef _H_RAINBOW_CONFIG_H_ +#define _H_RAINBOW_CONFIG_H_ + +/// @file rainbow_config.h +/// @brief Defining the parameters of the Rainbow and the corresponding constants. +/// + +#define _USE_GF16 +#define _GFSIZE 16 +#define _V1 32 +#define _O1 32 +#define _O2 32 +#define _MAX_O 32 +#define _HASH_LEN 32 + + +#define _V2 ((_V1) + (_O1)) + +/// size of N, in # of gf elements. +#define _PUB_N (_V1 + _O1 + _O2) + +/// size of M, in # gf elements. +#define _PUB_M (_O1 + _O2) + +/// size of variables, in # bytes. + +// GF16 +#define _V1_BYTE (_V1 / 2) +#define _V2_BYTE (_V2 / 2) +#define _O1_BYTE (_O1 / 2) +#define _O2_BYTE (_O2 / 2) +#define _MAX_O_BYTE (_MAX_O / 2) +#define _PUB_N_BYTE (_PUB_N / 2) +#define _PUB_M_BYTE (_PUB_M / 2) + + +/// length of seed for public key, in # bytes +#define LEN_PKSEED 32 + +/// length of seed for secret key, in # bytes +#define LEN_SKSEED 32 + +/// length of salt for a signature, in # bytes +#define _SALT_BYTE 16 + +/// length of a signature +#define _SIGNATURE_BYTE (_PUB_N_BYTE + _SALT_BYTE) + +#endif // _H_RAINBOW_CONFIG_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/rainbow_keypair.c b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/rainbow_keypair.c new file mode 100644 index 0000000000..3aa376deba --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/rainbow_keypair.c @@ -0,0 +1,188 @@ +/// @file rainbow_keypair.c +/// @brief implementations of functions in rainbow_keypair.h +/// + +#include "rainbow_keypair.h" +#include "blas.h" +#include "blas_comm.h" +#include "rainbow_blas.h" +#include "rainbow_keypair_computation.h" +#include "utils_prng.h" +#include +#include +#include + +static void generate_S_T(unsigned char *s_and_t, prng_t *prng0) { + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_prng_gen(prng0, s_and_t, _O1_BYTE * _O2); // S1 + s_and_t += _O1_BYTE * _O2; + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_prng_gen(prng0, s_and_t, _V1_BYTE * _O1); // T1 + s_and_t += _V1_BYTE * _O1; + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_prng_gen(prng0, s_and_t, _V1_BYTE * _O2); // T2 + s_and_t += _V1_BYTE * _O2; + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_prng_gen(prng0, s_and_t, _O1_BYTE * _O2); // T3 +} + +static unsigned int generate_l1_F12(unsigned char *sk, prng_t *prng0) { + unsigned int n_byte_generated = 0; + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_prng_gen(prng0, sk, _O1_BYTE * N_TRIANGLE_TERMS(_V1)); // l1_F1 + sk += _O1_BYTE * N_TRIANGLE_TERMS(_V1); + n_byte_generated += _O1_BYTE * N_TRIANGLE_TERMS(_V1); + + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_prng_gen(prng0, sk, _O1_BYTE * _V1 * _O1); // l1_F2 + n_byte_generated += _O1_BYTE * _V1 * _O1; + return n_byte_generated; +} + +static unsigned int generate_l2_F12356(unsigned char *sk, prng_t *prng0) { + unsigned int n_byte_generated = 0; + + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_prng_gen(prng0, sk, _O2_BYTE * N_TRIANGLE_TERMS(_V1)); // l2_F1 + sk += _O2_BYTE * N_TRIANGLE_TERMS(_V1); + n_byte_generated += _O2_BYTE * N_TRIANGLE_TERMS(_V1); + + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_prng_gen(prng0, sk, _O2_BYTE * _V1 * _O1); // l2_F2 + sk += _O2_BYTE * _V1 * _O1; + n_byte_generated += _O2_BYTE * _V1 * _O1; + + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_prng_gen(prng0, sk, _O2_BYTE * _V1 * _O2); // l2_F3 + sk += _O2_BYTE * _V1 * _O1; + n_byte_generated += _O2_BYTE * _V1 * _O1; + + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_prng_gen(prng0, sk, _O2_BYTE * N_TRIANGLE_TERMS(_O1)); // l2_F5 + sk += _O2_BYTE * N_TRIANGLE_TERMS(_O1); + n_byte_generated += _O2_BYTE * N_TRIANGLE_TERMS(_O1); + + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_prng_gen(prng0, sk, _O2_BYTE * _O1 * _O2); // l2_F6 + n_byte_generated += _O2_BYTE * _O1 * _O2; + + return n_byte_generated; +} + +static void generate_B1_B2(unsigned char *sk, prng_t *prng0) { + sk += generate_l1_F12(sk, prng0); + generate_l2_F12356(sk, prng0); +} + +static void calculate_t4(unsigned char *t2_to_t4, const unsigned char *t1, const unsigned char *t3) { + // t4 = T_sk.t1 * T_sk.t3 - T_sk.t2 + unsigned char temp[_V1_BYTE + 32]; + unsigned char *t4 = t2_to_t4; + for (unsigned int i = 0; i < _O2; i++) { /// t3 width + gfmat_prod(temp, t1, _V1_BYTE, _O1, t3); + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_add(t4, temp, _V1_BYTE); + t4 += _V1_BYTE; + t3 += _O1_BYTE; + } +} + +static void obsfucate_l1_polys(unsigned char *l1_polys, const unsigned char *l2_polys, unsigned int n_terms, const unsigned char *s1) { + unsigned char temp[_O1_BYTE + 32]; + while (n_terms--) { + gfmat_prod(temp, s1, _O1_BYTE, _O2, l2_polys); + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_gf256v_add(l1_polys, temp, _O1_BYTE); + l1_polys += _O1_BYTE; + l2_polys += _O2_BYTE; + } +} + +/////////////////// Classic ////////////////////////////////// + + +///////////////////// Cyclic ////////////////////////////////// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_generate_keypair_cyclic(cpk_t *pk, sk_t *sk, const unsigned char *pk_seed, const unsigned char *sk_seed) { + memcpy(pk->pk_seed, pk_seed, LEN_PKSEED); + memcpy(sk->sk_seed, sk_seed, LEN_SKSEED); + + // prng for sk + prng_t prng; + prng_t *prng0 = &prng; + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_prng_set(prng0, sk_seed, LEN_SKSEED); + generate_S_T(sk->s1, prng0); // S,T: only a part of sk + + unsigned char t2[sizeof(sk->t4)]; + memcpy(t2, sk->t4, _V1_BYTE * _O2); // temporarily store t2 + calculate_t4(sk->t4, sk->t1, sk->t3); // t2 <- t4 + + // prng for pk + sk_t inst_Qs; + sk_t *Qs = &inst_Qs; + prng_t *prng1 = &prng; + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_prng_set(prng1, pk_seed, LEN_PKSEED); + generate_B1_B2(Qs->l1_F1, prng1); // generating l1_Q1, l1_Q2, l2_Q1, l2_Q2, l2_Q3, l2_Q5, l2_Q6 + obsfucate_l1_polys(Qs->l1_F1, Qs->l2_F1, N_TRIANGLE_TERMS(_V1), sk->s1); + obsfucate_l1_polys(Qs->l1_F2, Qs->l2_F2, _V1 * _O1, sk->s1); + // so far, the Qs contains l1_F1, l1_F2, l2_F1, l2_F2, l2_F3, l2_F5, l2_F6. + + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_calculate_F_from_Q(sk, Qs, sk); // calcuate the rest parts of secret key from Qs and S,T + + unsigned char t4[sizeof(sk->t4)]; + memcpy(t4, sk->t4, _V1_BYTE * _O2); // temporarily store t4 + memcpy(sk->t4, t2, _V1_BYTE * _O2); // restore t2 + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_calculate_Q_from_F_cyclic(pk, sk, sk); // calculate the rest parts of public key: l1_Q3, l1_Q5, l1_Q6, l1_Q9, l2_Q9 + memcpy(sk->t4, t4, _V1_BYTE * _O2); // restore t4 + + obsfucate_l1_polys(pk->l1_Q3, Qs->l2_F3, _V1 * _O2, sk->s1); + obsfucate_l1_polys(pk->l1_Q5, Qs->l2_F5, N_TRIANGLE_TERMS(_O1), sk->s1); + obsfucate_l1_polys(pk->l1_Q6, Qs->l2_F6, _O1 * _O2, sk->s1); + obsfucate_l1_polys(pk->l1_Q9, pk->l2_Q9, N_TRIANGLE_TERMS(_O2), sk->s1); + + // clean + memset(&prng, 0, sizeof(prng_t)); +} + + +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_generate_compact_keypair_cyclic(cpk_t *pk, csk_t *rsk, const unsigned char *pk_seed, const unsigned char *sk_seed) { + memcpy(rsk->pk_seed, pk_seed, LEN_PKSEED); + memcpy(rsk->sk_seed, sk_seed, LEN_SKSEED); + sk_t sk; + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_generate_keypair_cyclic(pk, &sk, pk_seed, sk_seed); +} + +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_generate_secretkey_cyclic(sk_t *sk, const unsigned char *pk_seed, const unsigned char *sk_seed) { + memcpy(sk->sk_seed, sk_seed, LEN_SKSEED); + + // prng for sk + prng_t prng0; + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_prng_set(&prng0, sk_seed, LEN_SKSEED); + generate_S_T(sk->s1, &prng0); + calculate_t4(sk->t4, sk->t1, sk->t3); + + // prng for pk + sk_t inst_Qs; + sk_t *Qs = &inst_Qs; + prng_t prng1; + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_prng_set(&prng1, pk_seed, LEN_PKSEED); + generate_B1_B2(Qs->l1_F1, &prng1); + + obsfucate_l1_polys(Qs->l1_F1, Qs->l2_F1, N_TRIANGLE_TERMS(_V1), sk->s1); + obsfucate_l1_polys(Qs->l1_F2, Qs->l2_F2, _V1 * _O1, sk->s1); + + // calcuate the parts of sk according to pk. + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_calculate_F_from_Q(sk, Qs, sk); + + // clean prng for sk + memset(&prng0, 0, sizeof(prng_t)); +} +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_cpk_to_pk(pk_t *rpk, const cpk_t *cpk) { + // procedure: cpk_t --> extcpk_t --> pk_t + + // convert from cpk_t to extcpk_t + ext_cpk_t pk; + + // setup prng + prng_t prng0; + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_prng_set(&prng0, cpk->pk_seed, LEN_SKSEED); + + // generating parts of key with prng + generate_l1_F12(pk.l1_Q1, &prng0); + // copying parts of key from input. l1_Q3, l1_Q5, l1_Q6, l1_Q9 + memcpy(pk.l1_Q3, cpk->l1_Q3, _O1_BYTE * (_V1 * _O2 + N_TRIANGLE_TERMS(_O1) + _O1 * _O2 + N_TRIANGLE_TERMS(_O2))); + + // generating parts of key with prng + generate_l2_F12356(pk.l2_Q1, &prng0); + // copying parts of key from input: l2_Q9 + memcpy(pk.l2_Q9, cpk->l2_Q9, _O2_BYTE * N_TRIANGLE_TERMS(_O2)); + + // convert from extcpk_t to pk_t + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_extcpk_to_pk(rpk, &pk); +} diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/rainbow_keypair.h b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/rainbow_keypair.h new file mode 100644 index 0000000000..718b959cdf --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/rainbow_keypair.h @@ -0,0 +1,111 @@ +#ifndef _RAINBOW_KEYPAIR_H_ +#define _RAINBOW_KEYPAIR_H_ +/// @file rainbow_keypair.h +/// @brief Formats of key pairs and functions for generating key pairs. +/// Formats of key pairs and functions for generating key pairs. +/// + +#include "rainbow_config.h" + +#define N_TRIANGLE_TERMS(n_var) ((n_var) * ((n_var) + 1) / 2) + +/// @brief public key for classic rainbow +/// +/// public key for classic rainbow +/// +typedef struct rainbow_publickey { + unsigned char pk[(_PUB_M_BYTE)*N_TRIANGLE_TERMS(_PUB_N)]; +} pk_t; + +/// @brief secret key for classic rainbow +/// +/// secret key for classic rainbow +/// +typedef struct rainbow_secretkey { + /// + /// seed for generating secret key. + /// Generating S, T, and F for classic rainbow. + /// Generating S and T only for cyclic rainbow. + unsigned char sk_seed[LEN_SKSEED]; + + unsigned char s1[_O1_BYTE * _O2]; ///< part of S map + unsigned char t1[_V1_BYTE * _O1]; ///< part of T map + unsigned char t4[_V1_BYTE * _O2]; ///< part of T map + unsigned char t3[_O1_BYTE * _O2]; ///< part of T map + + unsigned char l1_F1[_O1_BYTE * N_TRIANGLE_TERMS(_V1)]; ///< part of C-map, F1, Layer1 + unsigned char l1_F2[_O1_BYTE * _V1 * _O1]; ///< part of C-map, F2, Layer1 + + unsigned char l2_F1[_O2_BYTE * N_TRIANGLE_TERMS(_V1)]; ///< part of C-map, F1, Layer2 + unsigned char l2_F2[_O2_BYTE * _V1 * _O1]; ///< part of C-map, F2, Layer2 + + unsigned char l2_F3[_O2_BYTE * _V1 * _O2]; ///< part of C-map, F3, Layer2 + unsigned char l2_F5[_O2_BYTE * N_TRIANGLE_TERMS(_O1)]; ///< part of C-map, F5, Layer2 + unsigned char l2_F6[_O2_BYTE * _O1 * _O2]; ///< part of C-map, F6, Layer2 +} sk_t; + +/// @brief public key for cyclic rainbow +/// +/// public key for cyclic rainbow +/// +typedef struct rainbow_publickey_cyclic { + unsigned char pk_seed[LEN_PKSEED]; ///< seed for generating l1_Q1,l1_Q2,l2_Q1,l2_Q2,l2_Q3,l2_Q5,l2_Q6 + + unsigned char l1_Q3[_O1_BYTE * _V1 * _O2]; ///< Q3, layer1 + unsigned char l1_Q5[_O1_BYTE * N_TRIANGLE_TERMS(_O1)]; ///< Q5, layer1 + unsigned char l1_Q6[_O1_BYTE * _O1 * _O2]; ///< Q6, layer1 + unsigned char l1_Q9[_O1_BYTE * N_TRIANGLE_TERMS(_O2)]; ///< Q9, layer1 + + unsigned char l2_Q9[_O2_BYTE * N_TRIANGLE_TERMS(_O2)]; ///< Q9, layer2 +} cpk_t; + +/// @brief compressed secret key for cyclic rainbow +/// +/// compressed secret key for cyclic rainbow +/// +typedef struct rainbow_secretkey_cyclic { + unsigned char pk_seed[LEN_PKSEED]; ///< seed for generating a part of public key. + unsigned char sk_seed[LEN_SKSEED]; ///< seed for generating a part of secret key. +} csk_t; + + +/// +/// @brief Generate key pairs for cyclic rainbow. +/// +/// @param[out] pk - the public key. +/// @param[out] sk - the secret key. +/// @param[in] pk_seed - seed for generating parts of public key. +/// @param[in] sk_seed - seed for generating secret key. +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_generate_keypair_cyclic(cpk_t *pk, sk_t *sk, const unsigned char *pk_seed, const unsigned char *sk_seed); + +/// +/// @brief Generate compressed key pairs for cyclic rainbow. +/// +/// @param[out] pk - the public key. +/// @param[out] sk - the compressed secret key. +/// @param[in] pk_seed - seed for generating parts of the public key. +/// @param[in] sk_seed - seed for generating the secret key. +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_generate_compact_keypair_cyclic(cpk_t *pk, csk_t *sk, const unsigned char *pk_seed, const unsigned char *sk_seed); + +/// +/// @brief Generate secret key for cyclic rainbow. +/// +/// @param[out] sk - the secret key. +/// @param[in] pk_seed - seed for generating parts of the pbulic key. +/// @param[in] sk_seed - seed for generating the secret key. +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_generate_secretkey_cyclic(sk_t *sk, const unsigned char *pk_seed, const unsigned char *sk_seed); + +//////////////////////////////////// + +/// +/// @brief converting formats of public keys : from cyclic version to classic key +/// +/// @param[out] pk - the classic public key. +/// @param[in] cpk - the cyclic public key. +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_cpk_to_pk(pk_t *pk, const cpk_t *cpk); + +#endif // _RAINBOW_KEYPAIR_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/rainbow_keypair_computation.c b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/rainbow_keypair_computation.c new file mode 100644 index 0000000000..ab7756b380 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/rainbow_keypair_computation.c @@ -0,0 +1,213 @@ +/// @file rainbow_keypair_computation.c +/// @brief Implementations for functions in rainbow_keypair_computation.h +/// + +#include "rainbow_keypair_computation.h" +#include "blas.h" +#include "blas_comm.h" +#include "rainbow_blas.h" +#include "rainbow_keypair.h" +#include +#include +#include + +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_extcpk_to_pk(pk_t *pk, const ext_cpk_t *cpk) { + const unsigned char *idx_l1 = cpk->l1_Q1; + const unsigned char *idx_l2 = cpk->l2_Q1; + for (unsigned int i = 0; i < _V1; i++) { + for (unsigned int j = i; j < _V1; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q2; + idx_l2 = cpk->l2_Q2; + for (unsigned int i = 0; i < _V1; i++) { + for (unsigned int j = _V1; j < _V1 + _O1; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q3; + idx_l2 = cpk->l2_Q3; + for (unsigned int i = 0; i < _V1; i++) { + for (unsigned int j = _V1 + _O1; j < _PUB_N; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q5; + idx_l2 = cpk->l2_Q5; + for (unsigned int i = _V1; i < _V1 + _O1; i++) { + for (unsigned int j = i; j < _V1 + _O1; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q6; + idx_l2 = cpk->l2_Q6; + for (unsigned int i = _V1; i < _V1 + _O1; i++) { + for (unsigned int j = _V1 + _O1; j < _PUB_N; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q9; + idx_l2 = cpk->l2_Q9; + for (unsigned int i = _V1 + _O1; i < _PUB_N; i++) { + for (unsigned int j = i; j < _PUB_N; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } +} + +static void calculate_F_from_Q_ref(sk_t *Fs, const sk_t *Qs, sk_t *Ts) { + // Layer 1 + // F_sk.l1_F1s[i] = Q_pk.l1_F1s[i] + memcpy(Fs->l1_F1, Qs->l1_F1, _O1_BYTE * N_TRIANGLE_TERMS(_V1)); + + // F_sk.l1_F2s[i] = ( Q_pk.l1_F1s[i] + Q_pk.l1_F1s[i].transpose() ) * T_sk.t1 + Q_pk.l1_F2s[i] + memcpy(Fs->l1_F2, Qs->l1_F2, _O1_BYTE * _V1 * _O1); + batch_2trimat_madd(Fs->l1_F2, Qs->l1_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O1_BYTE); + + /* + Layer 2 + computations: + + F_sk.l2_F1s[i] = Q_pk.l2_F1s[i] + + Q1_T1 = Q_pk.l2_F1s[i]*T_sk.t1 + F_sk.l2_F2s[i] = Q1_T1 + Q_pk.l2_F2s[i] + Q_pk.l2_F1s[i].transpose() * T_sk.t1 + F_sk.l2_F5s[i] = UT( t1_tr* ( Q1_T1 + Q_pk.l2_F2s[i] ) ) + Q_pk.l2_F5s[i] + + Q1_Q1T_T4 = (Q_pk.l2_F1s[i] + Q_pk.l2_F1s[i].transpose()) * t4 + #Q1_Q1T_T4 = Q1_Q1T * t4 + Q2_T3 = Q_pk.l2_F2s[i]*T_sk.t3 + F_sk.l2_F3s[i] = Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] + F_sk.l2_F6s[i] = t1_tr * ( Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] ) + + Q_pk.l2_F2s[i].transpose() * t4 + + (Q_pk.l2_F5s[i] + Q_pk.l2_F5s[i].transpose())*T_sk.t3 + Q_pk.l2_F6s[i] + + */ + memcpy(Fs->l2_F1, Qs->l2_F1, _O2_BYTE * N_TRIANGLE_TERMS(_V1)); // F_sk.l2_F1s[i] = Q_pk.l2_F1s[i] + + // F_sk.l2_F2s[i] = Q1_T1 + Q_pk.l2_F2s[i] + Q_pk.l2_F1s[i].transpose() * T_sk.t1 + // F_sk.l2_F5s[i] = UT( t1_tr* ( Q1_T1 + Q_pk.l2_F2s[i] ) ) + Q_pk.l2_F5s[i] + memcpy(Fs->l2_F2, Qs->l2_F2, _O2_BYTE * _V1 * _O1); + batch_trimat_madd(Fs->l2_F2, Qs->l2_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O2_BYTE); // Q1_T1+ Q2 + + unsigned char tempQ[_O1 * _O1 * _O2_BYTE + 32]; + memset(tempQ, 0, _O1 * _O1 * _O2_BYTE); + batch_matTr_madd(tempQ, Ts->t1, _V1, _V1_BYTE, _O1, Fs->l2_F2, _O1, _O2_BYTE); // t1_tr*(Q1_T1+Q2) + memcpy(Fs->l2_F5, Qs->l2_F5, _O2_BYTE * N_TRIANGLE_TERMS(_O1)); // F5 + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_UpperTrianglize(Fs->l2_F5, tempQ, _O1, _O2_BYTE); // UT( ... ) + + batch_trimatTr_madd(Fs->l2_F2, Qs->l2_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O2_BYTE); // F2 = Q1_T1 + Q2 + Q1^tr*t1 + + // Q1_Q1T_T4 = (Q_pk.l2_F1s[i] + Q_pk.l2_F1s[i].transpose()) * t4 + // Q2_T3 = Q_pk.l2_F2s[i]*T_sk.t3 + // F_sk.l2_F3s[i] = Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] + memcpy(Fs->l2_F3, Qs->l2_F3, _V1 * _O2 * _O2_BYTE); + batch_2trimat_madd(Fs->l2_F3, Qs->l2_F1, Ts->t4, _V1, _V1_BYTE, _O2, _O2_BYTE); // Q1_Q1T_T4 + batch_mat_madd(Fs->l2_F3, Qs->l2_F2, _V1, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // Q2_T3 + + // F_sk.l2_F6s[i] = t1_tr * ( Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] ) + // + Q_pk.l2_F2s[i].transpose() * t4 + // + (Q_pk.l2_F5s[i] + Q_pk.l2_F5s[i].transpose())*T_sk.t3 + Q_pk.l2_F6s[i] + memcpy(Fs->l2_F6, Qs->l2_F6, _O1 * _O2 * _O2_BYTE); + batch_matTr_madd(Fs->l2_F6, Ts->t1, _V1, _V1_BYTE, _O1, Fs->l2_F3, _O2, _O2_BYTE); // t1_tr * ( Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] ) + batch_2trimat_madd(Fs->l2_F6, Qs->l2_F5, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // (Q_pk.l2_F5s[i] + Q_pk.l2_F5s[i].transpose())*T_sk.t3 + batch_bmatTr_madd(Fs->l2_F6, Qs->l2_F2, _O1, Ts->t4, _V1, _V1_BYTE, _O2, _O2_BYTE); +} + +static void calculate_Q_from_F_cyclic_ref(cpk_t *Qs, const sk_t *Fs, const sk_t *Ts) { + // Layer 1: Computing Q5, Q3, Q6, Q9 + + // Q_pk.l1_F5s[i] = UT( T1tr* (F1 * T1 + F2) ) + const unsigned char *t2 = Ts->t4; + sk_t tempQ; + memcpy(tempQ.l1_F2, Fs->l1_F2, _O1_BYTE * _V1 * _O1); + batch_trimat_madd(tempQ.l1_F2, Fs->l1_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O1_BYTE); // F1*T1 + F2 + memset(tempQ.l2_F1, 0, sizeof(tempQ.l2_F1)); + memset(tempQ.l2_F2, 0, sizeof(tempQ.l2_F2)); + batch_matTr_madd(tempQ.l2_F1, Ts->t1, _V1, _V1_BYTE, _O1, tempQ.l1_F2, _O1, _O1_BYTE); // T1tr*(F1*T1 + F2) + memset(Qs->l1_Q5, 0, _O1_BYTE * N_TRIANGLE_TERMS(_O1)); + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_UpperTrianglize(Qs->l1_Q5, tempQ.l2_F1, _O1, _O1_BYTE); // UT( ... ) // Q5 + + /* + F1_T2 = F1 * t2 + F2_T3 = F2 * t3 + F1_F1T_T2 + F2_T3 = F1_T2 + F2_T3 + F1tr * t2 + Q_pk.l1_F3s[i] = F1_F1T_T2 + F2_T3 + Q_pk.l1_F6s[i] = T1tr* ( F1_F1T_T2 + F2_T3 ) + F2tr * t2 + Q_pk.l1_F9s[i] = UT( T2tr* ( F1_T2 + F2_T3 ) ) + */ + memset(Qs->l1_Q3, 0, _O1_BYTE * _V1 * _O2); + memset(Qs->l1_Q6, 0, _O1_BYTE * _O1 * _O2); + memset(Qs->l1_Q9, 0, _O1_BYTE * N_TRIANGLE_TERMS(_O2)); + + batch_trimat_madd(Qs->l1_Q3, Fs->l1_F1, t2, _V1, _V1_BYTE, _O2, _O1_BYTE); // F1*T2 + batch_mat_madd(Qs->l1_Q3, Fs->l1_F2, _V1, Ts->t3, _O1, _O1_BYTE, _O2, _O1_BYTE); // F1_T2 + F2_T3 + + memset(tempQ.l1_F2, 0, _O1_BYTE * _V1 * _O2); // should be F3. assuming: _O1 >= _O2 + batch_matTr_madd(tempQ.l1_F2, t2, _V1, _V1_BYTE, _O2, Qs->l1_Q3, _O2, _O1_BYTE); // T2tr * ( F1_T2 + F2_T3 ) + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_UpperTrianglize(Qs->l1_Q9, tempQ.l1_F2, _O2, _O1_BYTE); // Q9 + + batch_trimatTr_madd(Qs->l1_Q3, Fs->l1_F1, t2, _V1, _V1_BYTE, _O2, _O1_BYTE); // F1_F1T_T2 + F2_T3 // Q3 + + batch_bmatTr_madd(Qs->l1_Q6, Fs->l1_F2, _O1, t2, _V1, _V1_BYTE, _O2, _O1_BYTE); // F2tr*T2 + batch_matTr_madd(Qs->l1_Q6, Ts->t1, _V1, _V1_BYTE, _O1, Qs->l1_Q3, _O2, _O1_BYTE); // Q6 + /* + Layer 2 + Computing Q9: + + F1_T2 = F1 * t2 + F2_T3 = F2 * t3 + Q9 = UT( T2tr*( F1*T2 + F2*T3 + F3 ) + T3tr*( F5*T3 + F6 ) ) + */ + sk_t tempQ2; + memcpy(tempQ2.l2_F3, Fs->l2_F3, _O2_BYTE * _V1 * _O2); /// F3 actually. + batch_trimat_madd(tempQ2.l2_F3, Fs->l2_F1, t2, _V1, _V1_BYTE, _O2, _O2_BYTE); // F1*T2 + F3 + batch_mat_madd(tempQ2.l2_F3, Fs->l2_F2, _V1, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // F1_T2 + F2_T3 + F3 + + memset(tempQ.l2_F3, 0, _O2_BYTE * _V1 * _O2); + batch_matTr_madd(tempQ.l2_F3, t2, _V1, _V1_BYTE, _O2, tempQ2.l2_F3, _O2, _O2_BYTE); // T2tr * ( ..... ) + + memcpy(tempQ.l2_F6, Fs->l2_F6, _O2_BYTE * _O1 * _O2); + batch_trimat_madd(tempQ.l2_F6, Fs->l2_F5, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // F5*T3 + F6 + + batch_matTr_madd(tempQ.l2_F3, Ts->t3, _O1, _O1_BYTE, _O2, tempQ.l2_F6, _O2, _O2_BYTE); // T2tr*( ..... ) + T3tr*( ..... ) + memset(Qs->l2_Q9, 0, _O2_BYTE * N_TRIANGLE_TERMS(_O2)); + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_UpperTrianglize(Qs->l2_Q9, tempQ.l2_F3, _O2, _O2_BYTE); // Q9 +} + +// Choosing implementations depends on the macros: _BLAS_SSE_ and _BLAS_AVX2_ +#define calculate_F_from_Q_impl calculate_F_from_Q_ref +#define calculate_Q_from_F_cyclic_impl calculate_Q_from_F_cyclic_ref + +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_calculate_F_from_Q(sk_t *Fs, const sk_t *Qs, sk_t *Ts) { + calculate_F_from_Q_impl(Fs, Qs, Ts); +} + +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_calculate_Q_from_F_cyclic(cpk_t *Qs, const sk_t *Fs, const sk_t *Ts) { + calculate_Q_from_F_cyclic_impl(Qs, Fs, Ts); +} diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/rainbow_keypair_computation.h b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/rainbow_keypair_computation.h new file mode 100644 index 0000000000..3af7563af3 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/rainbow_keypair_computation.h @@ -0,0 +1,71 @@ +#ifndef _RAINBOW_KEYPAIR_COMP_H_ +#define _RAINBOW_KEYPAIR_COMP_H_ +/// @file rainbow_keypair_computation.h +/// @brief Functions for calculating pk/sk while generating keys. +/// +/// Defining an internal structure of public key. +/// Functions for calculating pk/sk for key generation. +/// + +#include "rainbow_keypair.h" + +/// @brief The (internal use) public key for rainbow +/// +/// The (internal use) public key for rainbow. The public +/// polynomials are divided into l1_Q1, l1_Q2, ... l1_Q9, +/// l2_Q1, .... , l2_Q9. +/// +typedef struct rainbow_extend_publickey { + unsigned char l1_Q1[_O1_BYTE * N_TRIANGLE_TERMS(_V1)]; + unsigned char l1_Q2[_O1_BYTE * _V1 * _O1]; + unsigned char l1_Q3[_O1_BYTE * _V1 * _O2]; + unsigned char l1_Q5[_O1_BYTE * N_TRIANGLE_TERMS(_O1)]; + unsigned char l1_Q6[_O1_BYTE * _O1 * _O2]; + unsigned char l1_Q9[_O1_BYTE * N_TRIANGLE_TERMS(_O2)]; + + unsigned char l2_Q1[_O2_BYTE * N_TRIANGLE_TERMS(_V1)]; + unsigned char l2_Q2[_O2_BYTE * _V1 * _O1]; + unsigned char l2_Q3[_O2_BYTE * _V1 * _O2]; + unsigned char l2_Q5[_O2_BYTE * N_TRIANGLE_TERMS(_O1)]; + unsigned char l2_Q6[_O2_BYTE * _O1 * _O2]; + unsigned char l2_Q9[_O2_BYTE * N_TRIANGLE_TERMS(_O2)]; +} ext_cpk_t; + +/// +/// @brief converting formats of public keys : from ext_cpk_t version to pk_t +/// +/// @param[out] pk - the classic public key. +/// @param[in] cpk - the internel public key. +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_extcpk_to_pk(pk_t *pk, const ext_cpk_t *cpk); +///////////////////////////////////////////////// + +/// +/// @brief Computing public key from secret key +/// +/// @param[out] Qs - the public key +/// @param[in] Fs - parts of the secret key: l1_F1, l1_F2, l2_F1, l2_F2, l2_F3, l2_F5, l2_F6 +/// @param[in] Ts - parts of the secret key: T1, T4, T3 +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_calculate_Q_from_F(ext_cpk_t *Qs, const sk_t *Fs, const sk_t *Ts); + + +/// +/// @brief Computing parts of the sk from parts of pk and sk +/// +/// @param[out] Fs - parts of the sk: l1_F1, l1_F2, l2_F1, l2_F2, l2_F3, l2_F5, l2_F6 +/// @param[in] Qs - parts of the pk: l1_Q1, l1_Q2, l2_Q1, l2_Q2, l2_Q3, l2_Q5, l2_Q6 +/// @param[in] Ts - parts of the sk: T1, T4, T3 +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_calculate_F_from_Q(sk_t *Fs, const sk_t *Qs, sk_t *Ts); + +/// +/// @brief Computing parts of the pk from the secret key +/// +/// @param[out] Qs - parts of the pk: l1_Q3, l1_Q5, l2_Q6, l1_Q9, l2_Q9 +/// @param[in] Fs - parts of the sk: l1_F1, l1_F2, l2_F1, l2_F2, l2_F3, l2_F5, l2_F6 +/// @param[in] Ts - parts of the sk: T1, T4, T3 +/// +void PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_calculate_Q_from_F_cyclic(cpk_t *Qs, const sk_t *Fs, const sk_t *Ts); + +#endif // _RAINBOW_KEYPAIR_COMP_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/sign.c b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/sign.c new file mode 100644 index 0000000000..3dc5694fed --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/sign.c @@ -0,0 +1,76 @@ +/// @file sign.c +/// @brief the implementations for functions in api.h +/// +/// + +#include "api.h" +#include "rainbow.h" +#include "rainbow_config.h" +#include "rainbow_keypair.h" +#include "randombytes.h" +#include "utils_hash.h" +#include +#include + +int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { + unsigned char sk_seed[LEN_SKSEED] = {0}; + randombytes(sk_seed, LEN_SKSEED); + + unsigned char pk_seed[LEN_PKSEED] = {0}; + randombytes(pk_seed, LEN_PKSEED); + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_generate_compact_keypair_cyclic((cpk_t *)pk, (csk_t *)sk, pk_seed, sk_seed); + return 0; +} + +int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { + unsigned char digest[_HASH_LEN]; + + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_hash_msg(digest, _HASH_LEN, m, mlen); + + memcpy(sm, m, mlen); + smlen[0] = mlen + _SIGNATURE_BYTE; + + return PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_rainbow_sign_cyclic(sm + mlen, (const csk_t *)sk, digest); +} + +int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { + int rc; + if (_SIGNATURE_BYTE > smlen) { + rc = -1; + } else { + *mlen = smlen - _SIGNATURE_BYTE; + + unsigned char digest[_HASH_LEN]; + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_hash_msg(digest, _HASH_LEN, sm, *mlen); + + rc = PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_rainbow_verify_cyclic(digest, sm + mlen[0], (const cpk_t *)pk); + } + if (!rc) { + memmove(m, sm, smlen - _SIGNATURE_BYTE); + } else { // bad signature + *mlen = (size_t) -1; + memset(m, 0, smlen); + } + return rc; +} + +int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_crypto_sign_signature( + uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + unsigned char digest[_HASH_LEN]; + + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_hash_msg(digest, _HASH_LEN, m, mlen); + *siglen = _SIGNATURE_BYTE; + return PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_rainbow_sign_cyclic(sig, (const csk_t *)sk, digest); +} + +int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_crypto_sign_verify( + const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + if (siglen != _SIGNATURE_BYTE) { + return -1; + } + unsigned char digest[_HASH_LEN]; + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_hash_msg(digest, _HASH_LEN, m, mlen); + return PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_rainbow_verify_cyclic(digest, sig, (const cpk_t *)pk); +} diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/utils_hash.c b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/utils_hash.c new file mode 100644 index 0000000000..3cec997702 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/utils_hash.c @@ -0,0 +1,50 @@ +/// @file utils_hash.c +/// @brief the adapter for SHA2 families. +/// +/// + +#include "utils_hash.h" +#include "rainbow_config.h" +#include "sha2.h" + +static inline int _hash(unsigned char *digest, const unsigned char *m, size_t mlen) { + sha256(digest, m, mlen); + return 0; +} + +static inline int expand_hash(unsigned char *digest, size_t n_digest, const unsigned char *hash) { + if (_HASH_LEN >= n_digest) { + for (size_t i = 0; i < n_digest; i++) { + digest[i] = hash[i]; + } + return 0; + } + for (size_t i = 0; i < _HASH_LEN; i++) { + digest[i] = hash[i]; + } + n_digest -= _HASH_LEN; + + while (_HASH_LEN <= n_digest) { + _hash(digest + _HASH_LEN, digest, _HASH_LEN); + + n_digest -= _HASH_LEN; + digest += _HASH_LEN; + } + unsigned char temp[_HASH_LEN]; + if (n_digest) { + _hash(temp, digest, _HASH_LEN); + for (size_t i = 0; i < n_digest; i++) { + digest[_HASH_LEN + i] = temp[i]; + } + } + return 0; +} + +int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_hash_msg(unsigned char *digest, + size_t len_digest, + const unsigned char *m, + size_t mlen) { + unsigned char buf[_HASH_LEN]; + _hash(buf, m, mlen); + return expand_hash(digest, len_digest, buf); +} diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/utils_hash.h b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/utils_hash.h new file mode 100644 index 0000000000..2e7fde2802 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/utils_hash.h @@ -0,0 +1,11 @@ +#ifndef _UTILS_HASH_H_ +#define _UTILS_HASH_H_ +/// @file utils_hash.h +/// @brief the interface for adapting hash functions. +/// + +#include + +int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_hash_msg(unsigned char *digest, size_t len_digest, const unsigned char *m, size_t mlen); + +#endif // _UTILS_HASH_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/utils_prng.c b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/utils_prng.c new file mode 100644 index 0000000000..54132ee019 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/utils_prng.c @@ -0,0 +1,97 @@ +/// @file utils_prng.c +/// @brief The implementation of PRNG related functions. +/// + +#include "utils_prng.h" +#include "aes.h" +#include "randombytes.h" +#include "utils_hash.h" +#include +#include + +static void prng_update(const unsigned char *provided_data, + unsigned char *Key, + unsigned char *V) { + unsigned char temp[48]; + aes256ctx ctx; + aes256_keyexp(&ctx, Key); + for (int i = 0; i < 3; i++) { + //increment V + for (int j = 15; j >= 0; j--) { + if (V[j] == 0xff) { + V[j] = 0x00; + } else { + V[j]++; + break; + } + } + aes256_ecb(temp + 16 * i, V, 1, &ctx); + } + if (provided_data != NULL) { + for (int i = 0; i < 48; i++) { + temp[i] ^= provided_data[i]; + } + } + aes256_ctx_release(&ctx); + memcpy(Key, temp, 32); + memcpy(V, temp + 32, 16); +} +static void randombytes_init_with_state(prng_t *state, + unsigned char *entropy_input_48bytes) { + memset(state->Key, 0x00, 32); + memset(state->V, 0x00, 16); + prng_update(entropy_input_48bytes, state->Key, state->V); +} + +static int randombytes_with_state(prng_t *state, + unsigned char *x, + size_t xlen) { + + unsigned char block[16]; + int i = 0; + + aes256ctx ctx; + aes256_keyexp(&ctx, state->Key); + + while (xlen > 0) { + //increment V + for (int j = 15; j >= 0; j--) { + if (state->V[j] == 0xff) { + state->V[j] = 0x00; + } else { + state->V[j]++; + break; + } + } + aes256_ecb(block, state->V, 1, &ctx); + if (xlen > 15) { + memcpy(x + i, block, 16); + i += 16; + xlen -= 16; + } else { + memcpy(x + i, block, xlen); + xlen = 0; + } + } + aes256_ctx_release(&ctx); + prng_update(NULL, state->Key, state->V); + return 0; +} + +int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_prng_set(prng_t *ctx, const void *prng_seed, unsigned long prng_seedlen) { + unsigned char seed[48]; + if (prng_seedlen >= 48) { + memcpy(seed, prng_seed, 48); + } else { + memcpy(seed, prng_seed, prng_seedlen); + PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_hash_msg(seed + prng_seedlen, 48 - (unsigned)prng_seedlen, (const unsigned char *)prng_seed, prng_seedlen); + } + + randombytes_init_with_state(ctx, seed); + + return 0; +} + +int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_prng_gen(prng_t *ctx, unsigned char *out, unsigned long outlen) { + return randombytes_with_state(ctx, out, outlen); +} diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/utils_prng.h b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/utils_prng.h new file mode 100644 index 0000000000..ab9ea9ea3e --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic-compressed_clean/utils_prng.h @@ -0,0 +1,18 @@ +#ifndef _UTILS_PRNG_H_ +#define _UTILS_PRNG_H_ +/// @file utils_prng.h +/// @brief the interface for adapting PRNG functions. +/// +/// + +#include "randombytes.h" + +typedef struct { + unsigned char Key[32]; + unsigned char V[16]; +} prng_t; + +int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_prng_set(prng_t *ctx, const void *prng_seed, unsigned long prng_seedlen); +int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_prng_gen(prng_t *ctx, unsigned char *out, unsigned long outlen); + +#endif // _UTILS_PRNG_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/LICENSE b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/LICENSE new file mode 100644 index 0000000000..cb00a6e354 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/LICENSE @@ -0,0 +1,8 @@ +`Software implementation of Rainbow for NIST R2 submission' by Ming-Shing Chen + +To the extent possible under law, the person who associated CC0 with +`Software implementation of Rainbow for NIST R2 submission' has waived all copyright and related or neighboring rights +to `Software implementation of Rainbow for NIST R2 submission'. + +You should have received a copy of the CC0 legalcode along with this +work. If not, see . diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/api.h b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/api.h new file mode 100644 index 0000000000..a37bb95259 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/api.h @@ -0,0 +1,32 @@ +#ifndef PQCLEAN_RAINBOWIACYCLIC_CLEAN_API_H +#define PQCLEAN_RAINBOWIACYCLIC_CLEAN_API_H + +#include +#include + +#define PQCLEAN_RAINBOWIACYCLIC_CLEAN_CRYPTO_SECRETKEYBYTES 92960 +#define PQCLEAN_RAINBOWIACYCLIC_CLEAN_CRYPTO_PUBLICKEYBYTES 58144 +#define PQCLEAN_RAINBOWIACYCLIC_CLEAN_CRYPTO_BYTES 64 +#define PQCLEAN_RAINBOWIACYCLIC_CLEAN_CRYPTO_ALGNAME "RAINBOW(16,32,32,32) - cyclic" + +int PQCLEAN_RAINBOWIACYCLIC_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + + +int PQCLEAN_RAINBOWIACYCLIC_CLEAN_crypto_sign_signature( + uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +int PQCLEAN_RAINBOWIACYCLIC_CLEAN_crypto_sign_verify( + const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +int PQCLEAN_RAINBOWIACYCLIC_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +int PQCLEAN_RAINBOWIACYCLIC_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + + +#endif diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/blas.c b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/blas.c new file mode 100644 index 0000000000..4f67082844 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/blas.c @@ -0,0 +1,43 @@ +#include "blas.h" +#include "gf.h" + +#include + +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_predicated_add(uint8_t *accu_b, uint8_t predicate, const uint8_t *a, size_t _num_byte) { + uint8_t pr_u8 = (uint8_t) ((uint8_t) 0 - predicate); + for (size_t i = 0; i < _num_byte; i++) { + accu_b[i] ^= (a[i] & pr_u8); + } +} + +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_add(uint8_t *accu_b, const uint8_t *a, size_t _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + accu_b[i] ^= a[i]; + } +} + + +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_mul_scalar(uint8_t *a, uint8_t gf16_b, size_t _num_byte) { + uint8_t tmp; + for (size_t i = 0; i < _num_byte; i++) { + tmp = PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16_mul(a[i] & 0xF, gf16_b); + tmp |= (uint8_t) (PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16_mul(a[i] >> 4, gf16_b) << 4); + a[i] = tmp; + } +} + +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_madd(uint8_t *accu_c, const uint8_t *a, uint8_t gf16_b, size_t _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + accu_c[i] ^= PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16_mul(a[i] & 0xF, gf16_b); + accu_c[i] ^= (uint8_t) (PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16_mul(a[i] >> 4, gf16_b) << 4); + } +} + +uint8_t PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_dot(const uint8_t *a, const uint8_t *b, size_t _num_byte) { + uint8_t r = 0; + for (size_t i = 0; i < _num_byte; i++) { + r ^= PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16_mul(a[i], b[i]); + } + return r; +} + diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/blas.h b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/blas.h new file mode 100644 index 0000000000..0c16213e54 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/blas.h @@ -0,0 +1,20 @@ +#ifndef _BLAS_H_ +#define _BLAS_H_ +/// @file blas.h +/// @brief Functions for implementing basic linear algebra functions. +/// + +#include "rainbow_config.h" +#include +#include + +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_predicated_add(uint8_t *accu_b, uint8_t predicate, const uint8_t *a, size_t _num_byte); +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_add(uint8_t *accu_b, const uint8_t *a, size_t _num_byte); + + +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_madd(uint8_t *accu_c, const uint8_t *a, uint8_t gf16_b, size_t _num_byte); +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_mul_scalar(uint8_t *a, uint8_t gf16_b, size_t _num_byte); +uint8_t PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_dot(const uint8_t *a, const uint8_t *b, size_t _num_byte); + + +#endif // _BLAS_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/blas_comm.c b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/blas_comm.c new file mode 100644 index 0000000000..49a6f6304d --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/blas_comm.c @@ -0,0 +1,152 @@ +/// @file blas_comm.c +/// @brief The standard implementations for blas_comm.h +/// + +#include "blas_comm.h" +#include "blas.h" +#include "gf.h" +#include "rainbow_config.h" + +#include +#include + +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_set_zero(uint8_t *b, unsigned int _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + b[i] = 0; + } +} + +/// @brief get an element from GF(16) vector . +/// +/// @param[in] a - the input vector a. +/// @param[in] i - the index in the vector a. +/// @return the value of the element. +/// +uint8_t PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_get_ele(const uint8_t *a, unsigned int i) { + uint8_t r = a[i >> 1]; + uint8_t r0 = r & 0xf; + uint8_t r1 = r >> 4; + uint8_t m = (uint8_t)(-((int8_t)i & 1)); + return (uint8_t)((r1 & m) | ((~m) & r0)); +} + +/// @brief set an element for a GF(16) vector . +/// +/// @param[in,out] a - the vector a. +/// @param[in] i - the index in the vector a. +/// @param[in] v - the value for the i-th element in vector a. +/// @return the value of the element. +/// +static uint8_t PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_set_ele(uint8_t *a, unsigned int i, uint8_t v) { + uint8_t m = (uint8_t)(0xf ^ (-((int8_t)i & 1))); /// 1--> 0xf0 , 0--> 0x0f + uint8_t ai_remaining = (uint8_t)(a[i >> 1] & (~m)); /// erase + a[i >> 1] = (uint8_t)(ai_remaining | (m & (v << 4)) | (m & v & 0xf)); /// set + return v; +} + +static void gf16mat_prod_ref(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b) { + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_set_zero(c, n_A_vec_byte); + for (unsigned int i = 0; i < n_A_width; i++) { + uint8_t bb = PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_get_ele(b, i); + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_madd(c, matA, bb, n_A_vec_byte); + matA += n_A_vec_byte; + } +} + +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16mat_mul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int len_vec) { + unsigned int n_vec_byte = (len_vec + 1) / 2; + for (unsigned int k = 0; k < len_vec; k++) { + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_set_zero(c, n_vec_byte); + const uint8_t *bk = b + n_vec_byte * k; + for (unsigned int i = 0; i < len_vec; i++) { + uint8_t bb = PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_get_ele(bk, i); + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_madd(c, a + n_vec_byte * i, bb, n_vec_byte); + } + c += n_vec_byte; + } +} + +static unsigned int gf16mat_gauss_elim_ref(uint8_t *mat, unsigned int h, unsigned int w) { + unsigned int n_w_byte = (w + 1) / 2; + unsigned int r8 = 1; + for (unsigned int i = 0; i < h; i++) { + unsigned int offset_byte = i >> 1; + uint8_t *ai = mat + n_w_byte * i; + for (unsigned int j = i + 1; j < h; j++) { + uint8_t *aj = mat + n_w_byte * j; + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_predicated_add(ai + offset_byte, !PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16_is_nonzero(PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_get_ele(ai, i)), aj + offset_byte, n_w_byte - offset_byte); + } + uint8_t pivot = PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_get_ele(ai, i); + r8 &= PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16_is_nonzero(pivot); + pivot = PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16_inv(pivot); + offset_byte = (i + 1) >> 1; + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_mul_scalar(ai + offset_byte, pivot, n_w_byte - offset_byte); + for (unsigned int j = 0; j < h; j++) { + if (i == j) { + continue; + } + uint8_t *aj = mat + n_w_byte * j; + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_madd(aj + offset_byte, ai + offset_byte, PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_get_ele(aj, i), n_w_byte - offset_byte); + } + } + return r8; +} + +static unsigned int gf16mat_solve_linear_eq_ref(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n) { + uint8_t mat[64 * 33]; + unsigned int n_byte = (n + 1) >> 1; + for (unsigned int i = 0; i < n; i++) { + memcpy(mat + i * (n_byte + 1), inp_mat + i * n_byte, n_byte); + mat[i * (n_byte + 1) + n_byte] = PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_get_ele(c_terms, i); + } + unsigned int r8 = PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16mat_gauss_elim(mat, n, n + 2); + for (unsigned int i = 0; i < n; i++) { + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_set_ele(sol, i, mat[i * (n_byte + 1) + n_byte]); + } + return r8; +} + +static inline void gf16mat_submat(uint8_t *mat2, unsigned int w2, unsigned int st, const uint8_t *mat, unsigned int w, unsigned int h) { + unsigned int n_byte_w1 = (w + 1) / 2; + unsigned int n_byte_w2 = (w2 + 1) / 2; + unsigned int st_2 = st / 2; + for (unsigned int i = 0; i < h; i++) { + for (unsigned int j = 0; j < n_byte_w2; j++) { + mat2[i * n_byte_w2 + j] = mat[i * n_byte_w1 + st_2 + j]; + } + } +} + +unsigned int PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16mat_inv(uint8_t *inv_a, const uint8_t *a, unsigned int H, uint8_t *buffer) { + unsigned int n_w_byte = (H + 1) / 2; + + uint8_t *aa = buffer; + for (unsigned int i = 0; i < H; i++) { + uint8_t *ai = aa + i * 2 * n_w_byte; + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_set_zero(ai, 2 * n_w_byte); + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_add(ai, a + i * n_w_byte, n_w_byte); + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_set_ele(ai + n_w_byte, i, 1); + } + unsigned int r8 = PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16mat_gauss_elim(aa, H, 2 * H); + gf16mat_submat(inv_a, H, H, aa, 2 * H, H); + return r8; +} + +// choosing the implementations depends on the macros _BLAS_AVX2_ and _BLAS_SSE + +#define gf16mat_prod_impl gf16mat_prod_ref +#define gf16mat_gauss_elim_impl gf16mat_gauss_elim_ref +#define gf16mat_solve_linear_eq_impl gf16mat_solve_linear_eq_ref + +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16mat_prod(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b) { + gf16mat_prod_impl(c, matA, n_A_vec_byte, n_A_width, b); +} + +unsigned int PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16mat_gauss_elim(uint8_t *mat, unsigned int h, unsigned int w) { + return gf16mat_gauss_elim_impl(mat, h, w); +} + +unsigned int PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16mat_solve_linear_eq(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n) { + return gf16mat_solve_linear_eq_impl(sol, inp_mat, c_terms, n); +} + diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/blas_comm.h b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/blas_comm.h new file mode 100644 index 0000000000..570e5ede64 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/blas_comm.h @@ -0,0 +1,74 @@ +#ifndef _BLAS_COMM_H_ +#define _BLAS_COMM_H_ +/// @file blas_comm.h +/// @brief Common functions for linear algebra. +/// + +#include "rainbow_config.h" +#include + +/// @brief set a vector to 0. +/// +/// @param[in,out] b - the vector b. +/// @param[in] _num_byte - number of bytes for the vector b. +/// +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_set_zero(uint8_t *b, unsigned int _num_byte); + +/// @brief get an element from GF(16) vector . +/// +/// @param[in] a - the input vector a. +/// @param[in] i - the index in the vector a. +/// @return the value of the element. +/// +uint8_t PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_get_ele(const uint8_t *a, unsigned int i); + +/// @brief matrix-matrix multiplication: c = a * b , in GF(16) +/// +/// @param[out] c - the output matrix c +/// @param[in] c - a matrix a. +/// @param[in] b - a matrix b. +/// @param[in] len_vec - the length of column vectors. +/// +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16mat_mul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int len_vec); + +/// @brief Gauss elimination for a matrix, in GF(16) +/// +/// @param[in,out] mat - the matrix. +/// @param[in] h - the height of the matrix. +/// @param[in] w - the width of the matrix. +/// @return 1(true) if success. 0(false) if the matrix is singular. +/// +unsigned int PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16mat_gauss_elim(uint8_t *mat, unsigned int h, unsigned int w); + +/// @brief Solving linear equations, in GF(16) +/// +/// @param[out] sol - the solutions. +/// @param[in] inp_mat - the matrix parts of input equations. +/// @param[in] c_terms - the constant terms of the input equations. +/// @param[in] n - the number of equations. +/// @return 1(true) if success. 0(false) if the matrix is singular. +/// +unsigned int PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16mat_solve_linear_eq(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n); + +/// @brief Computing the inverse matrix, in GF(16) +/// +/// @param[out] inv_a - the output of matrix a. +/// @param[in] a - a matrix a. +/// @param[in] H - height of matrix a, i.e., matrix a is an HxH matrix. +/// @param[in] buffer - The buffer for computations. it has to be as large as 2 input matrixes. +/// @return 1(true) if success. 0(false) if the matrix is singular. +/// +unsigned int PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16mat_inv(uint8_t *inv_a, const uint8_t *a, unsigned int H, uint8_t *buffer); + +/// @brief matrix-vector multiplication: c = matA * b , in GF(16) +/// +/// @param[out] c - the output vector c +/// @param[in] matA - a column-major matrix A. +/// @param[in] n_A_vec_byte - the size of column vectors in bytes. +/// @param[in] n_A_width - the width of matrix A. +/// @param[in] b - the vector b. +/// +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16mat_prod(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b); + + +#endif // _BLAS_COMM_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/gf.c b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/gf.c new file mode 100644 index 0000000000..8cc1b2b532 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/gf.c @@ -0,0 +1,54 @@ +#include "gf.h" + +//// gf4 := gf2[x]/x^2+x+1 +static inline uint8_t gf4_mul_2(uint8_t a) { + uint8_t r = (uint8_t)(a << 1); + r ^= (uint8_t)((a >> 1) * 7); + return r; +} + +static inline uint8_t gf4_mul(uint8_t a, uint8_t b) { + uint8_t r = (uint8_t)(a * (b & 1)); + return r ^ (uint8_t)(gf4_mul_2(a) * (b >> 1)); +} + +static inline uint8_t gf4_squ(uint8_t a) { + return a ^ (a >> 1); +} + +//// gf16 := gf4[y]/y^2+y+x +uint8_t PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16_mul(uint8_t a, uint8_t b) { + uint8_t a0 = a & 3; + uint8_t a1 = (a >> 2); + uint8_t b0 = b & 3; + uint8_t b1 = (b >> 2); + uint8_t a0b0 = gf4_mul(a0, b0); + uint8_t a1b1 = gf4_mul(a1, b1); + uint8_t a0b1_a1b0 = gf4_mul(a0 ^ a1, b0 ^ b1) ^ a0b0 ^ a1b1; + uint8_t a1b1_x2 = gf4_mul_2(a1b1); + return (uint8_t)((a0b1_a1b0 ^ a1b1) << 2 ^ a0b0 ^ a1b1_x2); +} + +static inline uint8_t gf16_squ(uint8_t a) { + uint8_t a0 = a & 3; + uint8_t a1 = (a >> 2); + a1 = gf4_squ(a1); + uint8_t a1squ_x2 = gf4_mul_2(a1); + return (uint8_t)((a1 << 2) ^ a1squ_x2 ^ gf4_squ(a0)); +} + +uint8_t PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16_is_nonzero(uint8_t a) { + unsigned int a4 = a & 0xf; + unsigned int r = ((unsigned int)0) - a4; + r >>= 4; + return r & 1; +} + +uint8_t PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16_inv(uint8_t a) { + uint8_t a2 = gf16_squ(a); + uint8_t a4 = gf16_squ(a2); + uint8_t a8 = gf16_squ(a4); + uint8_t a6 = PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16_mul(a4, a2); + return PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16_mul(a8, a6); +} + diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/gf.h b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/gf.h new file mode 100644 index 0000000000..c26bfee6f0 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/gf.h @@ -0,0 +1,18 @@ +#ifndef _GF16_H_ +#define _GF16_H_ + +#include "rainbow_config.h" +#include + +/// @file gf16.h +/// @brief Library for arithmetics in GF(16) and GF(256) +/// + +uint8_t PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16_mul(uint8_t a, uint8_t b); + + +uint8_t PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16_is_nonzero(uint8_t a); +uint8_t PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16_inv(uint8_t a); + + +#endif // _GF16_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/parallel_matrix_op.c b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/parallel_matrix_op.c new file mode 100644 index 0000000000..0abba1dcb9 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/parallel_matrix_op.c @@ -0,0 +1,182 @@ +/// @file parallel_matrix_op.c +/// @brief the standard implementations for functions in parallel_matrix_op.h +/// +/// the standard implementations for functions in parallel_matrix_op.h +/// + +#include "parallel_matrix_op.h" +#include "blas.h" +#include "blas_comm.h" + +/// +/// @brief Calculate the corresponding index in an array for an upper-triangle(UT) matrix. +/// +/// @param[in] i_row - the i-th row in an upper-triangle matrix. +/// @param[in] j_col - the j-th column in an upper-triangle matrix. +/// @param[in] dim - the dimension of the upper-triangle matrix, i.e., an dim x dim matrix. +/// @return the corresponding index in an array storage. +/// +unsigned int PQCLEAN_RAINBOWIACYCLIC_CLEAN_idx_of_trimat(unsigned int i_row, unsigned int j_col, unsigned int dim) { + return (dim + dim - i_row + 1) * i_row / 2 + j_col - i_row; +} + +/// +/// @brief Calculate the corresponding index in an array for an upper-triangle or lower-triangle matrix. +/// +/// @param[in] i_row - the i-th row in a triangle matrix. +/// @param[in] j_col - the j-th column in a triangle matrix. +/// @param[in] dim - the dimension of the triangle matrix, i.e., an dim x dim matrix. +/// @return the corresponding index in an array storage. +/// +static inline unsigned int idx_of_2trimat(unsigned int i_row, unsigned int j_col, unsigned int n_var) { + if (i_row > j_col) { + return PQCLEAN_RAINBOWIACYCLIC_CLEAN_idx_of_trimat(j_col, i_row, n_var); + } + return PQCLEAN_RAINBOWIACYCLIC_CLEAN_idx_of_trimat(i_row, j_col, n_var); +} + +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_UpperTrianglize(unsigned char *btriC, const unsigned char *bA, unsigned int Awidth, unsigned int size_batch) { + unsigned char *runningC = btriC; + unsigned int Aheight = Awidth; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < i; j++) { + unsigned int idx = PQCLEAN_RAINBOWIACYCLIC_CLEAN_idx_of_trimat(j, i, Aheight); + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_add(btriC + idx * size_batch, bA + size_batch * (i * Awidth + j), size_batch); + } + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_add(runningC, bA + size_batch * (i * Awidth + i), size_batch * (Aheight - i)); + runningC += size_batch * (Aheight - i); + } +} + +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_trimat_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Awidth = Bheight; + unsigned int Aheight = Awidth; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + if (k < i) { + continue; + } + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_madd(bC, &btriA[(k - i) * size_batch], PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + btriA += (Aheight - i) * size_batch; + } +} + +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_trimatTr_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Aheight = Bheight; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + if (i < k) { + continue; + } + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_madd(bC, &btriA[size_batch * (PQCLEAN_RAINBOWIACYCLIC_CLEAN_idx_of_trimat(k, i, Aheight))], PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_2trimat_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Aheight = Bheight; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + if (i == k) { + continue; + } + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_madd(bC, &btriA[size_batch * (idx_of_2trimat(i, k, Aheight))], PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_matTr_madd_gf16(unsigned char *bC, const unsigned char *A_to_tr, unsigned int Aheight, unsigned int size_Acolvec, unsigned int Awidth, + const unsigned char *bB, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Atr_height = Awidth; + unsigned int Atr_width = Aheight; + for (unsigned int i = 0; i < Atr_height; i++) { + for (unsigned int j = 0; j < Atr_width; j++) { + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_madd(bC, &bB[j * Bwidth * size_batch], PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_get_ele(&A_to_tr[size_Acolvec * i], j), size_batch * Bwidth); + } + bC += size_batch * Bwidth; + } +} + +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_bmatTr_madd_gf16(unsigned char *bC, const unsigned char *bA_to_tr, unsigned int Awidth_before_tr, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + const unsigned char *bA = bA_to_tr; + unsigned int Aheight = Awidth_before_tr; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_madd(bC, &bA[size_batch * (i + k * Aheight)], PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_mat_madd_gf16(unsigned char *bC, const unsigned char *bA, unsigned int Aheight, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Awidth = Bheight; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_madd(bC, &bA[k * size_batch], PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + bA += (Awidth) * size_batch; + } +} + +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_quad_recmat_eval_gf16(unsigned char *z, const unsigned char *y, unsigned int dim_y, const unsigned char *mat, + const unsigned char *x, unsigned int dim_x, unsigned int size_batch) { + unsigned char tmp[128]; + + unsigned char _x[128]; + for (unsigned int i = 0; i < dim_x; i++) { + _x[i] = PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_get_ele(x, i); + } + unsigned char _y[128]; + for (unsigned int i = 0; i < dim_y; i++) { + _y[i] = PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_get_ele(y, i); + } + + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_set_zero(z, size_batch); + for (unsigned int i = 0; i < dim_y; i++) { + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_set_zero(tmp, size_batch); + for (unsigned int j = 0; j < dim_x; j++) { + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_madd(tmp, mat, _x[j], size_batch); + mat += size_batch; + } + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_madd(z, tmp, _y[i], size_batch); + } +} + +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_quad_trimat_eval_gf16(unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned int dim, unsigned int size_batch) { + unsigned char tmp[256]; + + unsigned char _x[256]; + for (unsigned int i = 0; i < dim; i++) { + _x[i] = PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_get_ele(x, i); + } + + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_set_zero(y, size_batch); + for (unsigned int i = 0; i < dim; i++) { + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_set_zero(tmp, size_batch); + for (unsigned int j = i; j < dim; j++) { + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_madd(tmp, trimat, _x[j], size_batch); + trimat += size_batch; + } + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_madd(y, tmp, _x[i], size_batch); + } +} diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/parallel_matrix_op.h b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/parallel_matrix_op.h new file mode 100644 index 0000000000..223fbeeaa1 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/parallel_matrix_op.h @@ -0,0 +1,260 @@ +#ifndef _P_MATRIX_OP_H_ +#define _P_MATRIX_OP_H_ +/// @file parallel_matrix_op.h +/// @brief Librarys for operations of batched matrixes. +/// +/// + +//////////////// Section: triangle matrix <-> rectangle matrix /////////////////////////////////// + +/// +/// @brief Calculate the corresponding index in an array for an upper-triangle(UT) matrix. +/// +/// @param[in] i_row - the i-th row in an upper-triangle matrix. +/// @param[in] j_col - the j-th column in an upper-triangle matrix. +/// @param[in] dim - the dimension of the upper-triangle matrix, i.e., an dim x dim matrix. +/// @return the corresponding index in an array storage. +/// +unsigned int PQCLEAN_RAINBOWIACYCLIC_CLEAN_idx_of_trimat(unsigned int i_row, unsigned int j_col, unsigned int dim); + +/// +/// @brief Upper trianglize a rectangle matrix to the corresponding upper-trangle matrix. +/// +/// @param[out] btriC - the batched upper-trianglized matrix C. +/// @param[in] bA - a batched retangle matrix A. +/// @param[in] bwidth - the width of the batched matrix A, i.e., A is a Awidth x Awidth matrix. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_UpperTrianglize(unsigned char *btriC, const unsigned char *bA, unsigned int Awidth, unsigned int size_batch); + +//////////////////// Section: matrix multiplications /////////////////////////////// + +/// +/// @brief bC += btriA * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_trimat_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += btriA * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += btriA^Tr * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. A will be transposed while multiplying. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_trimatTr_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += btriA^Tr * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A, which will be transposed while multiplying. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_trimatTr_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += (btriA + btriA^Tr) *B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. The operand for multiplication is (btriA + btriA^Tr). +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_2trimat_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += (btriA + btriA^Tr) *B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. The operand for multiplication is (btriA + btriA^Tr). +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_2trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += A^Tr * bB , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] A_to_tr - a column-major matrix A. The operand for multiplication is A^Tr. +/// @param[in] Aheight - the height of A. +/// @param[in] size_Acolvec - the size of a column vector in A. +/// @param[in] Awidth - the width of A. +/// @param[in] bB - a batched matrix B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_matTr_madd_gf16(unsigned char *bC, + const unsigned char *A_to_tr, unsigned int Aheight, unsigned int size_Acolvec, unsigned int Awidth, + const unsigned char *bB, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += A^Tr * bB , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] A_to_tr - a column-major matrix A. The operand for multiplication is A^Tr. +/// @param[in] Aheight - the height of A. +/// @param[in] size_Acolvec - the size of a column vector in A. +/// @param[in] Awidth - the width of A. +/// @param[in] bB - a batched matrix B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_matTr_madd_gf256(unsigned char *bC, + const unsigned char *A_to_tr, unsigned int Aheight, unsigned int size_Acolvec, unsigned int Awidth, + const unsigned char *bB, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA^Tr * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA_to_tr - a batched matrix A. The operand for multiplication is (bA^Tr). +/// @param[in] Awidth_befor_tr - the width of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_bmatTr_madd_gf16(unsigned char *bC, const unsigned char *bA_to_tr, unsigned int Awidth_before_tr, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA^Tr * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA_to_tr - a batched matrix A. The operand for multiplication is (bA^Tr). +/// @param[in] Awidth_befor_tr - the width of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_bmatTr_madd_gf256(unsigned char *bC, const unsigned char *bA_to_tr, unsigned int Awidth_before_tr, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA - a batched matrix A. +/// @param[in] Aheigh - the height of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_mat_madd_gf16(unsigned char *bC, const unsigned char *bA, unsigned int Aheight, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA - a batched matrix A. +/// @param[in] Aheigh - the height of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_mat_madd_gf256(unsigned char *bC, const unsigned char *bA, unsigned int Aheight, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +//////////////////// Section: "quadratric" matrix evaluation /////////////////////////////// + +/// +/// @brief y = x^Tr * trimat * x , in GF(16) +/// +/// @param[out] y - the returned batched element y. +/// @param[in] trimat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim - the dimension of matrix trimat (and x). +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_quad_trimat_eval_gf16(unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned int dim, unsigned int size_batch); + +/// +/// @brief y = x^Tr * trimat * x , in GF(256) +/// +/// @param[out] y - the returned batched element y. +/// @param[in] trimat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim - the dimension of matrix trimat (and x). +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_quad_trimat_eval_gf256(unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned int dim, unsigned int size_batch); + +/// +/// @brief z = y^Tr * mat * x , in GF(16) +/// +/// @param[out] z - the returned batched element z. +/// @param[in] y - an input vector y. +/// @param[in] dim_y - the length of y. +/// @param[in] mat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim_x - the length of x. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_quad_recmat_eval_gf16(unsigned char *z, const unsigned char *y, unsigned int dim_y, + const unsigned char *mat, const unsigned char *x, unsigned int dim_x, unsigned int size_batch); + +/// +/// @brief z = y^Tr * mat * x , in GF(256) +/// +/// @param[out] z - the returned batched element z. +/// @param[in] y - an input vector y. +/// @param[in] dim_y - the length of y. +/// @param[in] mat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim_x - the length of x. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_quad_recmat_eval_gf256(unsigned char *z, const unsigned char *y, unsigned int dim_y, + const unsigned char *mat, const unsigned char *x, unsigned int dim_x, unsigned int size_batch); + +#endif // _P_MATRIX_OP_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/rainbow.c b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/rainbow.c new file mode 100644 index 0000000000..a4b6f45ef1 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/rainbow.c @@ -0,0 +1,173 @@ +/// @file rainbow.c +/// @brief The standard implementations for functions in rainbow.h +/// + +#include "blas.h" +#include "parallel_matrix_op.h" +#include "rainbow.h" +#include "rainbow_blas.h" +#include "rainbow_config.h" +#include "rainbow_keypair.h" +#include "utils_hash.h" +#include "utils_prng.h" +#include +#include +#include + +#define MAX_ATTEMPT_FRMAT 128 + +int PQCLEAN_RAINBOWIACYCLIC_CLEAN_rainbow_sign(uint8_t *signature, const sk_t *sk, const uint8_t *_digest) { + uint8_t mat_l1[_O1 * _O1_BYTE]; + uint8_t mat_l2[_O2 * _O2_BYTE]; + uint8_t mat_buffer[2 * _MAX_O * _MAX_O_BYTE]; + + // setup PRNG + prng_t prng_sign; + uint8_t prng_preseed[LEN_SKSEED + _HASH_LEN]; + memcpy(prng_preseed, sk->sk_seed, LEN_SKSEED); + memcpy(prng_preseed + LEN_SKSEED, _digest, _HASH_LEN); // prng_preseed = sk_seed || digest + uint8_t prng_seed[_HASH_LEN]; + PQCLEAN_RAINBOWIACYCLIC_CLEAN_hash_msg(prng_seed, _HASH_LEN, prng_preseed, _HASH_LEN + LEN_SKSEED); + PQCLEAN_RAINBOWIACYCLIC_CLEAN_prng_set(&prng_sign, prng_seed, _HASH_LEN); // seed = H( sk_seed || digest ) + for (unsigned int i = 0; i < LEN_SKSEED + _HASH_LEN; i++) { + prng_preseed[i] ^= prng_preseed[i]; // clean + } + for (unsigned int i = 0; i < _HASH_LEN; i++) { + prng_seed[i] ^= prng_seed[i]; // clean + } + + // roll vinegars. + uint8_t vinegar[_V1_BYTE]; + unsigned int n_attempt = 0; + unsigned int l1_succ = 0; + while (!l1_succ) { + if (MAX_ATTEMPT_FRMAT <= n_attempt) { + break; + } + PQCLEAN_RAINBOWIACYCLIC_CLEAN_prng_gen(&prng_sign, vinegar, _V1_BYTE); // generating vinegars + gfmat_prod(mat_l1, sk->l1_F2, _O1 * _O1_BYTE, _V1, vinegar); // generating the linear equations for layer 1 + l1_succ = gfmat_inv(mat_l1, mat_l1, _O1, mat_buffer); // check if the linear equation solvable + n_attempt++; + } + + // Given the vinegars, pre-compute variables needed for layer 2 + uint8_t r_l1_F1[_O1_BYTE] = {0}; + uint8_t r_l2_F1[_O2_BYTE] = {0}; + batch_quad_trimat_eval(r_l1_F1, sk->l1_F1, vinegar, _V1, _O1_BYTE); + batch_quad_trimat_eval(r_l2_F1, sk->l2_F1, vinegar, _V1, _O2_BYTE); + uint8_t mat_l2_F3[_O2 * _O2_BYTE]; + uint8_t mat_l2_F2[_O1 * _O2_BYTE]; + gfmat_prod(mat_l2_F3, sk->l2_F3, _O2 * _O2_BYTE, _V1, vinegar); + gfmat_prod(mat_l2_F2, sk->l2_F2, _O1 * _O2_BYTE, _V1, vinegar); + + // Some local variables. + uint8_t _z[_PUB_M_BYTE]; + uint8_t y[_PUB_M_BYTE]; + uint8_t *x_v1 = vinegar; + uint8_t x_o1[_O1_BYTE]; + uint8_t x_o2[_O1_BYTE]; + + uint8_t digest_salt[_HASH_LEN + _SALT_BYTE]; + memcpy(digest_salt, _digest, _HASH_LEN); + uint8_t *salt = digest_salt + _HASH_LEN; + + uint8_t temp_o[_MAX_O_BYTE + 32] = {0}; + unsigned int succ = 0; + while (!succ) { + if (MAX_ATTEMPT_FRMAT <= n_attempt) { + break; + } + // The computation: H(digest||salt) --> z --S--> y --C-map--> x --T--> w + + PQCLEAN_RAINBOWIACYCLIC_CLEAN_prng_gen(&prng_sign, salt, _SALT_BYTE); // roll the salt + PQCLEAN_RAINBOWIACYCLIC_CLEAN_hash_msg(_z, _PUB_M_BYTE, digest_salt, _HASH_LEN + _SALT_BYTE); // H(digest||salt) + + // y = S^-1 * z + memcpy(y, _z, _PUB_M_BYTE); // identity part of S + gfmat_prod(temp_o, sk->s1, _O1_BYTE, _O2, _z + _O1_BYTE); + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_add(y, temp_o, _O1_BYTE); + + // Central Map: + // layer 1: calculate x_o1 + memcpy(temp_o, r_l1_F1, _O1_BYTE); + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_add(temp_o, y, _O1_BYTE); + gfmat_prod(x_o1, mat_l1, _O1_BYTE, _O1, temp_o); + + // layer 2: calculate x_o2 + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_set_zero(temp_o, _O2_BYTE); + gfmat_prod(temp_o, mat_l2_F2, _O2_BYTE, _O1, x_o1); // F2 + batch_quad_trimat_eval(mat_l2, sk->l2_F5, x_o1, _O1, _O2_BYTE); // F5 + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_add(temp_o, mat_l2, _O2_BYTE); + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_add(temp_o, r_l2_F1, _O2_BYTE); // F1 + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_add(temp_o, y + _O1_BYTE, _O2_BYTE); + + // generate the linear equations of the 2nd layer + gfmat_prod(mat_l2, sk->l2_F6, _O2 * _O2_BYTE, _O1, x_o1); // F6 + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_add(mat_l2, mat_l2_F3, _O2 * _O2_BYTE); // F3 + succ = gfmat_inv(mat_l2, mat_l2, _O2, mat_buffer); + gfmat_prod(x_o2, mat_l2, _O2_BYTE, _O2, temp_o); // solve l2 eqs + + n_attempt++; + }; + // w = T^-1 * y + uint8_t w[_PUB_N_BYTE]; + // identity part of T. + memcpy(w, x_v1, _V1_BYTE); + memcpy(w + _V1_BYTE, x_o1, _O1_BYTE); + memcpy(w + _V2_BYTE, x_o2, _O2_BYTE); + // Computing the t1 part. + gfmat_prod(y, sk->t1, _V1_BYTE, _O1, x_o1); + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_add(w, y, _V1_BYTE); + // Computing the t4 part. + gfmat_prod(y, sk->t4, _V1_BYTE, _O2, x_o2); + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_add(w, y, _V1_BYTE); + // Computing the t3 part. + gfmat_prod(y, sk->t3, _O1_BYTE, _O2, x_o2); + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_add(w + _V1_BYTE, y, _O1_BYTE); + + memset(signature, 0, _SIGNATURE_BYTE); // set the output 0 + // clean + memset(&prng_sign, 0, sizeof(prng_t)); + memset(vinegar, 0, _V1_BYTE); + memset(r_l1_F1, 0, _O1_BYTE); + memset(r_l2_F1, 0, _O2_BYTE); + memset(_z, 0, _PUB_M_BYTE); + memset(y, 0, _PUB_M_BYTE); + memset(x_o1, 0, _O1_BYTE); + memset(x_o2, 0, _O2_BYTE); + memset(temp_o, 0, sizeof(temp_o)); + + // return: copy w and salt to the signature. + if (MAX_ATTEMPT_FRMAT <= n_attempt) { + return -1; + } + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_add(signature, w, _PUB_N_BYTE); + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_add(signature + _PUB_N_BYTE, salt, _SALT_BYTE); + return 0; +} + +int PQCLEAN_RAINBOWIACYCLIC_CLEAN_rainbow_verify(const uint8_t *digest, const uint8_t *signature, const pk_t *pk) { + unsigned char digest_ck[_PUB_M_BYTE]; + // public_map( digest_ck , pk , signature ); Evaluating the quadratic public polynomials. + batch_quad_trimat_eval(digest_ck, pk->pk, signature, _PUB_N, _PUB_M_BYTE); + + unsigned char correct[_PUB_M_BYTE]; + unsigned char digest_salt[_HASH_LEN + _SALT_BYTE]; + memcpy(digest_salt, digest, _HASH_LEN); + memcpy(digest_salt + _HASH_LEN, signature + _PUB_N_BYTE, _SALT_BYTE); + PQCLEAN_RAINBOWIACYCLIC_CLEAN_hash_msg(correct, _PUB_M_BYTE, digest_salt, _HASH_LEN + _SALT_BYTE); // H( digest || salt ) + + // check consistancy. + unsigned char cc = 0; + for (unsigned int i = 0; i < _PUB_M_BYTE; i++) { + cc |= (digest_ck[i] ^ correct[i]); + } + return (0 == cc) ? 0 : -1; +} + + +int PQCLEAN_RAINBOWIACYCLIC_CLEAN_rainbow_verify_cyclic(const uint8_t *digest, const uint8_t *signature, const cpk_t *_pk) { + unsigned char pk[sizeof(pk_t) + 32]; + PQCLEAN_RAINBOWIACYCLIC_CLEAN_cpk_to_pk((pk_t *)pk, _pk); // generating classic public key. + return PQCLEAN_RAINBOWIACYCLIC_CLEAN_rainbow_verify(digest, signature, (pk_t *)pk); +} diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/rainbow.h b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/rainbow.h new file mode 100644 index 0000000000..dca27b1159 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/rainbow.h @@ -0,0 +1,42 @@ +#ifndef _RAINBOW_H_ +#define _RAINBOW_H_ +/// @file rainbow.h +/// @brief APIs for rainbow. +/// + +#include "rainbow_config.h" +#include "rainbow_keypair.h" + +#include + +/// +/// @brief Signing function for classical secret key. +/// +/// @param[out] signature - the signature. +/// @param[in] sk - the secret key. +/// @param[in] digest - the digest. +/// +int PQCLEAN_RAINBOWIACYCLIC_CLEAN_rainbow_sign(uint8_t *signature, const sk_t *sk, const uint8_t *digest); + +/// +/// @brief Verifying function. +/// +/// @param[in] digest - the digest. +/// @param[in] signature - the signature. +/// @param[in] pk - the public key. +/// @return 0 for successful verified. -1 for failed verification. +/// +int PQCLEAN_RAINBOWIACYCLIC_CLEAN_rainbow_verify(const uint8_t *digest, const uint8_t *signature, const pk_t *pk); + + +/// +/// @brief Verifying function for cyclic public keys. +/// +/// @param[in] digest - the digest. +/// @param[in] signature - the signature. +/// @param[in] pk - the public key of cyclic rainbow. +/// @return 0 for successful verified. -1 for failed verification. +/// +int PQCLEAN_RAINBOWIACYCLIC_CLEAN_rainbow_verify_cyclic(const uint8_t *digest, const uint8_t *signature, const cpk_t *pk); + +#endif // _RAINBOW_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/rainbow_blas.h b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/rainbow_blas.h new file mode 100644 index 0000000000..a78caf541d --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/rainbow_blas.h @@ -0,0 +1,32 @@ +#ifndef _RAINBOW_BLAS_H_ +#define _RAINBOW_BLAS_H_ +/// @file rainbow_blas.h +/// @brief Defining the functions used in rainbow.c acconding to the definitions in rainbow_config.h +/// +/// Defining the functions used in rainbow.c acconding to the definitions in rainbow_config.h + +#include "blas.h" +#include "blas_comm.h" +#include "parallel_matrix_op.h" +#include "rainbow_config.h" + + +#define gfv_get_ele PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_get_ele +#define gfv_mul_scalar PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_mul_scalar +#define gfv_madd PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16v_madd + +#define gfmat_prod PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16mat_prod +#define gfmat_inv PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf16mat_inv + +#define batch_trimat_madd PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_trimat_madd_gf16 +#define batch_trimatTr_madd PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_trimatTr_madd_gf16 +#define batch_2trimat_madd PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_2trimat_madd_gf16 +#define batch_matTr_madd PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_matTr_madd_gf16 +#define batch_bmatTr_madd PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_bmatTr_madd_gf16 +#define batch_mat_madd PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_mat_madd_gf16 + +#define batch_quad_trimat_eval PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_quad_trimat_eval_gf16 +#define batch_quad_recmat_eval PQCLEAN_RAINBOWIACYCLIC_CLEAN_batch_quad_recmat_eval_gf16 + + +#endif // _RAINBOW_BLAS_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/rainbow_config.h b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/rainbow_config.h new file mode 100644 index 0000000000..3607536831 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/rainbow_config.h @@ -0,0 +1,49 @@ +#ifndef _H_RAINBOW_CONFIG_H_ +#define _H_RAINBOW_CONFIG_H_ + +/// @file rainbow_config.h +/// @brief Defining the parameters of the Rainbow and the corresponding constants. +/// + +#define _USE_GF16 +#define _GFSIZE 16 +#define _V1 32 +#define _O1 32 +#define _O2 32 +#define _MAX_O 32 +#define _HASH_LEN 32 + + +#define _V2 ((_V1) + (_O1)) + +/// size of N, in # of gf elements. +#define _PUB_N (_V1 + _O1 + _O2) + +/// size of M, in # gf elements. +#define _PUB_M (_O1 + _O2) + +/// size of variables, in # bytes. + +// GF16 +#define _V1_BYTE (_V1 / 2) +#define _V2_BYTE (_V2 / 2) +#define _O1_BYTE (_O1 / 2) +#define _O2_BYTE (_O2 / 2) +#define _MAX_O_BYTE (_MAX_O / 2) +#define _PUB_N_BYTE (_PUB_N / 2) +#define _PUB_M_BYTE (_PUB_M / 2) + + +/// length of seed for public key, in # bytes +#define LEN_PKSEED 32 + +/// length of seed for secret key, in # bytes +#define LEN_SKSEED 32 + +/// length of salt for a signature, in # bytes +#define _SALT_BYTE 16 + +/// length of a signature +#define _SIGNATURE_BYTE (_PUB_N_BYTE + _SALT_BYTE) + +#endif // _H_RAINBOW_CONFIG_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/rainbow_keypair.c b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/rainbow_keypair.c new file mode 100644 index 0000000000..3c6258d2e7 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/rainbow_keypair.c @@ -0,0 +1,157 @@ +/// @file rainbow_keypair.c +/// @brief implementations of functions in rainbow_keypair.h +/// + +#include "rainbow_keypair.h" +#include "blas.h" +#include "blas_comm.h" +#include "rainbow_blas.h" +#include "rainbow_keypair_computation.h" +#include "utils_prng.h" +#include +#include +#include + +static void generate_S_T(unsigned char *s_and_t, prng_t *prng0) { + PQCLEAN_RAINBOWIACYCLIC_CLEAN_prng_gen(prng0, s_and_t, _O1_BYTE * _O2); // S1 + s_and_t += _O1_BYTE * _O2; + PQCLEAN_RAINBOWIACYCLIC_CLEAN_prng_gen(prng0, s_and_t, _V1_BYTE * _O1); // T1 + s_and_t += _V1_BYTE * _O1; + PQCLEAN_RAINBOWIACYCLIC_CLEAN_prng_gen(prng0, s_and_t, _V1_BYTE * _O2); // T2 + s_and_t += _V1_BYTE * _O2; + PQCLEAN_RAINBOWIACYCLIC_CLEAN_prng_gen(prng0, s_and_t, _O1_BYTE * _O2); // T3 +} + +static unsigned int generate_l1_F12(unsigned char *sk, prng_t *prng0) { + unsigned int n_byte_generated = 0; + PQCLEAN_RAINBOWIACYCLIC_CLEAN_prng_gen(prng0, sk, _O1_BYTE * N_TRIANGLE_TERMS(_V1)); // l1_F1 + sk += _O1_BYTE * N_TRIANGLE_TERMS(_V1); + n_byte_generated += _O1_BYTE * N_TRIANGLE_TERMS(_V1); + + PQCLEAN_RAINBOWIACYCLIC_CLEAN_prng_gen(prng0, sk, _O1_BYTE * _V1 * _O1); // l1_F2 + n_byte_generated += _O1_BYTE * _V1 * _O1; + return n_byte_generated; +} + +static unsigned int generate_l2_F12356(unsigned char *sk, prng_t *prng0) { + unsigned int n_byte_generated = 0; + + PQCLEAN_RAINBOWIACYCLIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * N_TRIANGLE_TERMS(_V1)); // l2_F1 + sk += _O2_BYTE * N_TRIANGLE_TERMS(_V1); + n_byte_generated += _O2_BYTE * N_TRIANGLE_TERMS(_V1); + + PQCLEAN_RAINBOWIACYCLIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * _V1 * _O1); // l2_F2 + sk += _O2_BYTE * _V1 * _O1; + n_byte_generated += _O2_BYTE * _V1 * _O1; + + PQCLEAN_RAINBOWIACYCLIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * _V1 * _O2); // l2_F3 + sk += _O2_BYTE * _V1 * _O1; + n_byte_generated += _O2_BYTE * _V1 * _O1; + + PQCLEAN_RAINBOWIACYCLIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * N_TRIANGLE_TERMS(_O1)); // l2_F5 + sk += _O2_BYTE * N_TRIANGLE_TERMS(_O1); + n_byte_generated += _O2_BYTE * N_TRIANGLE_TERMS(_O1); + + PQCLEAN_RAINBOWIACYCLIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * _O1 * _O2); // l2_F6 + n_byte_generated += _O2_BYTE * _O1 * _O2; + + return n_byte_generated; +} + +static void generate_B1_B2(unsigned char *sk, prng_t *prng0) { + sk += generate_l1_F12(sk, prng0); + generate_l2_F12356(sk, prng0); +} + +static void calculate_t4(unsigned char *t2_to_t4, const unsigned char *t1, const unsigned char *t3) { + // t4 = T_sk.t1 * T_sk.t3 - T_sk.t2 + unsigned char temp[_V1_BYTE + 32]; + unsigned char *t4 = t2_to_t4; + for (unsigned int i = 0; i < _O2; i++) { /// t3 width + gfmat_prod(temp, t1, _V1_BYTE, _O1, t3); + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_add(t4, temp, _V1_BYTE); + t4 += _V1_BYTE; + t3 += _O1_BYTE; + } +} + +static void obsfucate_l1_polys(unsigned char *l1_polys, const unsigned char *l2_polys, unsigned int n_terms, const unsigned char *s1) { + unsigned char temp[_O1_BYTE + 32]; + while (n_terms--) { + gfmat_prod(temp, s1, _O1_BYTE, _O2, l2_polys); + PQCLEAN_RAINBOWIACYCLIC_CLEAN_gf256v_add(l1_polys, temp, _O1_BYTE); + l1_polys += _O1_BYTE; + l2_polys += _O2_BYTE; + } +} + +/////////////////// Classic ////////////////////////////////// + + +///////////////////// Cyclic ////////////////////////////////// +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_generate_keypair_cyclic(cpk_t *pk, sk_t *sk, const unsigned char *pk_seed, const unsigned char *sk_seed) { + memcpy(pk->pk_seed, pk_seed, LEN_PKSEED); + memcpy(sk->sk_seed, sk_seed, LEN_SKSEED); + + // prng for sk + prng_t prng; + prng_t *prng0 = &prng; + PQCLEAN_RAINBOWIACYCLIC_CLEAN_prng_set(prng0, sk_seed, LEN_SKSEED); + generate_S_T(sk->s1, prng0); // S,T: only a part of sk + + unsigned char t2[sizeof(sk->t4)]; + memcpy(t2, sk->t4, _V1_BYTE * _O2); // temporarily store t2 + calculate_t4(sk->t4, sk->t1, sk->t3); // t2 <- t4 + + // prng for pk + sk_t inst_Qs; + sk_t *Qs = &inst_Qs; + prng_t *prng1 = &prng; + PQCLEAN_RAINBOWIACYCLIC_CLEAN_prng_set(prng1, pk_seed, LEN_PKSEED); + generate_B1_B2(Qs->l1_F1, prng1); // generating l1_Q1, l1_Q2, l2_Q1, l2_Q2, l2_Q3, l2_Q5, l2_Q6 + obsfucate_l1_polys(Qs->l1_F1, Qs->l2_F1, N_TRIANGLE_TERMS(_V1), sk->s1); + obsfucate_l1_polys(Qs->l1_F2, Qs->l2_F2, _V1 * _O1, sk->s1); + // so far, the Qs contains l1_F1, l1_F2, l2_F1, l2_F2, l2_F3, l2_F5, l2_F6. + + PQCLEAN_RAINBOWIACYCLIC_CLEAN_calculate_F_from_Q(sk, Qs, sk); // calcuate the rest parts of secret key from Qs and S,T + + unsigned char t4[sizeof(sk->t4)]; + memcpy(t4, sk->t4, _V1_BYTE * _O2); // temporarily store t4 + memcpy(sk->t4, t2, _V1_BYTE * _O2); // restore t2 + PQCLEAN_RAINBOWIACYCLIC_CLEAN_calculate_Q_from_F_cyclic(pk, sk, sk); // calculate the rest parts of public key: l1_Q3, l1_Q5, l1_Q6, l1_Q9, l2_Q9 + memcpy(sk->t4, t4, _V1_BYTE * _O2); // restore t4 + + obsfucate_l1_polys(pk->l1_Q3, Qs->l2_F3, _V1 * _O2, sk->s1); + obsfucate_l1_polys(pk->l1_Q5, Qs->l2_F5, N_TRIANGLE_TERMS(_O1), sk->s1); + obsfucate_l1_polys(pk->l1_Q6, Qs->l2_F6, _O1 * _O2, sk->s1); + obsfucate_l1_polys(pk->l1_Q9, pk->l2_Q9, N_TRIANGLE_TERMS(_O2), sk->s1); + + // clean + memset(&prng, 0, sizeof(prng_t)); +} + + + +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_cpk_to_pk(pk_t *rpk, const cpk_t *cpk) { + // procedure: cpk_t --> extcpk_t --> pk_t + + // convert from cpk_t to extcpk_t + ext_cpk_t pk; + + // setup prng + prng_t prng0; + PQCLEAN_RAINBOWIACYCLIC_CLEAN_prng_set(&prng0, cpk->pk_seed, LEN_SKSEED); + + // generating parts of key with prng + generate_l1_F12(pk.l1_Q1, &prng0); + // copying parts of key from input. l1_Q3, l1_Q5, l1_Q6, l1_Q9 + memcpy(pk.l1_Q3, cpk->l1_Q3, _O1_BYTE * (_V1 * _O2 + N_TRIANGLE_TERMS(_O1) + _O1 * _O2 + N_TRIANGLE_TERMS(_O2))); + + // generating parts of key with prng + generate_l2_F12356(pk.l2_Q1, &prng0); + // copying parts of key from input: l2_Q9 + memcpy(pk.l2_Q9, cpk->l2_Q9, _O2_BYTE * N_TRIANGLE_TERMS(_O2)); + + // convert from extcpk_t to pk_t + PQCLEAN_RAINBOWIACYCLIC_CLEAN_extcpk_to_pk(rpk, &pk); +} diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/rainbow_keypair.h b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/rainbow_keypair.h new file mode 100644 index 0000000000..3490ea05a5 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/rainbow_keypair.h @@ -0,0 +1,94 @@ +#ifndef _RAINBOW_KEYPAIR_H_ +#define _RAINBOW_KEYPAIR_H_ +/// @file rainbow_keypair.h +/// @brief Formats of key pairs and functions for generating key pairs. +/// Formats of key pairs and functions for generating key pairs. +/// + +#include "rainbow_config.h" + +#define N_TRIANGLE_TERMS(n_var) ((n_var) * ((n_var) + 1) / 2) + +/// @brief public key for classic rainbow +/// +/// public key for classic rainbow +/// +typedef struct rainbow_publickey { + unsigned char pk[(_PUB_M_BYTE)*N_TRIANGLE_TERMS(_PUB_N)]; +} pk_t; + +/// @brief secret key for classic rainbow +/// +/// secret key for classic rainbow +/// +typedef struct rainbow_secretkey { + /// + /// seed for generating secret key. + /// Generating S, T, and F for classic rainbow. + /// Generating S and T only for cyclic rainbow. + unsigned char sk_seed[LEN_SKSEED]; + + unsigned char s1[_O1_BYTE * _O2]; ///< part of S map + unsigned char t1[_V1_BYTE * _O1]; ///< part of T map + unsigned char t4[_V1_BYTE * _O2]; ///< part of T map + unsigned char t3[_O1_BYTE * _O2]; ///< part of T map + + unsigned char l1_F1[_O1_BYTE * N_TRIANGLE_TERMS(_V1)]; ///< part of C-map, F1, Layer1 + unsigned char l1_F2[_O1_BYTE * _V1 * _O1]; ///< part of C-map, F2, Layer1 + + unsigned char l2_F1[_O2_BYTE * N_TRIANGLE_TERMS(_V1)]; ///< part of C-map, F1, Layer2 + unsigned char l2_F2[_O2_BYTE * _V1 * _O1]; ///< part of C-map, F2, Layer2 + + unsigned char l2_F3[_O2_BYTE * _V1 * _O2]; ///< part of C-map, F3, Layer2 + unsigned char l2_F5[_O2_BYTE * N_TRIANGLE_TERMS(_O1)]; ///< part of C-map, F5, Layer2 + unsigned char l2_F6[_O2_BYTE * _O1 * _O2]; ///< part of C-map, F6, Layer2 +} sk_t; + +/// @brief public key for cyclic rainbow +/// +/// public key for cyclic rainbow +/// +typedef struct rainbow_publickey_cyclic { + unsigned char pk_seed[LEN_PKSEED]; ///< seed for generating l1_Q1,l1_Q2,l2_Q1,l2_Q2,l2_Q3,l2_Q5,l2_Q6 + + unsigned char l1_Q3[_O1_BYTE * _V1 * _O2]; ///< Q3, layer1 + unsigned char l1_Q5[_O1_BYTE * N_TRIANGLE_TERMS(_O1)]; ///< Q5, layer1 + unsigned char l1_Q6[_O1_BYTE * _O1 * _O2]; ///< Q6, layer1 + unsigned char l1_Q9[_O1_BYTE * N_TRIANGLE_TERMS(_O2)]; ///< Q9, layer1 + + unsigned char l2_Q9[_O2_BYTE * N_TRIANGLE_TERMS(_O2)]; ///< Q9, layer2 +} cpk_t; + +/// @brief compressed secret key for cyclic rainbow +/// +/// compressed secret key for cyclic rainbow +/// +typedef struct rainbow_secretkey_cyclic { + unsigned char pk_seed[LEN_PKSEED]; ///< seed for generating a part of public key. + unsigned char sk_seed[LEN_SKSEED]; ///< seed for generating a part of secret key. +} csk_t; + + +/// +/// @brief Generate key pairs for cyclic rainbow. +/// +/// @param[out] pk - the public key. +/// @param[out] sk - the secret key. +/// @param[in] pk_seed - seed for generating parts of public key. +/// @param[in] sk_seed - seed for generating secret key. +/// +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_generate_keypair_cyclic(cpk_t *pk, sk_t *sk, const unsigned char *pk_seed, const unsigned char *sk_seed); + + + +//////////////////////////////////// + +/// +/// @brief converting formats of public keys : from cyclic version to classic key +/// +/// @param[out] pk - the classic public key. +/// @param[in] cpk - the cyclic public key. +/// +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_cpk_to_pk(pk_t *pk, const cpk_t *cpk); + +#endif // _RAINBOW_KEYPAIR_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/rainbow_keypair_computation.c b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/rainbow_keypair_computation.c new file mode 100644 index 0000000000..982d13b1fb --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/rainbow_keypair_computation.c @@ -0,0 +1,213 @@ +/// @file rainbow_keypair_computation.c +/// @brief Implementations for functions in rainbow_keypair_computation.h +/// + +#include "rainbow_keypair_computation.h" +#include "blas.h" +#include "blas_comm.h" +#include "rainbow_blas.h" +#include "rainbow_keypair.h" +#include +#include +#include + +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_extcpk_to_pk(pk_t *pk, const ext_cpk_t *cpk) { + const unsigned char *idx_l1 = cpk->l1_Q1; + const unsigned char *idx_l2 = cpk->l2_Q1; + for (unsigned int i = 0; i < _V1; i++) { + for (unsigned int j = i; j < _V1; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIACYCLIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q2; + idx_l2 = cpk->l2_Q2; + for (unsigned int i = 0; i < _V1; i++) { + for (unsigned int j = _V1; j < _V1 + _O1; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIACYCLIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q3; + idx_l2 = cpk->l2_Q3; + for (unsigned int i = 0; i < _V1; i++) { + for (unsigned int j = _V1 + _O1; j < _PUB_N; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIACYCLIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q5; + idx_l2 = cpk->l2_Q5; + for (unsigned int i = _V1; i < _V1 + _O1; i++) { + for (unsigned int j = i; j < _V1 + _O1; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIACYCLIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q6; + idx_l2 = cpk->l2_Q6; + for (unsigned int i = _V1; i < _V1 + _O1; i++) { + for (unsigned int j = _V1 + _O1; j < _PUB_N; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIACYCLIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q9; + idx_l2 = cpk->l2_Q9; + for (unsigned int i = _V1 + _O1; i < _PUB_N; i++) { + for (unsigned int j = i; j < _PUB_N; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWIACYCLIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } +} + +static void calculate_F_from_Q_ref(sk_t *Fs, const sk_t *Qs, sk_t *Ts) { + // Layer 1 + // F_sk.l1_F1s[i] = Q_pk.l1_F1s[i] + memcpy(Fs->l1_F1, Qs->l1_F1, _O1_BYTE * N_TRIANGLE_TERMS(_V1)); + + // F_sk.l1_F2s[i] = ( Q_pk.l1_F1s[i] + Q_pk.l1_F1s[i].transpose() ) * T_sk.t1 + Q_pk.l1_F2s[i] + memcpy(Fs->l1_F2, Qs->l1_F2, _O1_BYTE * _V1 * _O1); + batch_2trimat_madd(Fs->l1_F2, Qs->l1_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O1_BYTE); + + /* + Layer 2 + computations: + + F_sk.l2_F1s[i] = Q_pk.l2_F1s[i] + + Q1_T1 = Q_pk.l2_F1s[i]*T_sk.t1 + F_sk.l2_F2s[i] = Q1_T1 + Q_pk.l2_F2s[i] + Q_pk.l2_F1s[i].transpose() * T_sk.t1 + F_sk.l2_F5s[i] = UT( t1_tr* ( Q1_T1 + Q_pk.l2_F2s[i] ) ) + Q_pk.l2_F5s[i] + + Q1_Q1T_T4 = (Q_pk.l2_F1s[i] + Q_pk.l2_F1s[i].transpose()) * t4 + #Q1_Q1T_T4 = Q1_Q1T * t4 + Q2_T3 = Q_pk.l2_F2s[i]*T_sk.t3 + F_sk.l2_F3s[i] = Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] + F_sk.l2_F6s[i] = t1_tr * ( Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] ) + + Q_pk.l2_F2s[i].transpose() * t4 + + (Q_pk.l2_F5s[i] + Q_pk.l2_F5s[i].transpose())*T_sk.t3 + Q_pk.l2_F6s[i] + + */ + memcpy(Fs->l2_F1, Qs->l2_F1, _O2_BYTE * N_TRIANGLE_TERMS(_V1)); // F_sk.l2_F1s[i] = Q_pk.l2_F1s[i] + + // F_sk.l2_F2s[i] = Q1_T1 + Q_pk.l2_F2s[i] + Q_pk.l2_F1s[i].transpose() * T_sk.t1 + // F_sk.l2_F5s[i] = UT( t1_tr* ( Q1_T1 + Q_pk.l2_F2s[i] ) ) + Q_pk.l2_F5s[i] + memcpy(Fs->l2_F2, Qs->l2_F2, _O2_BYTE * _V1 * _O1); + batch_trimat_madd(Fs->l2_F2, Qs->l2_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O2_BYTE); // Q1_T1+ Q2 + + unsigned char tempQ[_O1 * _O1 * _O2_BYTE + 32]; + memset(tempQ, 0, _O1 * _O1 * _O2_BYTE); + batch_matTr_madd(tempQ, Ts->t1, _V1, _V1_BYTE, _O1, Fs->l2_F2, _O1, _O2_BYTE); // t1_tr*(Q1_T1+Q2) + memcpy(Fs->l2_F5, Qs->l2_F5, _O2_BYTE * N_TRIANGLE_TERMS(_O1)); // F5 + PQCLEAN_RAINBOWIACYCLIC_CLEAN_UpperTrianglize(Fs->l2_F5, tempQ, _O1, _O2_BYTE); // UT( ... ) + + batch_trimatTr_madd(Fs->l2_F2, Qs->l2_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O2_BYTE); // F2 = Q1_T1 + Q2 + Q1^tr*t1 + + // Q1_Q1T_T4 = (Q_pk.l2_F1s[i] + Q_pk.l2_F1s[i].transpose()) * t4 + // Q2_T3 = Q_pk.l2_F2s[i]*T_sk.t3 + // F_sk.l2_F3s[i] = Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] + memcpy(Fs->l2_F3, Qs->l2_F3, _V1 * _O2 * _O2_BYTE); + batch_2trimat_madd(Fs->l2_F3, Qs->l2_F1, Ts->t4, _V1, _V1_BYTE, _O2, _O2_BYTE); // Q1_Q1T_T4 + batch_mat_madd(Fs->l2_F3, Qs->l2_F2, _V1, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // Q2_T3 + + // F_sk.l2_F6s[i] = t1_tr * ( Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] ) + // + Q_pk.l2_F2s[i].transpose() * t4 + // + (Q_pk.l2_F5s[i] + Q_pk.l2_F5s[i].transpose())*T_sk.t3 + Q_pk.l2_F6s[i] + memcpy(Fs->l2_F6, Qs->l2_F6, _O1 * _O2 * _O2_BYTE); + batch_matTr_madd(Fs->l2_F6, Ts->t1, _V1, _V1_BYTE, _O1, Fs->l2_F3, _O2, _O2_BYTE); // t1_tr * ( Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] ) + batch_2trimat_madd(Fs->l2_F6, Qs->l2_F5, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // (Q_pk.l2_F5s[i] + Q_pk.l2_F5s[i].transpose())*T_sk.t3 + batch_bmatTr_madd(Fs->l2_F6, Qs->l2_F2, _O1, Ts->t4, _V1, _V1_BYTE, _O2, _O2_BYTE); +} + +static void calculate_Q_from_F_cyclic_ref(cpk_t *Qs, const sk_t *Fs, const sk_t *Ts) { + // Layer 1: Computing Q5, Q3, Q6, Q9 + + // Q_pk.l1_F5s[i] = UT( T1tr* (F1 * T1 + F2) ) + const unsigned char *t2 = Ts->t4; + sk_t tempQ; + memcpy(tempQ.l1_F2, Fs->l1_F2, _O1_BYTE * _V1 * _O1); + batch_trimat_madd(tempQ.l1_F2, Fs->l1_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O1_BYTE); // F1*T1 + F2 + memset(tempQ.l2_F1, 0, sizeof(tempQ.l2_F1)); + memset(tempQ.l2_F2, 0, sizeof(tempQ.l2_F2)); + batch_matTr_madd(tempQ.l2_F1, Ts->t1, _V1, _V1_BYTE, _O1, tempQ.l1_F2, _O1, _O1_BYTE); // T1tr*(F1*T1 + F2) + memset(Qs->l1_Q5, 0, _O1_BYTE * N_TRIANGLE_TERMS(_O1)); + PQCLEAN_RAINBOWIACYCLIC_CLEAN_UpperTrianglize(Qs->l1_Q5, tempQ.l2_F1, _O1, _O1_BYTE); // UT( ... ) // Q5 + + /* + F1_T2 = F1 * t2 + F2_T3 = F2 * t3 + F1_F1T_T2 + F2_T3 = F1_T2 + F2_T3 + F1tr * t2 + Q_pk.l1_F3s[i] = F1_F1T_T2 + F2_T3 + Q_pk.l1_F6s[i] = T1tr* ( F1_F1T_T2 + F2_T3 ) + F2tr * t2 + Q_pk.l1_F9s[i] = UT( T2tr* ( F1_T2 + F2_T3 ) ) + */ + memset(Qs->l1_Q3, 0, _O1_BYTE * _V1 * _O2); + memset(Qs->l1_Q6, 0, _O1_BYTE * _O1 * _O2); + memset(Qs->l1_Q9, 0, _O1_BYTE * N_TRIANGLE_TERMS(_O2)); + + batch_trimat_madd(Qs->l1_Q3, Fs->l1_F1, t2, _V1, _V1_BYTE, _O2, _O1_BYTE); // F1*T2 + batch_mat_madd(Qs->l1_Q3, Fs->l1_F2, _V1, Ts->t3, _O1, _O1_BYTE, _O2, _O1_BYTE); // F1_T2 + F2_T3 + + memset(tempQ.l1_F2, 0, _O1_BYTE * _V1 * _O2); // should be F3. assuming: _O1 >= _O2 + batch_matTr_madd(tempQ.l1_F2, t2, _V1, _V1_BYTE, _O2, Qs->l1_Q3, _O2, _O1_BYTE); // T2tr * ( F1_T2 + F2_T3 ) + PQCLEAN_RAINBOWIACYCLIC_CLEAN_UpperTrianglize(Qs->l1_Q9, tempQ.l1_F2, _O2, _O1_BYTE); // Q9 + + batch_trimatTr_madd(Qs->l1_Q3, Fs->l1_F1, t2, _V1, _V1_BYTE, _O2, _O1_BYTE); // F1_F1T_T2 + F2_T3 // Q3 + + batch_bmatTr_madd(Qs->l1_Q6, Fs->l1_F2, _O1, t2, _V1, _V1_BYTE, _O2, _O1_BYTE); // F2tr*T2 + batch_matTr_madd(Qs->l1_Q6, Ts->t1, _V1, _V1_BYTE, _O1, Qs->l1_Q3, _O2, _O1_BYTE); // Q6 + /* + Layer 2 + Computing Q9: + + F1_T2 = F1 * t2 + F2_T3 = F2 * t3 + Q9 = UT( T2tr*( F1*T2 + F2*T3 + F3 ) + T3tr*( F5*T3 + F6 ) ) + */ + sk_t tempQ2; + memcpy(tempQ2.l2_F3, Fs->l2_F3, _O2_BYTE * _V1 * _O2); /// F3 actually. + batch_trimat_madd(tempQ2.l2_F3, Fs->l2_F1, t2, _V1, _V1_BYTE, _O2, _O2_BYTE); // F1*T2 + F3 + batch_mat_madd(tempQ2.l2_F3, Fs->l2_F2, _V1, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // F1_T2 + F2_T3 + F3 + + memset(tempQ.l2_F3, 0, _O2_BYTE * _V1 * _O2); + batch_matTr_madd(tempQ.l2_F3, t2, _V1, _V1_BYTE, _O2, tempQ2.l2_F3, _O2, _O2_BYTE); // T2tr * ( ..... ) + + memcpy(tempQ.l2_F6, Fs->l2_F6, _O2_BYTE * _O1 * _O2); + batch_trimat_madd(tempQ.l2_F6, Fs->l2_F5, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // F5*T3 + F6 + + batch_matTr_madd(tempQ.l2_F3, Ts->t3, _O1, _O1_BYTE, _O2, tempQ.l2_F6, _O2, _O2_BYTE); // T2tr*( ..... ) + T3tr*( ..... ) + memset(Qs->l2_Q9, 0, _O2_BYTE * N_TRIANGLE_TERMS(_O2)); + PQCLEAN_RAINBOWIACYCLIC_CLEAN_UpperTrianglize(Qs->l2_Q9, tempQ.l2_F3, _O2, _O2_BYTE); // Q9 +} + +// Choosing implementations depends on the macros: _BLAS_SSE_ and _BLAS_AVX2_ +#define calculate_F_from_Q_impl calculate_F_from_Q_ref +#define calculate_Q_from_F_cyclic_impl calculate_Q_from_F_cyclic_ref + +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_calculate_F_from_Q(sk_t *Fs, const sk_t *Qs, sk_t *Ts) { + calculate_F_from_Q_impl(Fs, Qs, Ts); +} + +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_calculate_Q_from_F_cyclic(cpk_t *Qs, const sk_t *Fs, const sk_t *Ts) { + calculate_Q_from_F_cyclic_impl(Qs, Fs, Ts); +} diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/rainbow_keypair_computation.h b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/rainbow_keypair_computation.h new file mode 100644 index 0000000000..9416abb4cb --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/rainbow_keypair_computation.h @@ -0,0 +1,71 @@ +#ifndef _RAINBOW_KEYPAIR_COMP_H_ +#define _RAINBOW_KEYPAIR_COMP_H_ +/// @file rainbow_keypair_computation.h +/// @brief Functions for calculating pk/sk while generating keys. +/// +/// Defining an internal structure of public key. +/// Functions for calculating pk/sk for key generation. +/// + +#include "rainbow_keypair.h" + +/// @brief The (internal use) public key for rainbow +/// +/// The (internal use) public key for rainbow. The public +/// polynomials are divided into l1_Q1, l1_Q2, ... l1_Q9, +/// l2_Q1, .... , l2_Q9. +/// +typedef struct rainbow_extend_publickey { + unsigned char l1_Q1[_O1_BYTE * N_TRIANGLE_TERMS(_V1)]; + unsigned char l1_Q2[_O1_BYTE * _V1 * _O1]; + unsigned char l1_Q3[_O1_BYTE * _V1 * _O2]; + unsigned char l1_Q5[_O1_BYTE * N_TRIANGLE_TERMS(_O1)]; + unsigned char l1_Q6[_O1_BYTE * _O1 * _O2]; + unsigned char l1_Q9[_O1_BYTE * N_TRIANGLE_TERMS(_O2)]; + + unsigned char l2_Q1[_O2_BYTE * N_TRIANGLE_TERMS(_V1)]; + unsigned char l2_Q2[_O2_BYTE * _V1 * _O1]; + unsigned char l2_Q3[_O2_BYTE * _V1 * _O2]; + unsigned char l2_Q5[_O2_BYTE * N_TRIANGLE_TERMS(_O1)]; + unsigned char l2_Q6[_O2_BYTE * _O1 * _O2]; + unsigned char l2_Q9[_O2_BYTE * N_TRIANGLE_TERMS(_O2)]; +} ext_cpk_t; + +/// +/// @brief converting formats of public keys : from ext_cpk_t version to pk_t +/// +/// @param[out] pk - the classic public key. +/// @param[in] cpk - the internel public key. +/// +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_extcpk_to_pk(pk_t *pk, const ext_cpk_t *cpk); +///////////////////////////////////////////////// + +/// +/// @brief Computing public key from secret key +/// +/// @param[out] Qs - the public key +/// @param[in] Fs - parts of the secret key: l1_F1, l1_F2, l2_F1, l2_F2, l2_F3, l2_F5, l2_F6 +/// @param[in] Ts - parts of the secret key: T1, T4, T3 +/// +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_calculate_Q_from_F(ext_cpk_t *Qs, const sk_t *Fs, const sk_t *Ts); + + +/// +/// @brief Computing parts of the sk from parts of pk and sk +/// +/// @param[out] Fs - parts of the sk: l1_F1, l1_F2, l2_F1, l2_F2, l2_F3, l2_F5, l2_F6 +/// @param[in] Qs - parts of the pk: l1_Q1, l1_Q2, l2_Q1, l2_Q2, l2_Q3, l2_Q5, l2_Q6 +/// @param[in] Ts - parts of the sk: T1, T4, T3 +/// +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_calculate_F_from_Q(sk_t *Fs, const sk_t *Qs, sk_t *Ts); + +/// +/// @brief Computing parts of the pk from the secret key +/// +/// @param[out] Qs - parts of the pk: l1_Q3, l1_Q5, l2_Q6, l1_Q9, l2_Q9 +/// @param[in] Fs - parts of the sk: l1_F1, l1_F2, l2_F1, l2_F2, l2_F3, l2_F5, l2_F6 +/// @param[in] Ts - parts of the sk: T1, T4, T3 +/// +void PQCLEAN_RAINBOWIACYCLIC_CLEAN_calculate_Q_from_F_cyclic(cpk_t *Qs, const sk_t *Fs, const sk_t *Ts); + +#endif // _RAINBOW_KEYPAIR_COMP_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/sign.c b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/sign.c new file mode 100644 index 0000000000..e0a2abc435 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/sign.c @@ -0,0 +1,76 @@ +/// @file sign.c +/// @brief the implementations for functions in api.h +/// +/// + +#include "api.h" +#include "rainbow.h" +#include "rainbow_config.h" +#include "rainbow_keypair.h" +#include "randombytes.h" +#include "utils_hash.h" +#include +#include + +int PQCLEAN_RAINBOWIACYCLIC_CLEAN_crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { + unsigned char sk_seed[LEN_SKSEED] = {0}; + randombytes(sk_seed, LEN_SKSEED); + + unsigned char pk_seed[LEN_PKSEED] = {0}; + randombytes(pk_seed, LEN_PKSEED); + PQCLEAN_RAINBOWIACYCLIC_CLEAN_generate_keypair_cyclic((cpk_t *)pk, (sk_t *)sk, pk_seed, sk_seed); + return 0; +} + +int PQCLEAN_RAINBOWIACYCLIC_CLEAN_crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { + unsigned char digest[_HASH_LEN]; + + PQCLEAN_RAINBOWIACYCLIC_CLEAN_hash_msg(digest, _HASH_LEN, m, mlen); + + memcpy(sm, m, mlen); + smlen[0] = mlen + _SIGNATURE_BYTE; + + return PQCLEAN_RAINBOWIACYCLIC_CLEAN_rainbow_sign(sm + mlen, (const sk_t *)sk, digest); +} + +int PQCLEAN_RAINBOWIACYCLIC_CLEAN_crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { + int rc; + if (_SIGNATURE_BYTE > smlen) { + rc = -1; + } else { + *mlen = smlen - _SIGNATURE_BYTE; + + unsigned char digest[_HASH_LEN]; + PQCLEAN_RAINBOWIACYCLIC_CLEAN_hash_msg(digest, _HASH_LEN, sm, *mlen); + + rc = PQCLEAN_RAINBOWIACYCLIC_CLEAN_rainbow_verify_cyclic(digest, sm + mlen[0], (const cpk_t *)pk); + } + if (!rc) { + memmove(m, sm, smlen - _SIGNATURE_BYTE); + } else { // bad signature + *mlen = (size_t) -1; + memset(m, 0, smlen); + } + return rc; +} + +int PQCLEAN_RAINBOWIACYCLIC_CLEAN_crypto_sign_signature( + uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + unsigned char digest[_HASH_LEN]; + + PQCLEAN_RAINBOWIACYCLIC_CLEAN_hash_msg(digest, _HASH_LEN, m, mlen); + *siglen = _SIGNATURE_BYTE; + return PQCLEAN_RAINBOWIACYCLIC_CLEAN_rainbow_sign(sig, (const sk_t *)sk, digest); +} + +int PQCLEAN_RAINBOWIACYCLIC_CLEAN_crypto_sign_verify( + const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + if (siglen != _SIGNATURE_BYTE) { + return -1; + } + unsigned char digest[_HASH_LEN]; + PQCLEAN_RAINBOWIACYCLIC_CLEAN_hash_msg(digest, _HASH_LEN, m, mlen); + return PQCLEAN_RAINBOWIACYCLIC_CLEAN_rainbow_verify_cyclic(digest, sig, (const cpk_t *)pk); +} diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/utils_hash.c b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/utils_hash.c new file mode 100644 index 0000000000..dba6a6330d --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/utils_hash.c @@ -0,0 +1,50 @@ +/// @file utils_hash.c +/// @brief the adapter for SHA2 families. +/// +/// + +#include "utils_hash.h" +#include "rainbow_config.h" +#include "sha2.h" + +static inline int _hash(unsigned char *digest, const unsigned char *m, size_t mlen) { + sha256(digest, m, mlen); + return 0; +} + +static inline int expand_hash(unsigned char *digest, size_t n_digest, const unsigned char *hash) { + if (_HASH_LEN >= n_digest) { + for (size_t i = 0; i < n_digest; i++) { + digest[i] = hash[i]; + } + return 0; + } + for (size_t i = 0; i < _HASH_LEN; i++) { + digest[i] = hash[i]; + } + n_digest -= _HASH_LEN; + + while (_HASH_LEN <= n_digest) { + _hash(digest + _HASH_LEN, digest, _HASH_LEN); + + n_digest -= _HASH_LEN; + digest += _HASH_LEN; + } + unsigned char temp[_HASH_LEN]; + if (n_digest) { + _hash(temp, digest, _HASH_LEN); + for (size_t i = 0; i < n_digest; i++) { + digest[_HASH_LEN + i] = temp[i]; + } + } + return 0; +} + +int PQCLEAN_RAINBOWIACYCLIC_CLEAN_hash_msg(unsigned char *digest, + size_t len_digest, + const unsigned char *m, + size_t mlen) { + unsigned char buf[_HASH_LEN]; + _hash(buf, m, mlen); + return expand_hash(digest, len_digest, buf); +} diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/utils_hash.h b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/utils_hash.h new file mode 100644 index 0000000000..da601579a5 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/utils_hash.h @@ -0,0 +1,11 @@ +#ifndef _UTILS_HASH_H_ +#define _UTILS_HASH_H_ +/// @file utils_hash.h +/// @brief the interface for adapting hash functions. +/// + +#include + +int PQCLEAN_RAINBOWIACYCLIC_CLEAN_hash_msg(unsigned char *digest, size_t len_digest, const unsigned char *m, size_t mlen); + +#endif // _UTILS_HASH_H_ diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/utils_prng.c b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/utils_prng.c new file mode 100644 index 0000000000..8f3b3fcdd8 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/utils_prng.c @@ -0,0 +1,97 @@ +/// @file utils_prng.c +/// @brief The implementation of PRNG related functions. +/// + +#include "utils_prng.h" +#include "aes.h" +#include "randombytes.h" +#include "utils_hash.h" +#include +#include + +static void prng_update(const unsigned char *provided_data, + unsigned char *Key, + unsigned char *V) { + unsigned char temp[48]; + aes256ctx ctx; + aes256_keyexp(&ctx, Key); + for (int i = 0; i < 3; i++) { + //increment V + for (int j = 15; j >= 0; j--) { + if (V[j] == 0xff) { + V[j] = 0x00; + } else { + V[j]++; + break; + } + } + aes256_ecb(temp + 16 * i, V, 1, &ctx); + } + if (provided_data != NULL) { + for (int i = 0; i < 48; i++) { + temp[i] ^= provided_data[i]; + } + } + aes256_ctx_release(&ctx); + memcpy(Key, temp, 32); + memcpy(V, temp + 32, 16); +} +static void randombytes_init_with_state(prng_t *state, + unsigned char *entropy_input_48bytes) { + memset(state->Key, 0x00, 32); + memset(state->V, 0x00, 16); + prng_update(entropy_input_48bytes, state->Key, state->V); +} + +static int randombytes_with_state(prng_t *state, + unsigned char *x, + size_t xlen) { + + unsigned char block[16]; + int i = 0; + + aes256ctx ctx; + aes256_keyexp(&ctx, state->Key); + + while (xlen > 0) { + //increment V + for (int j = 15; j >= 0; j--) { + if (state->V[j] == 0xff) { + state->V[j] = 0x00; + } else { + state->V[j]++; + break; + } + } + aes256_ecb(block, state->V, 1, &ctx); + if (xlen > 15) { + memcpy(x + i, block, 16); + i += 16; + xlen -= 16; + } else { + memcpy(x + i, block, xlen); + xlen = 0; + } + } + aes256_ctx_release(&ctx); + prng_update(NULL, state->Key, state->V); + return 0; +} + +int PQCLEAN_RAINBOWIACYCLIC_CLEAN_prng_set(prng_t *ctx, const void *prng_seed, unsigned long prng_seedlen) { + unsigned char seed[48]; + if (prng_seedlen >= 48) { + memcpy(seed, prng_seed, 48); + } else { + memcpy(seed, prng_seed, prng_seedlen); + PQCLEAN_RAINBOWIACYCLIC_CLEAN_hash_msg(seed + prng_seedlen, 48 - (unsigned)prng_seedlen, (const unsigned char *)prng_seed, prng_seedlen); + } + + randombytes_init_with_state(ctx, seed); + + return 0; +} + +int PQCLEAN_RAINBOWIACYCLIC_CLEAN_prng_gen(prng_t *ctx, unsigned char *out, unsigned long outlen) { + return randombytes_with_state(ctx, out, outlen); +} diff --git a/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/utils_prng.h b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/utils_prng.h new file mode 100644 index 0000000000..4465547ee7 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowIa-cyclic_clean/utils_prng.h @@ -0,0 +1,18 @@ +#ifndef _UTILS_PRNG_H_ +#define _UTILS_PRNG_H_ +/// @file utils_prng.h +/// @brief the interface for adapting PRNG functions. +/// +/// + +#include "randombytes.h" + +typedef struct { + unsigned char Key[32]; + unsigned char V[16]; +} prng_t; + +int PQCLEAN_RAINBOWIACYCLIC_CLEAN_prng_set(prng_t *ctx, const void *prng_seed, unsigned long prng_seedlen); +int PQCLEAN_RAINBOWIACYCLIC_CLEAN_prng_gen(prng_t *ctx, unsigned char *out, unsigned long outlen); + +#endif // _UTILS_PRNG_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-classic_clean/LICENSE b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/LICENSE new file mode 100644 index 0000000000..cb00a6e354 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/LICENSE @@ -0,0 +1,8 @@ +`Software implementation of Rainbow for NIST R2 submission' by Ming-Shing Chen + +To the extent possible under law, the person who associated CC0 with +`Software implementation of Rainbow for NIST R2 submission' has waived all copyright and related or neighboring rights +to `Software implementation of Rainbow for NIST R2 submission'. + +You should have received a copy of the CC0 legalcode along with this +work. If not, see . diff --git a/src/sig/rainbow/pqclean_rainbowVc-classic_clean/api.h b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/api.h new file mode 100644 index 0000000000..11edfb1494 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/api.h @@ -0,0 +1,32 @@ +#ifndef PQCLEAN_RAINBOWVCCLASSIC_CLEAN_API_H +#define PQCLEAN_RAINBOWVCCLASSIC_CLEAN_API_H + +#include +#include + +#define PQCLEAN_RAINBOWVCCLASSIC_CLEAN_CRYPTO_SECRETKEYBYTES 1227104 +#define PQCLEAN_RAINBOWVCCLASSIC_CLEAN_CRYPTO_PUBLICKEYBYTES 1705536 +#define PQCLEAN_RAINBOWVCCLASSIC_CLEAN_CRYPTO_BYTES 204 +#define PQCLEAN_RAINBOWVCCLASSIC_CLEAN_CRYPTO_ALGNAME "RAINBOW(256,92,48,48) - classic" + +int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + + +int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_crypto_sign_signature( + uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_crypto_sign_verify( + const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + + +#endif diff --git a/src/sig/rainbow/pqclean_rainbowVc-classic_clean/blas.c b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/blas.c new file mode 100644 index 0000000000..7bc7b48963 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/blas.c @@ -0,0 +1,31 @@ +#include "blas.h" +#include "gf.h" + +#include + +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_predicated_add(uint8_t *accu_b, uint8_t predicate, const uint8_t *a, size_t _num_byte) { + uint8_t pr_u8 = (uint8_t) ((uint8_t) 0 - predicate); + for (size_t i = 0; i < _num_byte; i++) { + accu_b[i] ^= (a[i] & pr_u8); + } +} + +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_add(uint8_t *accu_b, const uint8_t *a, size_t _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + accu_b[i] ^= a[i]; + } +} + + +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_mul_scalar(uint8_t *a, uint8_t b, size_t _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + a[i] = PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256_mul(a[i], b); + } +} + +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_madd(uint8_t *accu_c, const uint8_t *a, uint8_t gf256_b, size_t _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + accu_c[i] ^= PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256_mul(a[i], gf256_b); + } +} + diff --git a/src/sig/rainbow/pqclean_rainbowVc-classic_clean/blas.h b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/blas.h new file mode 100644 index 0000000000..426f09a09b --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/blas.h @@ -0,0 +1,19 @@ +#ifndef _BLAS_H_ +#define _BLAS_H_ +/// @file blas.h +/// @brief Functions for implementing basic linear algebra functions. +/// + +#include "rainbow_config.h" +#include +#include + +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_predicated_add(uint8_t *accu_b, uint8_t predicate, const uint8_t *a, size_t _num_byte); +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_add(uint8_t *accu_b, const uint8_t *a, size_t _num_byte); + + +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_mul_scalar(uint8_t *a, uint8_t b, size_t _num_byte); +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_madd(uint8_t *accu_c, const uint8_t *a, uint8_t gf256_b, size_t _num_byte); + + +#endif // _BLAS_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-classic_clean/blas_comm.c b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/blas_comm.c new file mode 100644 index 0000000000..2242e16b62 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/blas_comm.c @@ -0,0 +1,144 @@ +/// @file blas_comm.c +/// @brief The standard implementations for blas_comm.h +/// + +#include "blas_comm.h" +#include "blas.h" +#include "gf.h" +#include "rainbow_config.h" + +#include +#include + +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_set_zero(uint8_t *b, unsigned int _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + b[i] = 0; + } +} +/// @brief get an element from GF(256) vector . +/// +/// @param[in] a - the input vector a. +/// @param[in] i - the index in the vector a. +/// @return the value of the element. +/// +uint8_t PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_get_ele(const uint8_t *a, unsigned int i) { + return a[i]; +} + +unsigned int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_is_zero(const uint8_t *a, unsigned int _num_byte) { + uint8_t r = 0; + while (_num_byte--) { + r |= a[0]; + a++; + } + return (0 == r); +} + +/// polynomial multplication +/// School boook +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_polymul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int _num) { + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_set_zero(c, _num * 2 - 1); + for (unsigned int i = 0; i < _num; i++) { + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_madd(c + i, a, b[i], _num); + } +} + +static void gf256mat_prod_ref(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b) { + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_set_zero(c, n_A_vec_byte); + for (unsigned int i = 0; i < n_A_width; i++) { + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_madd(c, matA, b[i], n_A_vec_byte); + matA += n_A_vec_byte; + } +} + +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256mat_mul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int len_vec) { + unsigned int n_vec_byte = len_vec; + for (unsigned int k = 0; k < len_vec; k++) { + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_set_zero(c, n_vec_byte); + const uint8_t *bk = b + n_vec_byte * k; + for (unsigned int i = 0; i < len_vec; i++) { + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_madd(c, a + n_vec_byte * i, bk[i], n_vec_byte); + } + c += n_vec_byte; + } +} + +static unsigned int gf256mat_gauss_elim_ref(uint8_t *mat, unsigned int h, unsigned int w) { + unsigned int r8 = 1; + + for (unsigned int i = 0; i < h; i++) { + uint8_t *ai = mat + w * i; + unsigned int skip_len_align4 = i & ((unsigned int)~0x3); + + for (unsigned int j = i + 1; j < h; j++) { + uint8_t *aj = mat + w * j; + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_predicated_add(ai + skip_len_align4, !PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256_is_nonzero(ai[i]), aj + skip_len_align4, w - skip_len_align4); + } + r8 &= PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256_is_nonzero(ai[i]); + uint8_t pivot = ai[i]; + pivot = PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256_inv(pivot); + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_mul_scalar(ai + skip_len_align4, pivot, w - skip_len_align4); + for (unsigned int j = 0; j < h; j++) { + if (i == j) { + continue; + } + uint8_t *aj = mat + w * j; + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_madd(aj + skip_len_align4, ai + skip_len_align4, aj[i], w - skip_len_align4); + } + } + + return r8; +} + +static unsigned int gf256mat_solve_linear_eq_ref(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n) { + uint8_t mat[64 * 64]; + for (unsigned int i = 0; i < n; i++) { + memcpy(mat + i * (n + 1), inp_mat + i * n, n); + mat[i * (n + 1) + n] = c_terms[i]; + } + unsigned int r8 = PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256mat_gauss_elim(mat, n, n + 1); + for (unsigned int i = 0; i < n; i++) { + sol[i] = mat[i * (n + 1) + n]; + } + return r8; +} + +static inline void gf256mat_submat(uint8_t *mat2, unsigned int w2, unsigned int st, const uint8_t *mat, unsigned int w, unsigned int h) { + for (unsigned int i = 0; i < h; i++) { + for (unsigned int j = 0; j < w2; j++) { + mat2[i * w2 + j] = mat[i * w + st + j]; + } + } +} + +unsigned int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256mat_inv(uint8_t *inv_a, const uint8_t *a, unsigned int H, uint8_t *buffer) { + uint8_t *aa = buffer; + for (unsigned int i = 0; i < H; i++) { + uint8_t *ai = aa + i * 2 * H; + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_set_zero(ai, 2 * H); + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_add(ai, a + i * H, H); + ai[H + i] = 1; + } + unsigned int r8 = PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256mat_gauss_elim(aa, H, 2 * H); + gf256mat_submat(inv_a, H, H, aa, 2 * H, H); + return r8; +} + + +// choosing the implementations depends on the macros _BLAS_AVX2_ and _BLAS_SSE + +#define gf256mat_prod_impl gf256mat_prod_ref +#define gf256mat_gauss_elim_impl gf256mat_gauss_elim_ref +#define gf256mat_solve_linear_eq_impl gf256mat_solve_linear_eq_ref +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256mat_prod(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b) { + gf256mat_prod_impl(c, matA, n_A_vec_byte, n_A_width, b); +} + +unsigned int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256mat_gauss_elim(uint8_t *mat, unsigned int h, unsigned int w) { + return gf256mat_gauss_elim_impl(mat, h, w); +} + +unsigned int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256mat_solve_linear_eq(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n) { + return gf256mat_solve_linear_eq_impl(sol, inp_mat, c_terms, n); +} + diff --git a/src/sig/rainbow/pqclean_rainbowVc-classic_clean/blas_comm.h b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/blas_comm.h new file mode 100644 index 0000000000..55be9b5eb9 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/blas_comm.h @@ -0,0 +1,90 @@ +#ifndef _BLAS_COMM_H_ +#define _BLAS_COMM_H_ +/// @file blas_comm.h +/// @brief Common functions for linear algebra. +/// + +#include "rainbow_config.h" +#include + +/// @brief set a vector to 0. +/// +/// @param[in,out] b - the vector b. +/// @param[in] _num_byte - number of bytes for the vector b. +/// +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_set_zero(uint8_t *b, unsigned int _num_byte); + +/// @brief get an element from GF(256) vector . +/// +/// @param[in] a - the input vector a. +/// @param[in] i - the index in the vector a. +/// @return the value of the element. +/// +uint8_t PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_get_ele(const uint8_t *a, unsigned int i); + +/// @brief check if a vector is 0. +/// +/// @param[in] a - the vector a. +/// @param[in] _num_byte - number of bytes for the vector a. +/// @return 1(true) if a is 0. 0(false) else. +/// +unsigned int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_is_zero(const uint8_t *a, unsigned int _num_byte); + +/// @brief polynomial multiplication: c = a*b +/// +/// @param[out] c - the output polynomial c +/// @param[in] a - the vector a. +/// @param[in] b - the vector b. +/// @param[in] _num - number of elements for the polynomials a and b. +/// +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_polymul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int _num); + +/// @brief matrix-vector multiplication: c = matA * b , in GF(256) +/// +/// @param[out] c - the output vector c +/// @param[in] matA - a column-major matrix A. +/// @param[in] n_A_vec_byte - the size of column vectors in bytes. +/// @param[in] n_A_width - the width of matrix A. +/// @param[in] b - the vector b. +/// +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256mat_prod(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b); + +/// @brief matrix-matrix multiplication: c = a * b , in GF(256) +/// +/// @param[out] c - the output matrix c +/// @param[in] c - a matrix a. +/// @param[in] b - a matrix b. +/// @param[in] len_vec - the length of column vectors. +/// +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256mat_mul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int len_vec); + +/// @brief Gauss elimination for a matrix, in GF(256) +/// +/// @param[in,out] mat - the matrix. +/// @param[in] h - the height of the matrix. +/// @param[in] w - the width of the matrix. +/// @return 1(true) if success. 0(false) if the matrix is singular. +/// +unsigned int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256mat_gauss_elim(uint8_t *mat, unsigned int h, unsigned int w); + +/// @brief Solving linear equations, in GF(256) +/// +/// @param[out] sol - the solutions. +/// @param[in] inp_mat - the matrix parts of input equations. +/// @param[in] c_terms - the constant terms of the input equations. +/// @param[in] n - the number of equations. +/// @return 1(true) if success. 0(false) if the matrix is singular. +/// +unsigned int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256mat_solve_linear_eq(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n); + +/// @brief Computing the inverse matrix, in GF(256) +/// +/// @param[out] inv_a - the output of matrix a. +/// @param[in] a - a matrix a. +/// @param[in] H - height of matrix a, i.e., matrix a is an HxH matrix. +/// @param[in] buffer - The buffer for computations. it has to be as large as 2 input matrixes. +/// @return 1(true) if success. 0(false) if the matrix is singular. +/// +unsigned int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256mat_inv(uint8_t *inv_a, const uint8_t *a, unsigned int H, uint8_t *buffer); + +#endif // _BLAS_COMM_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-classic_clean/gf.c b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/gf.c new file mode 100644 index 0000000000..048d193726 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/gf.c @@ -0,0 +1,91 @@ +#include "gf.h" + +//// gf4 := gf2[x]/x^2+x+1 +static inline uint8_t gf4_mul_2(uint8_t a) { + uint8_t r = (uint8_t)(a << 1); + r ^= (uint8_t)((a >> 1) * 7); + return r; +} + +static inline uint8_t gf4_mul(uint8_t a, uint8_t b) { + uint8_t r = (uint8_t)(a * (b & 1)); + return r ^ (uint8_t)(gf4_mul_2(a) * (b >> 1)); +} + +static inline uint8_t gf4_squ(uint8_t a) { + return a ^ (a >> 1); +} + +//// gf16 := gf4[y]/y^2+y+x +uint8_t PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf16_mul(uint8_t a, uint8_t b) { + uint8_t a0 = a & 3; + uint8_t a1 = (a >> 2); + uint8_t b0 = b & 3; + uint8_t b1 = (b >> 2); + uint8_t a0b0 = gf4_mul(a0, b0); + uint8_t a1b1 = gf4_mul(a1, b1); + uint8_t a0b1_a1b0 = gf4_mul(a0 ^ a1, b0 ^ b1) ^ a0b0 ^ a1b1; + uint8_t a1b1_x2 = gf4_mul_2(a1b1); + return (uint8_t)((a0b1_a1b0 ^ a1b1) << 2 ^ a0b0 ^ a1b1_x2); +} + +static inline uint8_t gf16_squ(uint8_t a) { + uint8_t a0 = a & 3; + uint8_t a1 = (a >> 2); + a1 = gf4_squ(a1); + uint8_t a1squ_x2 = gf4_mul_2(a1); + return (uint8_t)((a1 << 2) ^ a1squ_x2 ^ gf4_squ(a0)); +} + +uint8_t PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256_is_nonzero(uint8_t a) { + unsigned int a8 = a; + unsigned int r = ((unsigned int)0) - a8; + r >>= 8; + return r & 1; +} + +static inline uint8_t gf4_mul_3(uint8_t a) { + uint8_t msk = (uint8_t)((a - 2) >> 1); + return (uint8_t)((msk & ((int)a * 3)) | ((~msk) & ((int)a - 1))); +} +static inline uint8_t gf16_mul_8(uint8_t a) { + uint8_t a0 = a & 3; + uint8_t a1 = a >> 2; + return (uint8_t)((gf4_mul_2(a0 ^ a1) << 2) | gf4_mul_3(a1)); +} + +// gf256 := gf16[X]/X^2+X+xy +uint8_t PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256_mul(uint8_t a, uint8_t b) { + uint8_t a0 = a & 15; + uint8_t a1 = (a >> 4); + uint8_t b0 = b & 15; + uint8_t b1 = (b >> 4); + uint8_t a0b0 = PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf16_mul(a0, b0); + uint8_t a1b1 = PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf16_mul(a1, b1); + uint8_t a0b1_a1b0 = PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf16_mul(a0 ^ a1, b0 ^ b1) ^ a0b0 ^ a1b1; + uint8_t a1b1_x8 = gf16_mul_8(a1b1); + return (uint8_t)((a0b1_a1b0 ^ a1b1) << 4 ^ a0b0 ^ a1b1_x8); +} + +static inline uint8_t gf256_squ(uint8_t a) { + uint8_t a0 = a & 15; + uint8_t a1 = (a >> 4); + a1 = gf16_squ(a1); + uint8_t a1squ_x8 = gf16_mul_8(a1); + return (uint8_t)((a1 << 4) ^ a1squ_x8 ^ gf16_squ(a0)); +} + +uint8_t PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256_inv(uint8_t a) { + // 128+64+32+16+8+4+2 = 254 + uint8_t a2 = gf256_squ(a); + uint8_t a4 = gf256_squ(a2); + uint8_t a8 = gf256_squ(a4); + uint8_t a4_2 = PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256_mul(a4, a2); + uint8_t a8_4_2 = PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256_mul(a4_2, a8); + uint8_t a64_ = gf256_squ(a8_4_2); + a64_ = gf256_squ(a64_); + a64_ = gf256_squ(a64_); + uint8_t a64_2 = PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256_mul(a64_, a8_4_2); + uint8_t a128_ = gf256_squ(a64_2); + return PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256_mul(a2, a128_); +} diff --git a/src/sig/rainbow/pqclean_rainbowVc-classic_clean/gf.h b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/gf.h new file mode 100644 index 0000000000..5053e82ad9 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/gf.h @@ -0,0 +1,19 @@ +#ifndef _GF16_H_ +#define _GF16_H_ + +#include "rainbow_config.h" +#include + +/// @file gf16.h +/// @brief Library for arithmetics in GF(16) and GF(256) +/// + +uint8_t PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf16_mul(uint8_t a, uint8_t b); + + +uint8_t PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256_is_nonzero(uint8_t a); +uint8_t PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256_inv(uint8_t a); +uint8_t PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256_mul(uint8_t a, uint8_t b); + + +#endif // _GF16_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-classic_clean/parallel_matrix_op.c b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/parallel_matrix_op.c new file mode 100644 index 0000000000..89d75ed946 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/parallel_matrix_op.c @@ -0,0 +1,183 @@ +/// @file parallel_matrix_op.c +/// @brief the standard implementations for functions in parallel_matrix_op.h +/// +/// the standard implementations for functions in parallel_matrix_op.h +/// + +#include "parallel_matrix_op.h" +#include "blas.h" +#include "blas_comm.h" + +/// +/// @brief Calculate the corresponding index in an array for an upper-triangle(UT) matrix. +/// +/// @param[in] i_row - the i-th row in an upper-triangle matrix. +/// @param[in] j_col - the j-th column in an upper-triangle matrix. +/// @param[in] dim - the dimension of the upper-triangle matrix, i.e., an dim x dim matrix. +/// @return the corresponding index in an array storage. +/// +unsigned int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_idx_of_trimat(unsigned int i_row, unsigned int j_col, unsigned int dim) { + return (dim + dim - i_row + 1) * i_row / 2 + j_col - i_row; +} + +/// +/// @brief Calculate the corresponding index in an array for an upper-triangle or lower-triangle matrix. +/// +/// @param[in] i_row - the i-th row in a triangle matrix. +/// @param[in] j_col - the j-th column in a triangle matrix. +/// @param[in] dim - the dimension of the triangle matrix, i.e., an dim x dim matrix. +/// @return the corresponding index in an array storage. +/// +static inline unsigned int idx_of_2trimat(unsigned int i_row, unsigned int j_col, unsigned int n_var) { + if (i_row > j_col) { + return PQCLEAN_RAINBOWVCCLASSIC_CLEAN_idx_of_trimat(j_col, i_row, n_var); + } + return PQCLEAN_RAINBOWVCCLASSIC_CLEAN_idx_of_trimat(i_row, j_col, n_var); +} + +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_UpperTrianglize(unsigned char *btriC, const unsigned char *bA, unsigned int Awidth, unsigned int size_batch) { + unsigned char *runningC = btriC; + unsigned int Aheight = Awidth; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < i; j++) { + unsigned int idx = PQCLEAN_RAINBOWVCCLASSIC_CLEAN_idx_of_trimat(j, i, Aheight); + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_add(btriC + idx * size_batch, bA + size_batch * (i * Awidth + j), size_batch); + } + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_add(runningC, bA + size_batch * (i * Awidth + i), size_batch * (Aheight - i)); + runningC += size_batch * (Aheight - i); + } +} + +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Awidth = Bheight; + unsigned int Aheight = Awidth; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + if (k < i) { + continue; + } + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_madd(bC, &btriA[(k - i) * size_batch], PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + btriA += (Aheight - i) * size_batch; + } +} + +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_trimatTr_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Aheight = Bheight; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + if (i < k) { + continue; + } + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_madd(bC, &btriA[size_batch * (PQCLEAN_RAINBOWVCCLASSIC_CLEAN_idx_of_trimat(k, i, Aheight))], PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_2trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Aheight = Bheight; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + if (i == k) { + continue; + } + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_madd(bC, &btriA[size_batch * (idx_of_2trimat(i, k, Aheight))], PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_matTr_madd_gf256(unsigned char *bC, const unsigned char *A_to_tr, unsigned int Aheight, unsigned int size_Acolvec, unsigned int Awidth, + const unsigned char *bB, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Atr_height = Awidth; + unsigned int Atr_width = Aheight; + for (unsigned int i = 0; i < Atr_height; i++) { + for (unsigned int j = 0; j < Atr_width; j++) { + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_madd(bC, &bB[j * Bwidth * size_batch], PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_get_ele(&A_to_tr[size_Acolvec * i], j), size_batch * Bwidth); + } + bC += size_batch * Bwidth; + } +} + +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_bmatTr_madd_gf256(unsigned char *bC, const unsigned char *bA_to_tr, unsigned int Awidth_before_tr, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + const unsigned char *bA = bA_to_tr; + unsigned int Aheight = Awidth_before_tr; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_madd(bC, &bA[size_batch * (i + k * Aheight)], PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_mat_madd_gf256(unsigned char *bC, const unsigned char *bA, unsigned int Aheight, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Awidth = Bheight; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_madd(bC, &bA[k * size_batch], PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + bA += (Awidth) * size_batch; + } +} + +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_quad_trimat_eval_gf256(unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned int dim, unsigned int size_batch) { + unsigned char tmp[256]; + + unsigned char _x[256]; + for (unsigned int i = 0; i < dim; i++) { + _x[i] = PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_get_ele(x, i); + } + + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_set_zero(y, size_batch); + for (unsigned int i = 0; i < dim; i++) { + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_set_zero(tmp, size_batch); + for (unsigned int j = i; j < dim; j++) { + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_madd(tmp, trimat, _x[j], size_batch); + trimat += size_batch; + } + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_madd(y, tmp, _x[i], size_batch); + } +} + +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_quad_recmat_eval_gf256(unsigned char *z, const unsigned char *y, unsigned int dim_y, const unsigned char *mat, + const unsigned char *x, unsigned dim_x, unsigned size_batch) { + unsigned char tmp[128]; + + unsigned char _x[128]; + for (unsigned int i = 0; i < dim_x; i++) { + _x[i] = PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_get_ele(x, i); + } + unsigned char _y[128]; + for (unsigned int i = 0; i < dim_y; i++) { + _y[i] = PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_get_ele(y, i); + } + + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_set_zero(z, size_batch); + for (unsigned int i = 0; i < dim_y; i++) { + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_set_zero(tmp, size_batch); + for (unsigned int j = 0; j < dim_x; j++) { + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_madd(tmp, mat, _x[j], size_batch); + mat += size_batch; + } + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_madd(z, tmp, _y[i], size_batch); + } +} + diff --git a/src/sig/rainbow/pqclean_rainbowVc-classic_clean/parallel_matrix_op.h b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/parallel_matrix_op.h new file mode 100644 index 0000000000..2af16a7e44 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/parallel_matrix_op.h @@ -0,0 +1,260 @@ +#ifndef _P_MATRIX_OP_H_ +#define _P_MATRIX_OP_H_ +/// @file parallel_matrix_op.h +/// @brief Librarys for operations of batched matrixes. +/// +/// + +//////////////// Section: triangle matrix <-> rectangle matrix /////////////////////////////////// + +/// +/// @brief Calculate the corresponding index in an array for an upper-triangle(UT) matrix. +/// +/// @param[in] i_row - the i-th row in an upper-triangle matrix. +/// @param[in] j_col - the j-th column in an upper-triangle matrix. +/// @param[in] dim - the dimension of the upper-triangle matrix, i.e., an dim x dim matrix. +/// @return the corresponding index in an array storage. +/// +unsigned int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_idx_of_trimat(unsigned int i_row, unsigned int j_col, unsigned int dim); + +/// +/// @brief Upper trianglize a rectangle matrix to the corresponding upper-trangle matrix. +/// +/// @param[out] btriC - the batched upper-trianglized matrix C. +/// @param[in] bA - a batched retangle matrix A. +/// @param[in] bwidth - the width of the batched matrix A, i.e., A is a Awidth x Awidth matrix. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_UpperTrianglize(unsigned char *btriC, const unsigned char *bA, unsigned int Awidth, unsigned int size_batch); + +//////////////////// Section: matrix multiplications /////////////////////////////// + +/// +/// @brief bC += btriA * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_trimat_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += btriA * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += btriA^Tr * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. A will be transposed while multiplying. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_trimatTr_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += btriA^Tr * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A, which will be transposed while multiplying. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_trimatTr_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += (btriA + btriA^Tr) *B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. The operand for multiplication is (btriA + btriA^Tr). +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_2trimat_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += (btriA + btriA^Tr) *B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. The operand for multiplication is (btriA + btriA^Tr). +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_2trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += A^Tr * bB , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] A_to_tr - a column-major matrix A. The operand for multiplication is A^Tr. +/// @param[in] Aheight - the height of A. +/// @param[in] size_Acolvec - the size of a column vector in A. +/// @param[in] Awidth - the width of A. +/// @param[in] bB - a batched matrix B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_matTr_madd_gf16(unsigned char *bC, + const unsigned char *A_to_tr, unsigned int Aheight, unsigned int size_Acolvec, unsigned int Awidth, + const unsigned char *bB, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += A^Tr * bB , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] A_to_tr - a column-major matrix A. The operand for multiplication is A^Tr. +/// @param[in] Aheight - the height of A. +/// @param[in] size_Acolvec - the size of a column vector in A. +/// @param[in] Awidth - the width of A. +/// @param[in] bB - a batched matrix B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_matTr_madd_gf256(unsigned char *bC, + const unsigned char *A_to_tr, unsigned int Aheight, unsigned int size_Acolvec, unsigned int Awidth, + const unsigned char *bB, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA^Tr * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA_to_tr - a batched matrix A. The operand for multiplication is (bA^Tr). +/// @param[in] Awidth_befor_tr - the width of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_bmatTr_madd_gf16(unsigned char *bC, const unsigned char *bA_to_tr, unsigned int Awidth_before_tr, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA^Tr * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA_to_tr - a batched matrix A. The operand for multiplication is (bA^Tr). +/// @param[in] Awidth_befor_tr - the width of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_bmatTr_madd_gf256(unsigned char *bC, const unsigned char *bA_to_tr, unsigned int Awidth_before_tr, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA - a batched matrix A. +/// @param[in] Aheigh - the height of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_mat_madd_gf16(unsigned char *bC, const unsigned char *bA, unsigned int Aheight, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA - a batched matrix A. +/// @param[in] Aheigh - the height of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_mat_madd_gf256(unsigned char *bC, const unsigned char *bA, unsigned int Aheight, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +//////////////////// Section: "quadratric" matrix evaluation /////////////////////////////// + +/// +/// @brief y = x^Tr * trimat * x , in GF(16) +/// +/// @param[out] y - the returned batched element y. +/// @param[in] trimat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim - the dimension of matrix trimat (and x). +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_quad_trimat_eval_gf16(unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned int dim, unsigned int size_batch); + +/// +/// @brief y = x^Tr * trimat * x , in GF(256) +/// +/// @param[out] y - the returned batched element y. +/// @param[in] trimat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim - the dimension of matrix trimat (and x). +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_quad_trimat_eval_gf256(unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned int dim, unsigned int size_batch); + +/// +/// @brief z = y^Tr * mat * x , in GF(16) +/// +/// @param[out] z - the returned batched element z. +/// @param[in] y - an input vector y. +/// @param[in] dim_y - the length of y. +/// @param[in] mat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim_x - the length of x. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_quad_recmat_eval_gf16(unsigned char *z, const unsigned char *y, unsigned int dim_y, + const unsigned char *mat, const unsigned char *x, unsigned int dim_x, unsigned int size_batch); + +/// +/// @brief z = y^Tr * mat * x , in GF(256) +/// +/// @param[out] z - the returned batched element z. +/// @param[in] y - an input vector y. +/// @param[in] dim_y - the length of y. +/// @param[in] mat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim_x - the length of x. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_quad_recmat_eval_gf256(unsigned char *z, const unsigned char *y, unsigned int dim_y, + const unsigned char *mat, const unsigned char *x, unsigned int dim_x, unsigned int size_batch); + +#endif // _P_MATRIX_OP_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-classic_clean/rainbow.c b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/rainbow.c new file mode 100644 index 0000000000..97f7616aed --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/rainbow.c @@ -0,0 +1,168 @@ +/// @file rainbow.c +/// @brief The standard implementations for functions in rainbow.h +/// + +#include "blas.h" +#include "parallel_matrix_op.h" +#include "rainbow.h" +#include "rainbow_blas.h" +#include "rainbow_config.h" +#include "rainbow_keypair.h" +#include "utils_hash.h" +#include "utils_prng.h" +#include +#include +#include + +#define MAX_ATTEMPT_FRMAT 128 + +int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_rainbow_sign(uint8_t *signature, const sk_t *sk, const uint8_t *_digest) { + uint8_t mat_l1[_O1 * _O1_BYTE]; + uint8_t mat_l2[_O2 * _O2_BYTE]; + uint8_t mat_buffer[2 * _MAX_O * _MAX_O_BYTE]; + + // setup PRNG + prng_t prng_sign; + uint8_t prng_preseed[LEN_SKSEED + _HASH_LEN]; + memcpy(prng_preseed, sk->sk_seed, LEN_SKSEED); + memcpy(prng_preseed + LEN_SKSEED, _digest, _HASH_LEN); // prng_preseed = sk_seed || digest + uint8_t prng_seed[_HASH_LEN]; + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_hash_msg(prng_seed, _HASH_LEN, prng_preseed, _HASH_LEN + LEN_SKSEED); + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_prng_set(&prng_sign, prng_seed, _HASH_LEN); // seed = H( sk_seed || digest ) + for (unsigned int i = 0; i < LEN_SKSEED + _HASH_LEN; i++) { + prng_preseed[i] ^= prng_preseed[i]; // clean + } + for (unsigned int i = 0; i < _HASH_LEN; i++) { + prng_seed[i] ^= prng_seed[i]; // clean + } + + // roll vinegars. + uint8_t vinegar[_V1_BYTE]; + unsigned int n_attempt = 0; + unsigned int l1_succ = 0; + while (!l1_succ) { + if (MAX_ATTEMPT_FRMAT <= n_attempt) { + break; + } + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_prng_gen(&prng_sign, vinegar, _V1_BYTE); // generating vinegars + gfmat_prod(mat_l1, sk->l1_F2, _O1 * _O1_BYTE, _V1, vinegar); // generating the linear equations for layer 1 + l1_succ = gfmat_inv(mat_l1, mat_l1, _O1, mat_buffer); // check if the linear equation solvable + n_attempt++; + } + + // Given the vinegars, pre-compute variables needed for layer 2 + uint8_t r_l1_F1[_O1_BYTE] = {0}; + uint8_t r_l2_F1[_O2_BYTE] = {0}; + batch_quad_trimat_eval(r_l1_F1, sk->l1_F1, vinegar, _V1, _O1_BYTE); + batch_quad_trimat_eval(r_l2_F1, sk->l2_F1, vinegar, _V1, _O2_BYTE); + uint8_t mat_l2_F3[_O2 * _O2_BYTE]; + uint8_t mat_l2_F2[_O1 * _O2_BYTE]; + gfmat_prod(mat_l2_F3, sk->l2_F3, _O2 * _O2_BYTE, _V1, vinegar); + gfmat_prod(mat_l2_F2, sk->l2_F2, _O1 * _O2_BYTE, _V1, vinegar); + + // Some local variables. + uint8_t _z[_PUB_M_BYTE]; + uint8_t y[_PUB_M_BYTE]; + uint8_t *x_v1 = vinegar; + uint8_t x_o1[_O1_BYTE]; + uint8_t x_o2[_O1_BYTE]; + + uint8_t digest_salt[_HASH_LEN + _SALT_BYTE]; + memcpy(digest_salt, _digest, _HASH_LEN); + uint8_t *salt = digest_salt + _HASH_LEN; + + uint8_t temp_o[_MAX_O_BYTE + 32] = {0}; + unsigned int succ = 0; + while (!succ) { + if (MAX_ATTEMPT_FRMAT <= n_attempt) { + break; + } + // The computation: H(digest||salt) --> z --S--> y --C-map--> x --T--> w + + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_prng_gen(&prng_sign, salt, _SALT_BYTE); // roll the salt + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_hash_msg(_z, _PUB_M_BYTE, digest_salt, _HASH_LEN + _SALT_BYTE); // H(digest||salt) + + // y = S^-1 * z + memcpy(y, _z, _PUB_M_BYTE); // identity part of S + gfmat_prod(temp_o, sk->s1, _O1_BYTE, _O2, _z + _O1_BYTE); + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_add(y, temp_o, _O1_BYTE); + + // Central Map: + // layer 1: calculate x_o1 + memcpy(temp_o, r_l1_F1, _O1_BYTE); + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_add(temp_o, y, _O1_BYTE); + gfmat_prod(x_o1, mat_l1, _O1_BYTE, _O1, temp_o); + + // layer 2: calculate x_o2 + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_set_zero(temp_o, _O2_BYTE); + gfmat_prod(temp_o, mat_l2_F2, _O2_BYTE, _O1, x_o1); // F2 + batch_quad_trimat_eval(mat_l2, sk->l2_F5, x_o1, _O1, _O2_BYTE); // F5 + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_add(temp_o, mat_l2, _O2_BYTE); + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_add(temp_o, r_l2_F1, _O2_BYTE); // F1 + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_add(temp_o, y + _O1_BYTE, _O2_BYTE); + + // generate the linear equations of the 2nd layer + gfmat_prod(mat_l2, sk->l2_F6, _O2 * _O2_BYTE, _O1, x_o1); // F6 + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_add(mat_l2, mat_l2_F3, _O2 * _O2_BYTE); // F3 + succ = gfmat_inv(mat_l2, mat_l2, _O2, mat_buffer); + gfmat_prod(x_o2, mat_l2, _O2_BYTE, _O2, temp_o); // solve l2 eqs + + n_attempt++; + }; + // w = T^-1 * y + uint8_t w[_PUB_N_BYTE]; + // identity part of T. + memcpy(w, x_v1, _V1_BYTE); + memcpy(w + _V1_BYTE, x_o1, _O1_BYTE); + memcpy(w + _V2_BYTE, x_o2, _O2_BYTE); + // Computing the t1 part. + gfmat_prod(y, sk->t1, _V1_BYTE, _O1, x_o1); + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_add(w, y, _V1_BYTE); + // Computing the t4 part. + gfmat_prod(y, sk->t4, _V1_BYTE, _O2, x_o2); + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_add(w, y, _V1_BYTE); + // Computing the t3 part. + gfmat_prod(y, sk->t3, _O1_BYTE, _O2, x_o2); + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_add(w + _V1_BYTE, y, _O1_BYTE); + + memset(signature, 0, _SIGNATURE_BYTE); // set the output 0 + // clean + memset(&prng_sign, 0, sizeof(prng_t)); + memset(vinegar, 0, _V1_BYTE); + memset(r_l1_F1, 0, _O1_BYTE); + memset(r_l2_F1, 0, _O2_BYTE); + memset(_z, 0, _PUB_M_BYTE); + memset(y, 0, _PUB_M_BYTE); + memset(x_o1, 0, _O1_BYTE); + memset(x_o2, 0, _O2_BYTE); + memset(temp_o, 0, sizeof(temp_o)); + + // return: copy w and salt to the signature. + if (MAX_ATTEMPT_FRMAT <= n_attempt) { + return -1; + } + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_add(signature, w, _PUB_N_BYTE); + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_add(signature + _PUB_N_BYTE, salt, _SALT_BYTE); + return 0; +} + +int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_rainbow_verify(const uint8_t *digest, const uint8_t *signature, const pk_t *pk) { + unsigned char digest_ck[_PUB_M_BYTE]; + // public_map( digest_ck , pk , signature ); Evaluating the quadratic public polynomials. + batch_quad_trimat_eval(digest_ck, pk->pk, signature, _PUB_N, _PUB_M_BYTE); + + unsigned char correct[_PUB_M_BYTE]; + unsigned char digest_salt[_HASH_LEN + _SALT_BYTE]; + memcpy(digest_salt, digest, _HASH_LEN); + memcpy(digest_salt + _HASH_LEN, signature + _PUB_N_BYTE, _SALT_BYTE); + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_hash_msg(correct, _PUB_M_BYTE, digest_salt, _HASH_LEN + _SALT_BYTE); // H( digest || salt ) + + // check consistancy. + unsigned char cc = 0; + for (unsigned int i = 0; i < _PUB_M_BYTE; i++) { + cc |= (digest_ck[i] ^ correct[i]); + } + return (0 == cc) ? 0 : -1; +} + + diff --git a/src/sig/rainbow/pqclean_rainbowVc-classic_clean/rainbow.h b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/rainbow.h new file mode 100644 index 0000000000..e455fe47d5 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/rainbow.h @@ -0,0 +1,33 @@ +#ifndef _RAINBOW_H_ +#define _RAINBOW_H_ +/// @file rainbow.h +/// @brief APIs for rainbow. +/// + +#include "rainbow_config.h" +#include "rainbow_keypair.h" + +#include + +/// +/// @brief Signing function for classical secret key. +/// +/// @param[out] signature - the signature. +/// @param[in] sk - the secret key. +/// @param[in] digest - the digest. +/// +int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_rainbow_sign(uint8_t *signature, const sk_t *sk, const uint8_t *digest); + +/// +/// @brief Verifying function. +/// +/// @param[in] digest - the digest. +/// @param[in] signature - the signature. +/// @param[in] pk - the public key. +/// @return 0 for successful verified. -1 for failed verification. +/// +int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_rainbow_verify(const uint8_t *digest, const uint8_t *signature, const pk_t *pk); + + + +#endif // _RAINBOW_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-classic_clean/rainbow_blas.h b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/rainbow_blas.h new file mode 100644 index 0000000000..d4a0d1cc37 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/rainbow_blas.h @@ -0,0 +1,32 @@ +#ifndef _RAINBOW_BLAS_H_ +#define _RAINBOW_BLAS_H_ +/// @file rainbow_blas.h +/// @brief Defining the functions used in rainbow.c acconding to the definitions in rainbow_config.h +/// +/// Defining the functions used in rainbow.c acconding to the definitions in rainbow_config.h + +#include "blas.h" +#include "blas_comm.h" +#include "parallel_matrix_op.h" +#include "rainbow_config.h" + + +#define gfv_get_ele PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_get_ele +#define gfv_mul_scalar PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_mul_scalar +#define gfv_madd PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_madd + +#define gfmat_prod PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256mat_prod +#define gfmat_inv PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256mat_inv + +#define batch_trimat_madd PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_trimat_madd_gf256 +#define batch_trimatTr_madd PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_trimatTr_madd_gf256 +#define batch_2trimat_madd PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_2trimat_madd_gf256 +#define batch_matTr_madd PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_matTr_madd_gf256 +#define batch_bmatTr_madd PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_bmatTr_madd_gf256 +#define batch_mat_madd PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_mat_madd_gf256 + +#define batch_quad_trimat_eval PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_quad_trimat_eval_gf256 +#define batch_quad_recmat_eval PQCLEAN_RAINBOWVCCLASSIC_CLEAN_batch_quad_recmat_eval_gf256 + + +#endif // _RAINBOW_BLAS_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-classic_clean/rainbow_config.h b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/rainbow_config.h new file mode 100644 index 0000000000..f691dfb11a --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/rainbow_config.h @@ -0,0 +1,48 @@ +#ifndef _H_RAINBOW_CONFIG_H_ +#define _H_RAINBOW_CONFIG_H_ + +/// @file rainbow_config.h +/// @brief Defining the parameters of the Rainbow and the corresponding constants. +/// + +#define _GFSIZE 256 +#define _V1 92 +#define _O1 48 +#define _O2 48 +#define _MAX_O 48 +#define _HASH_LEN 64 + + +#define _V2 ((_V1) + (_O1)) + +/// size of N, in # of gf elements. +#define _PUB_N (_V1 + _O1 + _O2) + +/// size of M, in # gf elements. +#define _PUB_M (_O1 + _O2) + +/// size of variables, in # bytes. + +// GF256 +#define _V1_BYTE (_V1) +#define _V2_BYTE (_V2) +#define _O1_BYTE (_O1) +#define _O2_BYTE (_O2) +#define _MAX_O_BYTE (_MAX_O) +#define _PUB_N_BYTE (_PUB_N) +#define _PUB_M_BYTE (_PUB_M) + + +/// length of seed for public key, in # bytes +#define LEN_PKSEED 32 + +/// length of seed for secret key, in # bytes +#define LEN_SKSEED 32 + +/// length of salt for a signature, in # bytes +#define _SALT_BYTE 16 + +/// length of a signature +#define _SIGNATURE_BYTE (_PUB_N_BYTE + _SALT_BYTE) + +#endif // _H_RAINBOW_CONFIG_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-classic_clean/rainbow_keypair.c b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/rainbow_keypair.c new file mode 100644 index 0000000000..27005dfc5b --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/rainbow_keypair.c @@ -0,0 +1,126 @@ +/// @file rainbow_keypair.c +/// @brief implementations of functions in rainbow_keypair.h +/// + +#include "rainbow_keypair.h" +#include "blas.h" +#include "blas_comm.h" +#include "rainbow_blas.h" +#include "rainbow_keypair_computation.h" +#include "utils_prng.h" +#include +#include +#include + +static void generate_S_T(unsigned char *s_and_t, prng_t *prng0) { + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_prng_gen(prng0, s_and_t, _O1_BYTE * _O2); // S1 + s_and_t += _O1_BYTE * _O2; + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_prng_gen(prng0, s_and_t, _V1_BYTE * _O1); // T1 + s_and_t += _V1_BYTE * _O1; + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_prng_gen(prng0, s_and_t, _V1_BYTE * _O2); // T2 + s_and_t += _V1_BYTE * _O2; + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_prng_gen(prng0, s_and_t, _O1_BYTE * _O2); // T3 +} + +static unsigned int generate_l1_F12(unsigned char *sk, prng_t *prng0) { + unsigned int n_byte_generated = 0; + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_prng_gen(prng0, sk, _O1_BYTE * N_TRIANGLE_TERMS(_V1)); // l1_F1 + sk += _O1_BYTE * N_TRIANGLE_TERMS(_V1); + n_byte_generated += _O1_BYTE * N_TRIANGLE_TERMS(_V1); + + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_prng_gen(prng0, sk, _O1_BYTE * _V1 * _O1); // l1_F2 + n_byte_generated += _O1_BYTE * _V1 * _O1; + return n_byte_generated; +} + +static unsigned int generate_l2_F12356(unsigned char *sk, prng_t *prng0) { + unsigned int n_byte_generated = 0; + + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * N_TRIANGLE_TERMS(_V1)); // l2_F1 + sk += _O2_BYTE * N_TRIANGLE_TERMS(_V1); + n_byte_generated += _O2_BYTE * N_TRIANGLE_TERMS(_V1); + + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * _V1 * _O1); // l2_F2 + sk += _O2_BYTE * _V1 * _O1; + n_byte_generated += _O2_BYTE * _V1 * _O1; + + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * _V1 * _O2); // l2_F3 + sk += _O2_BYTE * _V1 * _O1; + n_byte_generated += _O2_BYTE * _V1 * _O1; + + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * N_TRIANGLE_TERMS(_O1)); // l2_F5 + sk += _O2_BYTE * N_TRIANGLE_TERMS(_O1); + n_byte_generated += _O2_BYTE * N_TRIANGLE_TERMS(_O1); + + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * _O1 * _O2); // l2_F6 + n_byte_generated += _O2_BYTE * _O1 * _O2; + + return n_byte_generated; +} + +static void generate_B1_B2(unsigned char *sk, prng_t *prng0) { + sk += generate_l1_F12(sk, prng0); + generate_l2_F12356(sk, prng0); +} + +static void calculate_t4(unsigned char *t2_to_t4, const unsigned char *t1, const unsigned char *t3) { + // t4 = T_sk.t1 * T_sk.t3 - T_sk.t2 + unsigned char temp[_V1_BYTE + 32]; + unsigned char *t4 = t2_to_t4; + for (unsigned int i = 0; i < _O2; i++) { /// t3 width + gfmat_prod(temp, t1, _V1_BYTE, _O1, t3); + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_add(t4, temp, _V1_BYTE); + t4 += _V1_BYTE; + t3 += _O1_BYTE; + } +} + +static void obsfucate_l1_polys(unsigned char *l1_polys, const unsigned char *l2_polys, unsigned int n_terms, const unsigned char *s1) { + unsigned char temp[_O1_BYTE + 32]; + while (n_terms--) { + gfmat_prod(temp, s1, _O1_BYTE, _O2, l2_polys); + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_gf256v_add(l1_polys, temp, _O1_BYTE); + l1_polys += _O1_BYTE; + l2_polys += _O2_BYTE; + } +} + +/////////////////// Classic ////////////////////////////////// + +static void _generate_secretkey(sk_t *sk, const unsigned char *sk_seed) { + memcpy(sk->sk_seed, sk_seed, LEN_SKSEED); + + // set up prng + prng_t prng0; + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_prng_set(&prng0, sk_seed, LEN_SKSEED); + + // generating secret key with prng. + generate_S_T(sk->s1, &prng0); + generate_B1_B2(sk->l1_F1, &prng0); + + // clean prng + memset(&prng0, 0, sizeof(prng_t)); +} + +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_generate_keypair(pk_t *rpk, sk_t *sk, const unsigned char *sk_seed) { + _generate_secretkey(sk, sk_seed); + + // set up a temporary structure ext_cpk_t for calculating public key. + ext_cpk_t pk; + + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_calculate_Q_from_F(&pk, sk, sk); // compute the public key in ext_cpk_t format. + calculate_t4(sk->t4, sk->t1, sk->t3); + + obsfucate_l1_polys(pk.l1_Q1, pk.l2_Q1, N_TRIANGLE_TERMS(_V1), sk->s1); + obsfucate_l1_polys(pk.l1_Q2, pk.l2_Q2, _V1 * _O1, sk->s1); + obsfucate_l1_polys(pk.l1_Q3, pk.l2_Q3, _V1 * _O2, sk->s1); + obsfucate_l1_polys(pk.l1_Q5, pk.l2_Q5, N_TRIANGLE_TERMS(_O1), sk->s1); + obsfucate_l1_polys(pk.l1_Q6, pk.l2_Q6, _O1 * _O2, sk->s1); + obsfucate_l1_polys(pk.l1_Q9, pk.l2_Q9, N_TRIANGLE_TERMS(_O2), sk->s1); + // so far, the pk contains the full pk but in ext_cpk_t format. + + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_extcpk_to_pk(rpk, &pk); // convert the public key from ext_cpk_t to pk_t. +} + + + diff --git a/src/sig/rainbow/pqclean_rainbowVc-classic_clean/rainbow_keypair.h b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/rainbow_keypair.h new file mode 100644 index 0000000000..2092aa868f --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/rainbow_keypair.h @@ -0,0 +1,61 @@ +#ifndef _RAINBOW_KEYPAIR_H_ +#define _RAINBOW_KEYPAIR_H_ +/// @file rainbow_keypair.h +/// @brief Formats of key pairs and functions for generating key pairs. +/// Formats of key pairs and functions for generating key pairs. +/// + +#include "rainbow_config.h" + +#define N_TRIANGLE_TERMS(n_var) ((n_var) * ((n_var) + 1) / 2) + +/// @brief public key for classic rainbow +/// +/// public key for classic rainbow +/// +typedef struct rainbow_publickey { + unsigned char pk[(_PUB_M_BYTE)*N_TRIANGLE_TERMS(_PUB_N)]; +} pk_t; + +/// @brief secret key for classic rainbow +/// +/// secret key for classic rainbow +/// +typedef struct rainbow_secretkey { + /// + /// seed for generating secret key. + /// Generating S, T, and F for classic rainbow. + /// Generating S and T only for cyclic rainbow. + unsigned char sk_seed[LEN_SKSEED]; + + unsigned char s1[_O1_BYTE * _O2]; ///< part of S map + unsigned char t1[_V1_BYTE * _O1]; ///< part of T map + unsigned char t4[_V1_BYTE * _O2]; ///< part of T map + unsigned char t3[_O1_BYTE * _O2]; ///< part of T map + + unsigned char l1_F1[_O1_BYTE * N_TRIANGLE_TERMS(_V1)]; ///< part of C-map, F1, Layer1 + unsigned char l1_F2[_O1_BYTE * _V1 * _O1]; ///< part of C-map, F2, Layer1 + + unsigned char l2_F1[_O2_BYTE * N_TRIANGLE_TERMS(_V1)]; ///< part of C-map, F1, Layer2 + unsigned char l2_F2[_O2_BYTE * _V1 * _O1]; ///< part of C-map, F2, Layer2 + + unsigned char l2_F3[_O2_BYTE * _V1 * _O2]; ///< part of C-map, F3, Layer2 + unsigned char l2_F5[_O2_BYTE * N_TRIANGLE_TERMS(_O1)]; ///< part of C-map, F5, Layer2 + unsigned char l2_F6[_O2_BYTE * _O1 * _O2]; ///< part of C-map, F6, Layer2 +} sk_t; + + +/// +/// @brief Generate key pairs for classic rainbow. +/// +/// @param[out] pk - the public key. +/// @param[out] sk - the secret key. +/// @param[in] sk_seed - seed for generating the secret key. +/// +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_generate_keypair(pk_t *pk, sk_t *sk, const unsigned char *sk_seed); + + + + + +#endif // _RAINBOW_KEYPAIR_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-classic_clean/rainbow_keypair_computation.c b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/rainbow_keypair_computation.c new file mode 100644 index 0000000000..da7851f42d --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/rainbow_keypair_computation.c @@ -0,0 +1,189 @@ +/// @file rainbow_keypair_computation.c +/// @brief Implementations for functions in rainbow_keypair_computation.h +/// + +#include "rainbow_keypair_computation.h" +#include "blas.h" +#include "blas_comm.h" +#include "rainbow_blas.h" +#include "rainbow_keypair.h" +#include +#include +#include + +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_extcpk_to_pk(pk_t *pk, const ext_cpk_t *cpk) { + const unsigned char *idx_l1 = cpk->l1_Q1; + const unsigned char *idx_l2 = cpk->l2_Q1; + for (unsigned int i = 0; i < _V1; i++) { + for (unsigned int j = i; j < _V1; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWVCCLASSIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q2; + idx_l2 = cpk->l2_Q2; + for (unsigned int i = 0; i < _V1; i++) { + for (unsigned int j = _V1; j < _V1 + _O1; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWVCCLASSIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q3; + idx_l2 = cpk->l2_Q3; + for (unsigned int i = 0; i < _V1; i++) { + for (unsigned int j = _V1 + _O1; j < _PUB_N; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWVCCLASSIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q5; + idx_l2 = cpk->l2_Q5; + for (unsigned int i = _V1; i < _V1 + _O1; i++) { + for (unsigned int j = i; j < _V1 + _O1; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWVCCLASSIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q6; + idx_l2 = cpk->l2_Q6; + for (unsigned int i = _V1; i < _V1 + _O1; i++) { + for (unsigned int j = _V1 + _O1; j < _PUB_N; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWVCCLASSIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q9; + idx_l2 = cpk->l2_Q9; + for (unsigned int i = _V1 + _O1; i < _PUB_N; i++) { + for (unsigned int j = i; j < _PUB_N; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWVCCLASSIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } +} + +static void calculate_Q_from_F_ref(ext_cpk_t *Qs, const sk_t *Fs, const sk_t *Ts) { + /* + Layer 1 + Computing : + Q_pk.l1_F1s[i] = F_sk.l1_F1s[i] + + Q_pk.l1_F2s[i] = (F1* T1 + F2) + F1tr * t1 + Q_pk.l1_F5s[i] = UT( T1tr* (F1 * T1 + F2) ) + */ + const unsigned char *t2 = Ts->t4; + + memcpy(Qs->l1_Q1, Fs->l1_F1, _O1_BYTE * N_TRIANGLE_TERMS(_V1)); + + memcpy(Qs->l1_Q2, Fs->l1_F2, _O1_BYTE * _V1 * _O1); + batch_trimat_madd(Qs->l1_Q2, Fs->l1_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O1_BYTE); // F1*T1 + F2 + + memset(Qs->l1_Q3, 0, _O1_BYTE * _V1 * _O2); + memset(Qs->l1_Q5, 0, _O1_BYTE * N_TRIANGLE_TERMS(_O1)); + memset(Qs->l1_Q6, 0, _O1_BYTE * _O1 * _O2); + memset(Qs->l1_Q9, 0, _O1_BYTE * N_TRIANGLE_TERMS(_O2)); + + // l1_Q5 : _O1_BYTE * _O1 * _O1 + // l1_Q9 : _O1_BYTE * _O2 * _O2 + // l2_Q5 : _O2_BYTE * _V1 * _O1 + // l2_Q9 : _O2_BYTE * _V1 * _O2 + + unsigned char tempQ[_O1_BYTE * _O1 * _O1 + 32]; + + memset(tempQ, 0, _O1_BYTE * _O1 * _O1); // l1_Q5 + batch_matTr_madd(tempQ, Ts->t1, _V1, _V1_BYTE, _O1, Qs->l1_Q2, _O1, _O1_BYTE); // t1_tr*(F1*T1 + F2) + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_UpperTrianglize(Qs->l1_Q5, tempQ, _O1, _O1_BYTE); // UT( ... ) // Q5 + + batch_trimatTr_madd(Qs->l1_Q2, Fs->l1_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O1_BYTE); // Q2 + /* + Computing: + F1_T2 = F1 * t2 + F2_T3 = F2 * t3 + F1_F1T_T2 + F2_T3 = F1_T2 + F2_T3 + F1tr * t2 + Q_pk.l1_F3s[i] = F1_F1T_T2 + F2_T3 + Q_pk.l1_F6s[i] = T1tr* ( F1_F1T_T2 + F2_T3 ) + F2tr * t2 + Q_pk.l1_F9s[i] = UT( T2tr* ( F1_T2 + F2_T3 ) ) + */ + batch_trimat_madd(Qs->l1_Q3, Fs->l1_F1, t2, _V1, _V1_BYTE, _O2, _O1_BYTE); // F1*T2 + batch_mat_madd(Qs->l1_Q3, Fs->l1_F2, _V1, Ts->t3, _O1, _O1_BYTE, _O2, _O1_BYTE); // F1_T2 + F2_T3 + + memset(tempQ, 0, _O1_BYTE * _O2 * _O2); // l1_Q9 + batch_matTr_madd(tempQ, t2, _V1, _V1_BYTE, _O2, Qs->l1_Q3, _O2, _O1_BYTE); // T2tr * ( F1_T2 + F2_T3 ) + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_UpperTrianglize(Qs->l1_Q9, tempQ, _O2, _O1_BYTE); // Q9 + + batch_trimatTr_madd(Qs->l1_Q3, Fs->l1_F1, t2, _V1, _V1_BYTE, _O2, _O1_BYTE); // F1_F1T_T2 + F2_T3 // Q3 + + batch_bmatTr_madd(Qs->l1_Q6, Fs->l1_F2, _O1, t2, _V1, _V1_BYTE, _O2, _O1_BYTE); // F2tr*T2 + batch_matTr_madd(Qs->l1_Q6, Ts->t1, _V1, _V1_BYTE, _O1, Qs->l1_Q3, _O2, _O1_BYTE); // Q6 + + /* + layer 2 + Computing: + Q1 = F1 + Q2 = F1_F1T*T1 + F2 + Q5 = UT( T1tr( F1*T1 + F2 ) + F5 ) + */ + memcpy(Qs->l2_Q1, Fs->l2_F1, _O2_BYTE * N_TRIANGLE_TERMS(_V1)); + + memcpy(Qs->l2_Q2, Fs->l2_F2, _O2_BYTE * _V1 * _O1); + batch_trimat_madd(Qs->l2_Q2, Fs->l2_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O2_BYTE); // F1*T1 + F2 + + memcpy(Qs->l2_Q5, Fs->l2_F5, _O2_BYTE * N_TRIANGLE_TERMS(_O1)); + memset(tempQ, 0, _O2_BYTE * _O1 * _O1); // l2_Q5 + batch_matTr_madd(tempQ, Ts->t1, _V1, _V1_BYTE, _O1, Qs->l2_Q2, _O1, _O2_BYTE); // t1_tr*(F1*T1 + F2) + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_UpperTrianglize(Qs->l2_Q5, tempQ, _O1, _O2_BYTE); // UT( ... ) // Q5 + + batch_trimatTr_madd(Qs->l2_Q2, Fs->l2_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O2_BYTE); // Q2 + + /* + Computing: + F1_T2 = F1 * t2 + F2_T3 = F2 * t3 + F1_F1T_T2 + F2_T3 = F1_T2 + F2_T3 + F1tr * t2 + + Q3 = F1_F1T*T2 + F2*T3 + F3 + Q9 = UT( T2tr*( F1*T2 + F2*T3 + F3 ) + T3tr*( F5*T3 + F6 ) ) + Q6 = T1tr*( F1_F1T*T2 + F2*T3 + F3 ) + F2Tr*T2 + F5_F5T*T3 + F6 + */ + memcpy(Qs->l2_Q3, Fs->l2_F3, _O2_BYTE * _V1 * _O2); + batch_trimat_madd(Qs->l2_Q3, Fs->l2_F1, t2, _V1, _V1_BYTE, _O2, _O2_BYTE); // F1*T2 + F3 + batch_mat_madd(Qs->l2_Q3, Fs->l2_F2, _V1, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // F1_T2 + F2_T3 + F3 + + memset(tempQ, 0, _O2_BYTE * _O2 * _O2); // l2_Q9 + batch_matTr_madd(tempQ, t2, _V1, _V1_BYTE, _O2, Qs->l2_Q3, _O2, _O2_BYTE); // T2tr * ( ..... ) + + memcpy(Qs->l2_Q6, Fs->l2_F6, _O2_BYTE * _O1 * _O2); + + batch_trimat_madd(Qs->l2_Q6, Fs->l2_F5, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // F5*T3 + F6 + batch_matTr_madd(tempQ, Ts->t3, _O1, _O1_BYTE, _O2, Qs->l2_Q6, _O2, _O2_BYTE); // T2tr*( ..... ) + T3tr*( ..... ) + memset(Qs->l2_Q9, 0, _O2_BYTE * N_TRIANGLE_TERMS(_O2)); + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_UpperTrianglize(Qs->l2_Q9, tempQ, _O2, _O2_BYTE); // Q9 + + batch_trimatTr_madd(Qs->l2_Q3, Fs->l2_F1, t2, _V1, _V1_BYTE, _O2, _O2_BYTE); // F1_F1T_T2 + F2_T3 + F3 // Q3 + + batch_bmatTr_madd(Qs->l2_Q6, Fs->l2_F2, _O1, t2, _V1, _V1_BYTE, _O2, _O2_BYTE); // F5*T3 + F6 + F2tr*T2 + batch_trimatTr_madd(Qs->l2_Q6, Fs->l2_F5, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // F2tr*T2 + F5_F5T*T3 + F6 + batch_matTr_madd(Qs->l2_Q6, Ts->t1, _V1, _V1_BYTE, _O1, Qs->l2_Q3, _O2, _O2_BYTE); // Q6 +} +#define calculate_Q_from_F_impl calculate_Q_from_F_ref +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_calculate_Q_from_F(ext_cpk_t *Qs, const sk_t *Fs, const sk_t *Ts) { + calculate_Q_from_F_impl(Qs, Fs, Ts); +} diff --git a/src/sig/rainbow/pqclean_rainbowVc-classic_clean/rainbow_keypair_computation.h b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/rainbow_keypair_computation.h new file mode 100644 index 0000000000..c9ea1499bd --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/rainbow_keypair_computation.h @@ -0,0 +1,53 @@ +#ifndef _RAINBOW_KEYPAIR_COMP_H_ +#define _RAINBOW_KEYPAIR_COMP_H_ +/// @file rainbow_keypair_computation.h +/// @brief Functions for calculating pk/sk while generating keys. +/// +/// Defining an internal structure of public key. +/// Functions for calculating pk/sk for key generation. +/// + +#include "rainbow_keypair.h" + +/// @brief The (internal use) public key for rainbow +/// +/// The (internal use) public key for rainbow. The public +/// polynomials are divided into l1_Q1, l1_Q2, ... l1_Q9, +/// l2_Q1, .... , l2_Q9. +/// +typedef struct rainbow_extend_publickey { + unsigned char l1_Q1[_O1_BYTE * N_TRIANGLE_TERMS(_V1)]; + unsigned char l1_Q2[_O1_BYTE * _V1 * _O1]; + unsigned char l1_Q3[_O1_BYTE * _V1 * _O2]; + unsigned char l1_Q5[_O1_BYTE * N_TRIANGLE_TERMS(_O1)]; + unsigned char l1_Q6[_O1_BYTE * _O1 * _O2]; + unsigned char l1_Q9[_O1_BYTE * N_TRIANGLE_TERMS(_O2)]; + + unsigned char l2_Q1[_O2_BYTE * N_TRIANGLE_TERMS(_V1)]; + unsigned char l2_Q2[_O2_BYTE * _V1 * _O1]; + unsigned char l2_Q3[_O2_BYTE * _V1 * _O2]; + unsigned char l2_Q5[_O2_BYTE * N_TRIANGLE_TERMS(_O1)]; + unsigned char l2_Q6[_O2_BYTE * _O1 * _O2]; + unsigned char l2_Q9[_O2_BYTE * N_TRIANGLE_TERMS(_O2)]; +} ext_cpk_t; + +/// +/// @brief converting formats of public keys : from ext_cpk_t version to pk_t +/// +/// @param[out] pk - the classic public key. +/// @param[in] cpk - the internel public key. +/// +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_extcpk_to_pk(pk_t *pk, const ext_cpk_t *cpk); +///////////////////////////////////////////////// + +/// +/// @brief Computing public key from secret key +/// +/// @param[out] Qs - the public key +/// @param[in] Fs - parts of the secret key: l1_F1, l1_F2, l2_F1, l2_F2, l2_F3, l2_F5, l2_F6 +/// @param[in] Ts - parts of the secret key: T1, T4, T3 +/// +void PQCLEAN_RAINBOWVCCLASSIC_CLEAN_calculate_Q_from_F(ext_cpk_t *Qs, const sk_t *Fs, const sk_t *Ts); + + +#endif // _RAINBOW_KEYPAIR_COMP_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-classic_clean/sign.c b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/sign.c new file mode 100644 index 0000000000..3c0e56a027 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/sign.c @@ -0,0 +1,74 @@ +/// @file sign.c +/// @brief the implementations for functions in api.h +/// +/// + +#include "api.h" +#include "rainbow.h" +#include "rainbow_config.h" +#include "rainbow_keypair.h" +#include "randombytes.h" +#include "utils_hash.h" +#include +#include + +int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { + unsigned char sk_seed[LEN_SKSEED] = {0}; + randombytes(sk_seed, LEN_SKSEED); + + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_generate_keypair((pk_t *)pk, (sk_t *)sk, sk_seed); + return 0; +} + +int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { + unsigned char digest[_HASH_LEN]; + + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_hash_msg(digest, _HASH_LEN, m, mlen); + + memcpy(sm, m, mlen); + smlen[0] = mlen + _SIGNATURE_BYTE; + + return PQCLEAN_RAINBOWVCCLASSIC_CLEAN_rainbow_sign(sm + mlen, (const sk_t *)sk, digest); +} + +int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { + int rc; + if (_SIGNATURE_BYTE > smlen) { + rc = -1; + } else { + *mlen = smlen - _SIGNATURE_BYTE; + + unsigned char digest[_HASH_LEN]; + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_hash_msg(digest, _HASH_LEN, sm, *mlen); + + rc = PQCLEAN_RAINBOWVCCLASSIC_CLEAN_rainbow_verify(digest, sm + mlen[0], (const pk_t *)pk); + } + if (!rc) { + memmove(m, sm, smlen - _SIGNATURE_BYTE); + } else { // bad signature + *mlen = (size_t) -1; + memset(m, 0, smlen); + } + return rc; +} + +int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_crypto_sign_signature( + uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + unsigned char digest[_HASH_LEN]; + + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_hash_msg(digest, _HASH_LEN, m, mlen); + *siglen = _SIGNATURE_BYTE; + return PQCLEAN_RAINBOWVCCLASSIC_CLEAN_rainbow_sign(sig, (const sk_t *)sk, digest); +} + +int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_crypto_sign_verify( + const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + if (siglen != _SIGNATURE_BYTE) { + return -1; + } + unsigned char digest[_HASH_LEN]; + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_hash_msg(digest, _HASH_LEN, m, mlen); + return PQCLEAN_RAINBOWVCCLASSIC_CLEAN_rainbow_verify(digest, sig, (const pk_t *)pk); +} diff --git a/src/sig/rainbow/pqclean_rainbowVc-classic_clean/utils_hash.c b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/utils_hash.c new file mode 100644 index 0000000000..b7bb5f3b55 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/utils_hash.c @@ -0,0 +1,50 @@ +/// @file utils_hash.c +/// @brief the adapter for SHA2 families. +/// +/// + +#include "utils_hash.h" +#include "rainbow_config.h" +#include "sha2.h" + +static inline int _hash(unsigned char *digest, const unsigned char *m, size_t mlen) { + sha512(digest, m, mlen); + return 0; +} + +static inline int expand_hash(unsigned char *digest, size_t n_digest, const unsigned char *hash) { + if (_HASH_LEN >= n_digest) { + for (size_t i = 0; i < n_digest; i++) { + digest[i] = hash[i]; + } + return 0; + } + for (size_t i = 0; i < _HASH_LEN; i++) { + digest[i] = hash[i]; + } + n_digest -= _HASH_LEN; + + while (_HASH_LEN <= n_digest) { + _hash(digest + _HASH_LEN, digest, _HASH_LEN); + + n_digest -= _HASH_LEN; + digest += _HASH_LEN; + } + unsigned char temp[_HASH_LEN]; + if (n_digest) { + _hash(temp, digest, _HASH_LEN); + for (size_t i = 0; i < n_digest; i++) { + digest[_HASH_LEN + i] = temp[i]; + } + } + return 0; +} + +int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_hash_msg(unsigned char *digest, + size_t len_digest, + const unsigned char *m, + size_t mlen) { + unsigned char buf[_HASH_LEN]; + _hash(buf, m, mlen); + return expand_hash(digest, len_digest, buf); +} diff --git a/src/sig/rainbow/pqclean_rainbowVc-classic_clean/utils_hash.h b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/utils_hash.h new file mode 100644 index 0000000000..bab036311e --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/utils_hash.h @@ -0,0 +1,11 @@ +#ifndef _UTILS_HASH_H_ +#define _UTILS_HASH_H_ +/// @file utils_hash.h +/// @brief the interface for adapting hash functions. +/// + +#include + +int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_hash_msg(unsigned char *digest, size_t len_digest, const unsigned char *m, size_t mlen); + +#endif // _UTILS_HASH_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-classic_clean/utils_prng.c b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/utils_prng.c new file mode 100644 index 0000000000..0c758c304a --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/utils_prng.c @@ -0,0 +1,97 @@ +/// @file utils_prng.c +/// @brief The implementation of PRNG related functions. +/// + +#include "utils_prng.h" +#include "aes.h" +#include "randombytes.h" +#include "utils_hash.h" +#include +#include + +static void prng_update(const unsigned char *provided_data, + unsigned char *Key, + unsigned char *V) { + unsigned char temp[48]; + aes256ctx ctx; + aes256_keyexp(&ctx, Key); + for (int i = 0; i < 3; i++) { + //increment V + for (int j = 15; j >= 0; j--) { + if (V[j] == 0xff) { + V[j] = 0x00; + } else { + V[j]++; + break; + } + } + aes256_ecb(temp + 16 * i, V, 1, &ctx); + } + if (provided_data != NULL) { + for (int i = 0; i < 48; i++) { + temp[i] ^= provided_data[i]; + } + } + aes256_ctx_release(&ctx); + memcpy(Key, temp, 32); + memcpy(V, temp + 32, 16); +} +static void randombytes_init_with_state(prng_t *state, + unsigned char *entropy_input_48bytes) { + memset(state->Key, 0x00, 32); + memset(state->V, 0x00, 16); + prng_update(entropy_input_48bytes, state->Key, state->V); +} + +static int randombytes_with_state(prng_t *state, + unsigned char *x, + size_t xlen) { + + unsigned char block[16]; + int i = 0; + + aes256ctx ctx; + aes256_keyexp(&ctx, state->Key); + + while (xlen > 0) { + //increment V + for (int j = 15; j >= 0; j--) { + if (state->V[j] == 0xff) { + state->V[j] = 0x00; + } else { + state->V[j]++; + break; + } + } + aes256_ecb(block, state->V, 1, &ctx); + if (xlen > 15) { + memcpy(x + i, block, 16); + i += 16; + xlen -= 16; + } else { + memcpy(x + i, block, xlen); + xlen = 0; + } + } + aes256_ctx_release(&ctx); + prng_update(NULL, state->Key, state->V); + return 0; +} + +int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_prng_set(prng_t *ctx, const void *prng_seed, unsigned long prng_seedlen) { + unsigned char seed[48]; + if (prng_seedlen >= 48) { + memcpy(seed, prng_seed, 48); + } else { + memcpy(seed, prng_seed, prng_seedlen); + PQCLEAN_RAINBOWVCCLASSIC_CLEAN_hash_msg(seed + prng_seedlen, 48 - (unsigned)prng_seedlen, (const unsigned char *)prng_seed, prng_seedlen); + } + + randombytes_init_with_state(ctx, seed); + + return 0; +} + +int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_prng_gen(prng_t *ctx, unsigned char *out, unsigned long outlen) { + return randombytes_with_state(ctx, out, outlen); +} diff --git a/src/sig/rainbow/pqclean_rainbowVc-classic_clean/utils_prng.h b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/utils_prng.h new file mode 100644 index 0000000000..ea9457b48d --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-classic_clean/utils_prng.h @@ -0,0 +1,18 @@ +#ifndef _UTILS_PRNG_H_ +#define _UTILS_PRNG_H_ +/// @file utils_prng.h +/// @brief the interface for adapting PRNG functions. +/// +/// + +#include "randombytes.h" + +typedef struct { + unsigned char Key[32]; + unsigned char V[16]; +} prng_t; + +int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_prng_set(prng_t *ctx, const void *prng_seed, unsigned long prng_seedlen); +int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_prng_gen(prng_t *ctx, unsigned char *out, unsigned long outlen); + +#endif // _UTILS_PRNG_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/LICENSE b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/LICENSE new file mode 100644 index 0000000000..cb00a6e354 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/LICENSE @@ -0,0 +1,8 @@ +`Software implementation of Rainbow for NIST R2 submission' by Ming-Shing Chen + +To the extent possible under law, the person who associated CC0 with +`Software implementation of Rainbow for NIST R2 submission' has waived all copyright and related or neighboring rights +to `Software implementation of Rainbow for NIST R2 submission'. + +You should have received a copy of the CC0 legalcode along with this +work. If not, see . diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/api.h b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/api.h new file mode 100644 index 0000000000..7f4a866c44 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/api.h @@ -0,0 +1,32 @@ +#ifndef PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_API_H +#define PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_API_H + +#include +#include + +#define PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_CRYPTO_SECRETKEYBYTES 64 +#define PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_CRYPTO_PUBLICKEYBYTES 491936 +#define PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_CRYPTO_BYTES 204 +#define PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_CRYPTO_ALGNAME "RAINBOW(256,92,48,48) - cyclic compressed" + +int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + + +int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_crypto_sign_signature( + uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_crypto_sign_verify( + const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + + +#endif diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/blas.c b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/blas.c new file mode 100644 index 0000000000..7bb41d5288 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/blas.c @@ -0,0 +1,31 @@ +#include "blas.h" +#include "gf.h" + +#include + +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_predicated_add(uint8_t *accu_b, uint8_t predicate, const uint8_t *a, size_t _num_byte) { + uint8_t pr_u8 = (uint8_t) ((uint8_t) 0 - predicate); + for (size_t i = 0; i < _num_byte; i++) { + accu_b[i] ^= (a[i] & pr_u8); + } +} + +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_add(uint8_t *accu_b, const uint8_t *a, size_t _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + accu_b[i] ^= a[i]; + } +} + + +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_mul_scalar(uint8_t *a, uint8_t b, size_t _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + a[i] = PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256_mul(a[i], b); + } +} + +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_madd(uint8_t *accu_c, const uint8_t *a, uint8_t gf256_b, size_t _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + accu_c[i] ^= PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256_mul(a[i], gf256_b); + } +} + diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/blas.h b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/blas.h new file mode 100644 index 0000000000..11bd93515f --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/blas.h @@ -0,0 +1,19 @@ +#ifndef _BLAS_H_ +#define _BLAS_H_ +/// @file blas.h +/// @brief Functions for implementing basic linear algebra functions. +/// + +#include "rainbow_config.h" +#include +#include + +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_predicated_add(uint8_t *accu_b, uint8_t predicate, const uint8_t *a, size_t _num_byte); +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_add(uint8_t *accu_b, const uint8_t *a, size_t _num_byte); + + +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_mul_scalar(uint8_t *a, uint8_t b, size_t _num_byte); +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_madd(uint8_t *accu_c, const uint8_t *a, uint8_t gf256_b, size_t _num_byte); + + +#endif // _BLAS_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/blas_comm.c b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/blas_comm.c new file mode 100644 index 0000000000..0d3fd44b60 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/blas_comm.c @@ -0,0 +1,144 @@ +/// @file blas_comm.c +/// @brief The standard implementations for blas_comm.h +/// + +#include "blas_comm.h" +#include "blas.h" +#include "gf.h" +#include "rainbow_config.h" + +#include +#include + +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_set_zero(uint8_t *b, unsigned int _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + b[i] = 0; + } +} +/// @brief get an element from GF(256) vector . +/// +/// @param[in] a - the input vector a. +/// @param[in] i - the index in the vector a. +/// @return the value of the element. +/// +uint8_t PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_get_ele(const uint8_t *a, unsigned int i) { + return a[i]; +} + +unsigned int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_is_zero(const uint8_t *a, unsigned int _num_byte) { + uint8_t r = 0; + while (_num_byte--) { + r |= a[0]; + a++; + } + return (0 == r); +} + +/// polynomial multplication +/// School boook +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_polymul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int _num) { + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_set_zero(c, _num * 2 - 1); + for (unsigned int i = 0; i < _num; i++) { + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_madd(c + i, a, b[i], _num); + } +} + +static void gf256mat_prod_ref(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b) { + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_set_zero(c, n_A_vec_byte); + for (unsigned int i = 0; i < n_A_width; i++) { + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_madd(c, matA, b[i], n_A_vec_byte); + matA += n_A_vec_byte; + } +} + +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256mat_mul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int len_vec) { + unsigned int n_vec_byte = len_vec; + for (unsigned int k = 0; k < len_vec; k++) { + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_set_zero(c, n_vec_byte); + const uint8_t *bk = b + n_vec_byte * k; + for (unsigned int i = 0; i < len_vec; i++) { + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_madd(c, a + n_vec_byte * i, bk[i], n_vec_byte); + } + c += n_vec_byte; + } +} + +static unsigned int gf256mat_gauss_elim_ref(uint8_t *mat, unsigned int h, unsigned int w) { + unsigned int r8 = 1; + + for (unsigned int i = 0; i < h; i++) { + uint8_t *ai = mat + w * i; + unsigned int skip_len_align4 = i & ((unsigned int)~0x3); + + for (unsigned int j = i + 1; j < h; j++) { + uint8_t *aj = mat + w * j; + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_predicated_add(ai + skip_len_align4, !PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256_is_nonzero(ai[i]), aj + skip_len_align4, w - skip_len_align4); + } + r8 &= PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256_is_nonzero(ai[i]); + uint8_t pivot = ai[i]; + pivot = PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256_inv(pivot); + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_mul_scalar(ai + skip_len_align4, pivot, w - skip_len_align4); + for (unsigned int j = 0; j < h; j++) { + if (i == j) { + continue; + } + uint8_t *aj = mat + w * j; + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_madd(aj + skip_len_align4, ai + skip_len_align4, aj[i], w - skip_len_align4); + } + } + + return r8; +} + +static unsigned int gf256mat_solve_linear_eq_ref(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n) { + uint8_t mat[64 * 64]; + for (unsigned int i = 0; i < n; i++) { + memcpy(mat + i * (n + 1), inp_mat + i * n, n); + mat[i * (n + 1) + n] = c_terms[i]; + } + unsigned int r8 = PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256mat_gauss_elim(mat, n, n + 1); + for (unsigned int i = 0; i < n; i++) { + sol[i] = mat[i * (n + 1) + n]; + } + return r8; +} + +static inline void gf256mat_submat(uint8_t *mat2, unsigned int w2, unsigned int st, const uint8_t *mat, unsigned int w, unsigned int h) { + for (unsigned int i = 0; i < h; i++) { + for (unsigned int j = 0; j < w2; j++) { + mat2[i * w2 + j] = mat[i * w + st + j]; + } + } +} + +unsigned int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256mat_inv(uint8_t *inv_a, const uint8_t *a, unsigned int H, uint8_t *buffer) { + uint8_t *aa = buffer; + for (unsigned int i = 0; i < H; i++) { + uint8_t *ai = aa + i * 2 * H; + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_set_zero(ai, 2 * H); + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_add(ai, a + i * H, H); + ai[H + i] = 1; + } + unsigned int r8 = PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256mat_gauss_elim(aa, H, 2 * H); + gf256mat_submat(inv_a, H, H, aa, 2 * H, H); + return r8; +} + + +// choosing the implementations depends on the macros _BLAS_AVX2_ and _BLAS_SSE + +#define gf256mat_prod_impl gf256mat_prod_ref +#define gf256mat_gauss_elim_impl gf256mat_gauss_elim_ref +#define gf256mat_solve_linear_eq_impl gf256mat_solve_linear_eq_ref +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256mat_prod(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b) { + gf256mat_prod_impl(c, matA, n_A_vec_byte, n_A_width, b); +} + +unsigned int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256mat_gauss_elim(uint8_t *mat, unsigned int h, unsigned int w) { + return gf256mat_gauss_elim_impl(mat, h, w); +} + +unsigned int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256mat_solve_linear_eq(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n) { + return gf256mat_solve_linear_eq_impl(sol, inp_mat, c_terms, n); +} + diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/blas_comm.h b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/blas_comm.h new file mode 100644 index 0000000000..af5715c636 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/blas_comm.h @@ -0,0 +1,90 @@ +#ifndef _BLAS_COMM_H_ +#define _BLAS_COMM_H_ +/// @file blas_comm.h +/// @brief Common functions for linear algebra. +/// + +#include "rainbow_config.h" +#include + +/// @brief set a vector to 0. +/// +/// @param[in,out] b - the vector b. +/// @param[in] _num_byte - number of bytes for the vector b. +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_set_zero(uint8_t *b, unsigned int _num_byte); + +/// @brief get an element from GF(256) vector . +/// +/// @param[in] a - the input vector a. +/// @param[in] i - the index in the vector a. +/// @return the value of the element. +/// +uint8_t PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_get_ele(const uint8_t *a, unsigned int i); + +/// @brief check if a vector is 0. +/// +/// @param[in] a - the vector a. +/// @param[in] _num_byte - number of bytes for the vector a. +/// @return 1(true) if a is 0. 0(false) else. +/// +unsigned int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_is_zero(const uint8_t *a, unsigned int _num_byte); + +/// @brief polynomial multiplication: c = a*b +/// +/// @param[out] c - the output polynomial c +/// @param[in] a - the vector a. +/// @param[in] b - the vector b. +/// @param[in] _num - number of elements for the polynomials a and b. +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_polymul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int _num); + +/// @brief matrix-vector multiplication: c = matA * b , in GF(256) +/// +/// @param[out] c - the output vector c +/// @param[in] matA - a column-major matrix A. +/// @param[in] n_A_vec_byte - the size of column vectors in bytes. +/// @param[in] n_A_width - the width of matrix A. +/// @param[in] b - the vector b. +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256mat_prod(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b); + +/// @brief matrix-matrix multiplication: c = a * b , in GF(256) +/// +/// @param[out] c - the output matrix c +/// @param[in] c - a matrix a. +/// @param[in] b - a matrix b. +/// @param[in] len_vec - the length of column vectors. +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256mat_mul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int len_vec); + +/// @brief Gauss elimination for a matrix, in GF(256) +/// +/// @param[in,out] mat - the matrix. +/// @param[in] h - the height of the matrix. +/// @param[in] w - the width of the matrix. +/// @return 1(true) if success. 0(false) if the matrix is singular. +/// +unsigned int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256mat_gauss_elim(uint8_t *mat, unsigned int h, unsigned int w); + +/// @brief Solving linear equations, in GF(256) +/// +/// @param[out] sol - the solutions. +/// @param[in] inp_mat - the matrix parts of input equations. +/// @param[in] c_terms - the constant terms of the input equations. +/// @param[in] n - the number of equations. +/// @return 1(true) if success. 0(false) if the matrix is singular. +/// +unsigned int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256mat_solve_linear_eq(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n); + +/// @brief Computing the inverse matrix, in GF(256) +/// +/// @param[out] inv_a - the output of matrix a. +/// @param[in] a - a matrix a. +/// @param[in] H - height of matrix a, i.e., matrix a is an HxH matrix. +/// @param[in] buffer - The buffer for computations. it has to be as large as 2 input matrixes. +/// @return 1(true) if success. 0(false) if the matrix is singular. +/// +unsigned int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256mat_inv(uint8_t *inv_a, const uint8_t *a, unsigned int H, uint8_t *buffer); + +#endif // _BLAS_COMM_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/gf.c b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/gf.c new file mode 100644 index 0000000000..1b6159264f --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/gf.c @@ -0,0 +1,91 @@ +#include "gf.h" + +//// gf4 := gf2[x]/x^2+x+1 +static inline uint8_t gf4_mul_2(uint8_t a) { + uint8_t r = (uint8_t)(a << 1); + r ^= (uint8_t)((a >> 1) * 7); + return r; +} + +static inline uint8_t gf4_mul(uint8_t a, uint8_t b) { + uint8_t r = (uint8_t)(a * (b & 1)); + return r ^ (uint8_t)(gf4_mul_2(a) * (b >> 1)); +} + +static inline uint8_t gf4_squ(uint8_t a) { + return a ^ (a >> 1); +} + +//// gf16 := gf4[y]/y^2+y+x +uint8_t PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf16_mul(uint8_t a, uint8_t b) { + uint8_t a0 = a & 3; + uint8_t a1 = (a >> 2); + uint8_t b0 = b & 3; + uint8_t b1 = (b >> 2); + uint8_t a0b0 = gf4_mul(a0, b0); + uint8_t a1b1 = gf4_mul(a1, b1); + uint8_t a0b1_a1b0 = gf4_mul(a0 ^ a1, b0 ^ b1) ^ a0b0 ^ a1b1; + uint8_t a1b1_x2 = gf4_mul_2(a1b1); + return (uint8_t)((a0b1_a1b0 ^ a1b1) << 2 ^ a0b0 ^ a1b1_x2); +} + +static inline uint8_t gf16_squ(uint8_t a) { + uint8_t a0 = a & 3; + uint8_t a1 = (a >> 2); + a1 = gf4_squ(a1); + uint8_t a1squ_x2 = gf4_mul_2(a1); + return (uint8_t)((a1 << 2) ^ a1squ_x2 ^ gf4_squ(a0)); +} + +uint8_t PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256_is_nonzero(uint8_t a) { + unsigned int a8 = a; + unsigned int r = ((unsigned int)0) - a8; + r >>= 8; + return r & 1; +} + +static inline uint8_t gf4_mul_3(uint8_t a) { + uint8_t msk = (uint8_t)((a - 2) >> 1); + return (uint8_t)((msk & ((int)a * 3)) | ((~msk) & ((int)a - 1))); +} +static inline uint8_t gf16_mul_8(uint8_t a) { + uint8_t a0 = a & 3; + uint8_t a1 = a >> 2; + return (uint8_t)((gf4_mul_2(a0 ^ a1) << 2) | gf4_mul_3(a1)); +} + +// gf256 := gf16[X]/X^2+X+xy +uint8_t PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256_mul(uint8_t a, uint8_t b) { + uint8_t a0 = a & 15; + uint8_t a1 = (a >> 4); + uint8_t b0 = b & 15; + uint8_t b1 = (b >> 4); + uint8_t a0b0 = PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf16_mul(a0, b0); + uint8_t a1b1 = PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf16_mul(a1, b1); + uint8_t a0b1_a1b0 = PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf16_mul(a0 ^ a1, b0 ^ b1) ^ a0b0 ^ a1b1; + uint8_t a1b1_x8 = gf16_mul_8(a1b1); + return (uint8_t)((a0b1_a1b0 ^ a1b1) << 4 ^ a0b0 ^ a1b1_x8); +} + +static inline uint8_t gf256_squ(uint8_t a) { + uint8_t a0 = a & 15; + uint8_t a1 = (a >> 4); + a1 = gf16_squ(a1); + uint8_t a1squ_x8 = gf16_mul_8(a1); + return (uint8_t)((a1 << 4) ^ a1squ_x8 ^ gf16_squ(a0)); +} + +uint8_t PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256_inv(uint8_t a) { + // 128+64+32+16+8+4+2 = 254 + uint8_t a2 = gf256_squ(a); + uint8_t a4 = gf256_squ(a2); + uint8_t a8 = gf256_squ(a4); + uint8_t a4_2 = PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256_mul(a4, a2); + uint8_t a8_4_2 = PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256_mul(a4_2, a8); + uint8_t a64_ = gf256_squ(a8_4_2); + a64_ = gf256_squ(a64_); + a64_ = gf256_squ(a64_); + uint8_t a64_2 = PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256_mul(a64_, a8_4_2); + uint8_t a128_ = gf256_squ(a64_2); + return PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256_mul(a2, a128_); +} diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/gf.h b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/gf.h new file mode 100644 index 0000000000..b99e533f5d --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/gf.h @@ -0,0 +1,19 @@ +#ifndef _GF16_H_ +#define _GF16_H_ + +#include "rainbow_config.h" +#include + +/// @file gf16.h +/// @brief Library for arithmetics in GF(16) and GF(256) +/// + +uint8_t PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf16_mul(uint8_t a, uint8_t b); + + +uint8_t PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256_is_nonzero(uint8_t a); +uint8_t PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256_inv(uint8_t a); +uint8_t PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256_mul(uint8_t a, uint8_t b); + + +#endif // _GF16_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/parallel_matrix_op.c b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/parallel_matrix_op.c new file mode 100644 index 0000000000..2a444d7cd0 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/parallel_matrix_op.c @@ -0,0 +1,183 @@ +/// @file parallel_matrix_op.c +/// @brief the standard implementations for functions in parallel_matrix_op.h +/// +/// the standard implementations for functions in parallel_matrix_op.h +/// + +#include "parallel_matrix_op.h" +#include "blas.h" +#include "blas_comm.h" + +/// +/// @brief Calculate the corresponding index in an array for an upper-triangle(UT) matrix. +/// +/// @param[in] i_row - the i-th row in an upper-triangle matrix. +/// @param[in] j_col - the j-th column in an upper-triangle matrix. +/// @param[in] dim - the dimension of the upper-triangle matrix, i.e., an dim x dim matrix. +/// @return the corresponding index in an array storage. +/// +unsigned int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_idx_of_trimat(unsigned int i_row, unsigned int j_col, unsigned int dim) { + return (dim + dim - i_row + 1) * i_row / 2 + j_col - i_row; +} + +/// +/// @brief Calculate the corresponding index in an array for an upper-triangle or lower-triangle matrix. +/// +/// @param[in] i_row - the i-th row in a triangle matrix. +/// @param[in] j_col - the j-th column in a triangle matrix. +/// @param[in] dim - the dimension of the triangle matrix, i.e., an dim x dim matrix. +/// @return the corresponding index in an array storage. +/// +static inline unsigned int idx_of_2trimat(unsigned int i_row, unsigned int j_col, unsigned int n_var) { + if (i_row > j_col) { + return PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_idx_of_trimat(j_col, i_row, n_var); + } + return PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_idx_of_trimat(i_row, j_col, n_var); +} + +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_UpperTrianglize(unsigned char *btriC, const unsigned char *bA, unsigned int Awidth, unsigned int size_batch) { + unsigned char *runningC = btriC; + unsigned int Aheight = Awidth; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < i; j++) { + unsigned int idx = PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_idx_of_trimat(j, i, Aheight); + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_add(btriC + idx * size_batch, bA + size_batch * (i * Awidth + j), size_batch); + } + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_add(runningC, bA + size_batch * (i * Awidth + i), size_batch * (Aheight - i)); + runningC += size_batch * (Aheight - i); + } +} + +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Awidth = Bheight; + unsigned int Aheight = Awidth; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + if (k < i) { + continue; + } + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_madd(bC, &btriA[(k - i) * size_batch], PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + btriA += (Aheight - i) * size_batch; + } +} + +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_trimatTr_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Aheight = Bheight; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + if (i < k) { + continue; + } + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_madd(bC, &btriA[size_batch * (PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_idx_of_trimat(k, i, Aheight))], PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_2trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Aheight = Bheight; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + if (i == k) { + continue; + } + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_madd(bC, &btriA[size_batch * (idx_of_2trimat(i, k, Aheight))], PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_matTr_madd_gf256(unsigned char *bC, const unsigned char *A_to_tr, unsigned int Aheight, unsigned int size_Acolvec, unsigned int Awidth, + const unsigned char *bB, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Atr_height = Awidth; + unsigned int Atr_width = Aheight; + for (unsigned int i = 0; i < Atr_height; i++) { + for (unsigned int j = 0; j < Atr_width; j++) { + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_madd(bC, &bB[j * Bwidth * size_batch], PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_get_ele(&A_to_tr[size_Acolvec * i], j), size_batch * Bwidth); + } + bC += size_batch * Bwidth; + } +} + +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_bmatTr_madd_gf256(unsigned char *bC, const unsigned char *bA_to_tr, unsigned int Awidth_before_tr, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + const unsigned char *bA = bA_to_tr; + unsigned int Aheight = Awidth_before_tr; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_madd(bC, &bA[size_batch * (i + k * Aheight)], PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_mat_madd_gf256(unsigned char *bC, const unsigned char *bA, unsigned int Aheight, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Awidth = Bheight; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_madd(bC, &bA[k * size_batch], PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + bA += (Awidth) * size_batch; + } +} + +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_quad_trimat_eval_gf256(unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned int dim, unsigned int size_batch) { + unsigned char tmp[256]; + + unsigned char _x[256]; + for (unsigned int i = 0; i < dim; i++) { + _x[i] = PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_get_ele(x, i); + } + + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_set_zero(y, size_batch); + for (unsigned int i = 0; i < dim; i++) { + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_set_zero(tmp, size_batch); + for (unsigned int j = i; j < dim; j++) { + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_madd(tmp, trimat, _x[j], size_batch); + trimat += size_batch; + } + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_madd(y, tmp, _x[i], size_batch); + } +} + +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_quad_recmat_eval_gf256(unsigned char *z, const unsigned char *y, unsigned int dim_y, const unsigned char *mat, + const unsigned char *x, unsigned dim_x, unsigned size_batch) { + unsigned char tmp[128]; + + unsigned char _x[128]; + for (unsigned int i = 0; i < dim_x; i++) { + _x[i] = PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_get_ele(x, i); + } + unsigned char _y[128]; + for (unsigned int i = 0; i < dim_y; i++) { + _y[i] = PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_get_ele(y, i); + } + + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_set_zero(z, size_batch); + for (unsigned int i = 0; i < dim_y; i++) { + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_set_zero(tmp, size_batch); + for (unsigned int j = 0; j < dim_x; j++) { + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_madd(tmp, mat, _x[j], size_batch); + mat += size_batch; + } + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_madd(z, tmp, _y[i], size_batch); + } +} + diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/parallel_matrix_op.h b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/parallel_matrix_op.h new file mode 100644 index 0000000000..6ce3d8c646 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/parallel_matrix_op.h @@ -0,0 +1,260 @@ +#ifndef _P_MATRIX_OP_H_ +#define _P_MATRIX_OP_H_ +/// @file parallel_matrix_op.h +/// @brief Librarys for operations of batched matrixes. +/// +/// + +//////////////// Section: triangle matrix <-> rectangle matrix /////////////////////////////////// + +/// +/// @brief Calculate the corresponding index in an array for an upper-triangle(UT) matrix. +/// +/// @param[in] i_row - the i-th row in an upper-triangle matrix. +/// @param[in] j_col - the j-th column in an upper-triangle matrix. +/// @param[in] dim - the dimension of the upper-triangle matrix, i.e., an dim x dim matrix. +/// @return the corresponding index in an array storage. +/// +unsigned int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_idx_of_trimat(unsigned int i_row, unsigned int j_col, unsigned int dim); + +/// +/// @brief Upper trianglize a rectangle matrix to the corresponding upper-trangle matrix. +/// +/// @param[out] btriC - the batched upper-trianglized matrix C. +/// @param[in] bA - a batched retangle matrix A. +/// @param[in] bwidth - the width of the batched matrix A, i.e., A is a Awidth x Awidth matrix. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_UpperTrianglize(unsigned char *btriC, const unsigned char *bA, unsigned int Awidth, unsigned int size_batch); + +//////////////////// Section: matrix multiplications /////////////////////////////// + +/// +/// @brief bC += btriA * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_trimat_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += btriA * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += btriA^Tr * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. A will be transposed while multiplying. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_trimatTr_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += btriA^Tr * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A, which will be transposed while multiplying. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_trimatTr_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += (btriA + btriA^Tr) *B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. The operand for multiplication is (btriA + btriA^Tr). +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_2trimat_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += (btriA + btriA^Tr) *B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. The operand for multiplication is (btriA + btriA^Tr). +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_2trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += A^Tr * bB , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] A_to_tr - a column-major matrix A. The operand for multiplication is A^Tr. +/// @param[in] Aheight - the height of A. +/// @param[in] size_Acolvec - the size of a column vector in A. +/// @param[in] Awidth - the width of A. +/// @param[in] bB - a batched matrix B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_matTr_madd_gf16(unsigned char *bC, + const unsigned char *A_to_tr, unsigned int Aheight, unsigned int size_Acolvec, unsigned int Awidth, + const unsigned char *bB, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += A^Tr * bB , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] A_to_tr - a column-major matrix A. The operand for multiplication is A^Tr. +/// @param[in] Aheight - the height of A. +/// @param[in] size_Acolvec - the size of a column vector in A. +/// @param[in] Awidth - the width of A. +/// @param[in] bB - a batched matrix B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_matTr_madd_gf256(unsigned char *bC, + const unsigned char *A_to_tr, unsigned int Aheight, unsigned int size_Acolvec, unsigned int Awidth, + const unsigned char *bB, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA^Tr * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA_to_tr - a batched matrix A. The operand for multiplication is (bA^Tr). +/// @param[in] Awidth_befor_tr - the width of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_bmatTr_madd_gf16(unsigned char *bC, const unsigned char *bA_to_tr, unsigned int Awidth_before_tr, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA^Tr * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA_to_tr - a batched matrix A. The operand for multiplication is (bA^Tr). +/// @param[in] Awidth_befor_tr - the width of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_bmatTr_madd_gf256(unsigned char *bC, const unsigned char *bA_to_tr, unsigned int Awidth_before_tr, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA - a batched matrix A. +/// @param[in] Aheigh - the height of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_mat_madd_gf16(unsigned char *bC, const unsigned char *bA, unsigned int Aheight, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA - a batched matrix A. +/// @param[in] Aheigh - the height of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_mat_madd_gf256(unsigned char *bC, const unsigned char *bA, unsigned int Aheight, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +//////////////////// Section: "quadratric" matrix evaluation /////////////////////////////// + +/// +/// @brief y = x^Tr * trimat * x , in GF(16) +/// +/// @param[out] y - the returned batched element y. +/// @param[in] trimat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim - the dimension of matrix trimat (and x). +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_quad_trimat_eval_gf16(unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned int dim, unsigned int size_batch); + +/// +/// @brief y = x^Tr * trimat * x , in GF(256) +/// +/// @param[out] y - the returned batched element y. +/// @param[in] trimat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim - the dimension of matrix trimat (and x). +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_quad_trimat_eval_gf256(unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned int dim, unsigned int size_batch); + +/// +/// @brief z = y^Tr * mat * x , in GF(16) +/// +/// @param[out] z - the returned batched element z. +/// @param[in] y - an input vector y. +/// @param[in] dim_y - the length of y. +/// @param[in] mat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim_x - the length of x. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_quad_recmat_eval_gf16(unsigned char *z, const unsigned char *y, unsigned int dim_y, + const unsigned char *mat, const unsigned char *x, unsigned int dim_x, unsigned int size_batch); + +/// +/// @brief z = y^Tr * mat * x , in GF(256) +/// +/// @param[out] z - the returned batched element z. +/// @param[in] y - an input vector y. +/// @param[in] dim_y - the length of y. +/// @param[in] mat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim_x - the length of x. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_quad_recmat_eval_gf256(unsigned char *z, const unsigned char *y, unsigned int dim_y, + const unsigned char *mat, const unsigned char *x, unsigned int dim_x, unsigned int size_batch); + +#endif // _P_MATRIX_OP_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/rainbow.c b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/rainbow.c new file mode 100644 index 0000000000..76fc687988 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/rainbow.c @@ -0,0 +1,179 @@ +/// @file rainbow.c +/// @brief The standard implementations for functions in rainbow.h +/// + +#include "blas.h" +#include "parallel_matrix_op.h" +#include "rainbow.h" +#include "rainbow_blas.h" +#include "rainbow_config.h" +#include "rainbow_keypair.h" +#include "utils_hash.h" +#include "utils_prng.h" +#include +#include +#include + +#define MAX_ATTEMPT_FRMAT 128 + +int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_rainbow_sign(uint8_t *signature, const sk_t *sk, const uint8_t *_digest) { + uint8_t mat_l1[_O1 * _O1_BYTE]; + uint8_t mat_l2[_O2 * _O2_BYTE]; + uint8_t mat_buffer[2 * _MAX_O * _MAX_O_BYTE]; + + // setup PRNG + prng_t prng_sign; + uint8_t prng_preseed[LEN_SKSEED + _HASH_LEN]; + memcpy(prng_preseed, sk->sk_seed, LEN_SKSEED); + memcpy(prng_preseed + LEN_SKSEED, _digest, _HASH_LEN); // prng_preseed = sk_seed || digest + uint8_t prng_seed[_HASH_LEN]; + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_hash_msg(prng_seed, _HASH_LEN, prng_preseed, _HASH_LEN + LEN_SKSEED); + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_prng_set(&prng_sign, prng_seed, _HASH_LEN); // seed = H( sk_seed || digest ) + for (unsigned int i = 0; i < LEN_SKSEED + _HASH_LEN; i++) { + prng_preseed[i] ^= prng_preseed[i]; // clean + } + for (unsigned int i = 0; i < _HASH_LEN; i++) { + prng_seed[i] ^= prng_seed[i]; // clean + } + + // roll vinegars. + uint8_t vinegar[_V1_BYTE]; + unsigned int n_attempt = 0; + unsigned int l1_succ = 0; + while (!l1_succ) { + if (MAX_ATTEMPT_FRMAT <= n_attempt) { + break; + } + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_prng_gen(&prng_sign, vinegar, _V1_BYTE); // generating vinegars + gfmat_prod(mat_l1, sk->l1_F2, _O1 * _O1_BYTE, _V1, vinegar); // generating the linear equations for layer 1 + l1_succ = gfmat_inv(mat_l1, mat_l1, _O1, mat_buffer); // check if the linear equation solvable + n_attempt++; + } + + // Given the vinegars, pre-compute variables needed for layer 2 + uint8_t r_l1_F1[_O1_BYTE] = {0}; + uint8_t r_l2_F1[_O2_BYTE] = {0}; + batch_quad_trimat_eval(r_l1_F1, sk->l1_F1, vinegar, _V1, _O1_BYTE); + batch_quad_trimat_eval(r_l2_F1, sk->l2_F1, vinegar, _V1, _O2_BYTE); + uint8_t mat_l2_F3[_O2 * _O2_BYTE]; + uint8_t mat_l2_F2[_O1 * _O2_BYTE]; + gfmat_prod(mat_l2_F3, sk->l2_F3, _O2 * _O2_BYTE, _V1, vinegar); + gfmat_prod(mat_l2_F2, sk->l2_F2, _O1 * _O2_BYTE, _V1, vinegar); + + // Some local variables. + uint8_t _z[_PUB_M_BYTE]; + uint8_t y[_PUB_M_BYTE]; + uint8_t *x_v1 = vinegar; + uint8_t x_o1[_O1_BYTE]; + uint8_t x_o2[_O1_BYTE]; + + uint8_t digest_salt[_HASH_LEN + _SALT_BYTE]; + memcpy(digest_salt, _digest, _HASH_LEN); + uint8_t *salt = digest_salt + _HASH_LEN; + + uint8_t temp_o[_MAX_O_BYTE + 32] = {0}; + unsigned int succ = 0; + while (!succ) { + if (MAX_ATTEMPT_FRMAT <= n_attempt) { + break; + } + // The computation: H(digest||salt) --> z --S--> y --C-map--> x --T--> w + + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_prng_gen(&prng_sign, salt, _SALT_BYTE); // roll the salt + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_hash_msg(_z, _PUB_M_BYTE, digest_salt, _HASH_LEN + _SALT_BYTE); // H(digest||salt) + + // y = S^-1 * z + memcpy(y, _z, _PUB_M_BYTE); // identity part of S + gfmat_prod(temp_o, sk->s1, _O1_BYTE, _O2, _z + _O1_BYTE); + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_add(y, temp_o, _O1_BYTE); + + // Central Map: + // layer 1: calculate x_o1 + memcpy(temp_o, r_l1_F1, _O1_BYTE); + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_add(temp_o, y, _O1_BYTE); + gfmat_prod(x_o1, mat_l1, _O1_BYTE, _O1, temp_o); + + // layer 2: calculate x_o2 + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_set_zero(temp_o, _O2_BYTE); + gfmat_prod(temp_o, mat_l2_F2, _O2_BYTE, _O1, x_o1); // F2 + batch_quad_trimat_eval(mat_l2, sk->l2_F5, x_o1, _O1, _O2_BYTE); // F5 + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_add(temp_o, mat_l2, _O2_BYTE); + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_add(temp_o, r_l2_F1, _O2_BYTE); // F1 + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_add(temp_o, y + _O1_BYTE, _O2_BYTE); + + // generate the linear equations of the 2nd layer + gfmat_prod(mat_l2, sk->l2_F6, _O2 * _O2_BYTE, _O1, x_o1); // F6 + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_add(mat_l2, mat_l2_F3, _O2 * _O2_BYTE); // F3 + succ = gfmat_inv(mat_l2, mat_l2, _O2, mat_buffer); + gfmat_prod(x_o2, mat_l2, _O2_BYTE, _O2, temp_o); // solve l2 eqs + + n_attempt++; + }; + // w = T^-1 * y + uint8_t w[_PUB_N_BYTE]; + // identity part of T. + memcpy(w, x_v1, _V1_BYTE); + memcpy(w + _V1_BYTE, x_o1, _O1_BYTE); + memcpy(w + _V2_BYTE, x_o2, _O2_BYTE); + // Computing the t1 part. + gfmat_prod(y, sk->t1, _V1_BYTE, _O1, x_o1); + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_add(w, y, _V1_BYTE); + // Computing the t4 part. + gfmat_prod(y, sk->t4, _V1_BYTE, _O2, x_o2); + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_add(w, y, _V1_BYTE); + // Computing the t3 part. + gfmat_prod(y, sk->t3, _O1_BYTE, _O2, x_o2); + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_add(w + _V1_BYTE, y, _O1_BYTE); + + memset(signature, 0, _SIGNATURE_BYTE); // set the output 0 + // clean + memset(&prng_sign, 0, sizeof(prng_t)); + memset(vinegar, 0, _V1_BYTE); + memset(r_l1_F1, 0, _O1_BYTE); + memset(r_l2_F1, 0, _O2_BYTE); + memset(_z, 0, _PUB_M_BYTE); + memset(y, 0, _PUB_M_BYTE); + memset(x_o1, 0, _O1_BYTE); + memset(x_o2, 0, _O2_BYTE); + memset(temp_o, 0, sizeof(temp_o)); + + // return: copy w and salt to the signature. + if (MAX_ATTEMPT_FRMAT <= n_attempt) { + return -1; + } + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_add(signature, w, _PUB_N_BYTE); + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_add(signature + _PUB_N_BYTE, salt, _SALT_BYTE); + return 0; +} + +int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_rainbow_verify(const uint8_t *digest, const uint8_t *signature, const pk_t *pk) { + unsigned char digest_ck[_PUB_M_BYTE]; + // public_map( digest_ck , pk , signature ); Evaluating the quadratic public polynomials. + batch_quad_trimat_eval(digest_ck, pk->pk, signature, _PUB_N, _PUB_M_BYTE); + + unsigned char correct[_PUB_M_BYTE]; + unsigned char digest_salt[_HASH_LEN + _SALT_BYTE]; + memcpy(digest_salt, digest, _HASH_LEN); + memcpy(digest_salt + _HASH_LEN, signature + _PUB_N_BYTE, _SALT_BYTE); + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_hash_msg(correct, _PUB_M_BYTE, digest_salt, _HASH_LEN + _SALT_BYTE); // H( digest || salt ) + + // check consistancy. + unsigned char cc = 0; + for (unsigned int i = 0; i < _PUB_M_BYTE; i++) { + cc |= (digest_ck[i] ^ correct[i]); + } + return (0 == cc) ? 0 : -1; +} + +/////////////// cyclic version /////////////////////////// +int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_rainbow_sign_cyclic(uint8_t *signature, const csk_t *csk, const uint8_t *digest) { + unsigned char sk[sizeof(sk_t) + 32]; + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_generate_secretkey_cyclic((sk_t *)sk, csk->pk_seed, csk->sk_seed); // generating classic secret key. + return PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_rainbow_sign(signature, (sk_t *)sk, digest); +} + +int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_rainbow_verify_cyclic(const uint8_t *digest, const uint8_t *signature, const cpk_t *_pk) { + unsigned char pk[sizeof(pk_t) + 32]; + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_cpk_to_pk((pk_t *)pk, _pk); // generating classic public key. + return PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_rainbow_verify(digest, signature, (pk_t *)pk); +} diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/rainbow.h b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/rainbow.h new file mode 100644 index 0000000000..116735d6d7 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/rainbow.h @@ -0,0 +1,50 @@ +#ifndef _RAINBOW_H_ +#define _RAINBOW_H_ +/// @file rainbow.h +/// @brief APIs for rainbow. +/// + +#include "rainbow_config.h" +#include "rainbow_keypair.h" + +#include + +/// +/// @brief Signing function for classical secret key. +/// +/// @param[out] signature - the signature. +/// @param[in] sk - the secret key. +/// @param[in] digest - the digest. +/// +int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_rainbow_sign(uint8_t *signature, const sk_t *sk, const uint8_t *digest); + +/// +/// @brief Verifying function. +/// +/// @param[in] digest - the digest. +/// @param[in] signature - the signature. +/// @param[in] pk - the public key. +/// @return 0 for successful verified. -1 for failed verification. +/// +int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_rainbow_verify(const uint8_t *digest, const uint8_t *signature, const pk_t *pk); + +/// +/// @brief Signing function for compressed secret key of the cyclic rainbow. +/// +/// @param[out] signature - the signature. +/// @param[in] sk - the compressed secret key. +/// @param[in] digest - the digest. +/// +int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_rainbow_sign_cyclic(uint8_t *signature, const csk_t *sk, const uint8_t *digest); + +/// +/// @brief Verifying function for cyclic public keys. +/// +/// @param[in] digest - the digest. +/// @param[in] signature - the signature. +/// @param[in] pk - the public key of cyclic rainbow. +/// @return 0 for successful verified. -1 for failed verification. +/// +int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_rainbow_verify_cyclic(const uint8_t *digest, const uint8_t *signature, const cpk_t *pk); + +#endif // _RAINBOW_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/rainbow_blas.h b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/rainbow_blas.h new file mode 100644 index 0000000000..6d83db42a8 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/rainbow_blas.h @@ -0,0 +1,32 @@ +#ifndef _RAINBOW_BLAS_H_ +#define _RAINBOW_BLAS_H_ +/// @file rainbow_blas.h +/// @brief Defining the functions used in rainbow.c acconding to the definitions in rainbow_config.h +/// +/// Defining the functions used in rainbow.c acconding to the definitions in rainbow_config.h + +#include "blas.h" +#include "blas_comm.h" +#include "parallel_matrix_op.h" +#include "rainbow_config.h" + + +#define gfv_get_ele PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_get_ele +#define gfv_mul_scalar PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_mul_scalar +#define gfv_madd PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_madd + +#define gfmat_prod PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256mat_prod +#define gfmat_inv PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256mat_inv + +#define batch_trimat_madd PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_trimat_madd_gf256 +#define batch_trimatTr_madd PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_trimatTr_madd_gf256 +#define batch_2trimat_madd PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_2trimat_madd_gf256 +#define batch_matTr_madd PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_matTr_madd_gf256 +#define batch_bmatTr_madd PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_bmatTr_madd_gf256 +#define batch_mat_madd PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_mat_madd_gf256 + +#define batch_quad_trimat_eval PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_quad_trimat_eval_gf256 +#define batch_quad_recmat_eval PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_batch_quad_recmat_eval_gf256 + + +#endif // _RAINBOW_BLAS_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/rainbow_config.h b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/rainbow_config.h new file mode 100644 index 0000000000..f691dfb11a --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/rainbow_config.h @@ -0,0 +1,48 @@ +#ifndef _H_RAINBOW_CONFIG_H_ +#define _H_RAINBOW_CONFIG_H_ + +/// @file rainbow_config.h +/// @brief Defining the parameters of the Rainbow and the corresponding constants. +/// + +#define _GFSIZE 256 +#define _V1 92 +#define _O1 48 +#define _O2 48 +#define _MAX_O 48 +#define _HASH_LEN 64 + + +#define _V2 ((_V1) + (_O1)) + +/// size of N, in # of gf elements. +#define _PUB_N (_V1 + _O1 + _O2) + +/// size of M, in # gf elements. +#define _PUB_M (_O1 + _O2) + +/// size of variables, in # bytes. + +// GF256 +#define _V1_BYTE (_V1) +#define _V2_BYTE (_V2) +#define _O1_BYTE (_O1) +#define _O2_BYTE (_O2) +#define _MAX_O_BYTE (_MAX_O) +#define _PUB_N_BYTE (_PUB_N) +#define _PUB_M_BYTE (_PUB_M) + + +/// length of seed for public key, in # bytes +#define LEN_PKSEED 32 + +/// length of seed for secret key, in # bytes +#define LEN_SKSEED 32 + +/// length of salt for a signature, in # bytes +#define _SALT_BYTE 16 + +/// length of a signature +#define _SIGNATURE_BYTE (_PUB_N_BYTE + _SALT_BYTE) + +#endif // _H_RAINBOW_CONFIG_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/rainbow_keypair.c b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/rainbow_keypair.c new file mode 100644 index 0000000000..614fc9e530 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/rainbow_keypair.c @@ -0,0 +1,188 @@ +/// @file rainbow_keypair.c +/// @brief implementations of functions in rainbow_keypair.h +/// + +#include "rainbow_keypair.h" +#include "blas.h" +#include "blas_comm.h" +#include "rainbow_blas.h" +#include "rainbow_keypair_computation.h" +#include "utils_prng.h" +#include +#include +#include + +static void generate_S_T(unsigned char *s_and_t, prng_t *prng0) { + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_prng_gen(prng0, s_and_t, _O1_BYTE * _O2); // S1 + s_and_t += _O1_BYTE * _O2; + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_prng_gen(prng0, s_and_t, _V1_BYTE * _O1); // T1 + s_and_t += _V1_BYTE * _O1; + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_prng_gen(prng0, s_and_t, _V1_BYTE * _O2); // T2 + s_and_t += _V1_BYTE * _O2; + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_prng_gen(prng0, s_and_t, _O1_BYTE * _O2); // T3 +} + +static unsigned int generate_l1_F12(unsigned char *sk, prng_t *prng0) { + unsigned int n_byte_generated = 0; + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_prng_gen(prng0, sk, _O1_BYTE * N_TRIANGLE_TERMS(_V1)); // l1_F1 + sk += _O1_BYTE * N_TRIANGLE_TERMS(_V1); + n_byte_generated += _O1_BYTE * N_TRIANGLE_TERMS(_V1); + + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_prng_gen(prng0, sk, _O1_BYTE * _V1 * _O1); // l1_F2 + n_byte_generated += _O1_BYTE * _V1 * _O1; + return n_byte_generated; +} + +static unsigned int generate_l2_F12356(unsigned char *sk, prng_t *prng0) { + unsigned int n_byte_generated = 0; + + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_prng_gen(prng0, sk, _O2_BYTE * N_TRIANGLE_TERMS(_V1)); // l2_F1 + sk += _O2_BYTE * N_TRIANGLE_TERMS(_V1); + n_byte_generated += _O2_BYTE * N_TRIANGLE_TERMS(_V1); + + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_prng_gen(prng0, sk, _O2_BYTE * _V1 * _O1); // l2_F2 + sk += _O2_BYTE * _V1 * _O1; + n_byte_generated += _O2_BYTE * _V1 * _O1; + + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_prng_gen(prng0, sk, _O2_BYTE * _V1 * _O2); // l2_F3 + sk += _O2_BYTE * _V1 * _O1; + n_byte_generated += _O2_BYTE * _V1 * _O1; + + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_prng_gen(prng0, sk, _O2_BYTE * N_TRIANGLE_TERMS(_O1)); // l2_F5 + sk += _O2_BYTE * N_TRIANGLE_TERMS(_O1); + n_byte_generated += _O2_BYTE * N_TRIANGLE_TERMS(_O1); + + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_prng_gen(prng0, sk, _O2_BYTE * _O1 * _O2); // l2_F6 + n_byte_generated += _O2_BYTE * _O1 * _O2; + + return n_byte_generated; +} + +static void generate_B1_B2(unsigned char *sk, prng_t *prng0) { + sk += generate_l1_F12(sk, prng0); + generate_l2_F12356(sk, prng0); +} + +static void calculate_t4(unsigned char *t2_to_t4, const unsigned char *t1, const unsigned char *t3) { + // t4 = T_sk.t1 * T_sk.t3 - T_sk.t2 + unsigned char temp[_V1_BYTE + 32]; + unsigned char *t4 = t2_to_t4; + for (unsigned int i = 0; i < _O2; i++) { /// t3 width + gfmat_prod(temp, t1, _V1_BYTE, _O1, t3); + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_add(t4, temp, _V1_BYTE); + t4 += _V1_BYTE; + t3 += _O1_BYTE; + } +} + +static void obsfucate_l1_polys(unsigned char *l1_polys, const unsigned char *l2_polys, unsigned int n_terms, const unsigned char *s1) { + unsigned char temp[_O1_BYTE + 32]; + while (n_terms--) { + gfmat_prod(temp, s1, _O1_BYTE, _O2, l2_polys); + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_gf256v_add(l1_polys, temp, _O1_BYTE); + l1_polys += _O1_BYTE; + l2_polys += _O2_BYTE; + } +} + +/////////////////// Classic ////////////////////////////////// + + +///////////////////// Cyclic ////////////////////////////////// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_generate_keypair_cyclic(cpk_t *pk, sk_t *sk, const unsigned char *pk_seed, const unsigned char *sk_seed) { + memcpy(pk->pk_seed, pk_seed, LEN_PKSEED); + memcpy(sk->sk_seed, sk_seed, LEN_SKSEED); + + // prng for sk + prng_t prng; + prng_t *prng0 = &prng; + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_prng_set(prng0, sk_seed, LEN_SKSEED); + generate_S_T(sk->s1, prng0); // S,T: only a part of sk + + unsigned char t2[sizeof(sk->t4)]; + memcpy(t2, sk->t4, _V1_BYTE * _O2); // temporarily store t2 + calculate_t4(sk->t4, sk->t1, sk->t3); // t2 <- t4 + + // prng for pk + sk_t inst_Qs; + sk_t *Qs = &inst_Qs; + prng_t *prng1 = &prng; + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_prng_set(prng1, pk_seed, LEN_PKSEED); + generate_B1_B2(Qs->l1_F1, prng1); // generating l1_Q1, l1_Q2, l2_Q1, l2_Q2, l2_Q3, l2_Q5, l2_Q6 + obsfucate_l1_polys(Qs->l1_F1, Qs->l2_F1, N_TRIANGLE_TERMS(_V1), sk->s1); + obsfucate_l1_polys(Qs->l1_F2, Qs->l2_F2, _V1 * _O1, sk->s1); + // so far, the Qs contains l1_F1, l1_F2, l2_F1, l2_F2, l2_F3, l2_F5, l2_F6. + + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_calculate_F_from_Q(sk, Qs, sk); // calcuate the rest parts of secret key from Qs and S,T + + unsigned char t4[sizeof(sk->t4)]; + memcpy(t4, sk->t4, _V1_BYTE * _O2); // temporarily store t4 + memcpy(sk->t4, t2, _V1_BYTE * _O2); // restore t2 + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_calculate_Q_from_F_cyclic(pk, sk, sk); // calculate the rest parts of public key: l1_Q3, l1_Q5, l1_Q6, l1_Q9, l2_Q9 + memcpy(sk->t4, t4, _V1_BYTE * _O2); // restore t4 + + obsfucate_l1_polys(pk->l1_Q3, Qs->l2_F3, _V1 * _O2, sk->s1); + obsfucate_l1_polys(pk->l1_Q5, Qs->l2_F5, N_TRIANGLE_TERMS(_O1), sk->s1); + obsfucate_l1_polys(pk->l1_Q6, Qs->l2_F6, _O1 * _O2, sk->s1); + obsfucate_l1_polys(pk->l1_Q9, pk->l2_Q9, N_TRIANGLE_TERMS(_O2), sk->s1); + + // clean + memset(&prng, 0, sizeof(prng_t)); +} + + +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_generate_compact_keypair_cyclic(cpk_t *pk, csk_t *rsk, const unsigned char *pk_seed, const unsigned char *sk_seed) { + memcpy(rsk->pk_seed, pk_seed, LEN_PKSEED); + memcpy(rsk->sk_seed, sk_seed, LEN_SKSEED); + sk_t sk; + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_generate_keypair_cyclic(pk, &sk, pk_seed, sk_seed); +} + +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_generate_secretkey_cyclic(sk_t *sk, const unsigned char *pk_seed, const unsigned char *sk_seed) { + memcpy(sk->sk_seed, sk_seed, LEN_SKSEED); + + // prng for sk + prng_t prng0; + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_prng_set(&prng0, sk_seed, LEN_SKSEED); + generate_S_T(sk->s1, &prng0); + calculate_t4(sk->t4, sk->t1, sk->t3); + + // prng for pk + sk_t inst_Qs; + sk_t *Qs = &inst_Qs; + prng_t prng1; + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_prng_set(&prng1, pk_seed, LEN_PKSEED); + generate_B1_B2(Qs->l1_F1, &prng1); + + obsfucate_l1_polys(Qs->l1_F1, Qs->l2_F1, N_TRIANGLE_TERMS(_V1), sk->s1); + obsfucate_l1_polys(Qs->l1_F2, Qs->l2_F2, _V1 * _O1, sk->s1); + + // calcuate the parts of sk according to pk. + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_calculate_F_from_Q(sk, Qs, sk); + + // clean prng for sk + memset(&prng0, 0, sizeof(prng_t)); +} +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_cpk_to_pk(pk_t *rpk, const cpk_t *cpk) { + // procedure: cpk_t --> extcpk_t --> pk_t + + // convert from cpk_t to extcpk_t + ext_cpk_t pk; + + // setup prng + prng_t prng0; + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_prng_set(&prng0, cpk->pk_seed, LEN_SKSEED); + + // generating parts of key with prng + generate_l1_F12(pk.l1_Q1, &prng0); + // copying parts of key from input. l1_Q3, l1_Q5, l1_Q6, l1_Q9 + memcpy(pk.l1_Q3, cpk->l1_Q3, _O1_BYTE * (_V1 * _O2 + N_TRIANGLE_TERMS(_O1) + _O1 * _O2 + N_TRIANGLE_TERMS(_O2))); + + // generating parts of key with prng + generate_l2_F12356(pk.l2_Q1, &prng0); + // copying parts of key from input: l2_Q9 + memcpy(pk.l2_Q9, cpk->l2_Q9, _O2_BYTE * N_TRIANGLE_TERMS(_O2)); + + // convert from extcpk_t to pk_t + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_extcpk_to_pk(rpk, &pk); +} diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/rainbow_keypair.h b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/rainbow_keypair.h new file mode 100644 index 0000000000..f0ccb7465a --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/rainbow_keypair.h @@ -0,0 +1,111 @@ +#ifndef _RAINBOW_KEYPAIR_H_ +#define _RAINBOW_KEYPAIR_H_ +/// @file rainbow_keypair.h +/// @brief Formats of key pairs and functions for generating key pairs. +/// Formats of key pairs and functions for generating key pairs. +/// + +#include "rainbow_config.h" + +#define N_TRIANGLE_TERMS(n_var) ((n_var) * ((n_var) + 1) / 2) + +/// @brief public key for classic rainbow +/// +/// public key for classic rainbow +/// +typedef struct rainbow_publickey { + unsigned char pk[(_PUB_M_BYTE)*N_TRIANGLE_TERMS(_PUB_N)]; +} pk_t; + +/// @brief secret key for classic rainbow +/// +/// secret key for classic rainbow +/// +typedef struct rainbow_secretkey { + /// + /// seed for generating secret key. + /// Generating S, T, and F for classic rainbow. + /// Generating S and T only for cyclic rainbow. + unsigned char sk_seed[LEN_SKSEED]; + + unsigned char s1[_O1_BYTE * _O2]; ///< part of S map + unsigned char t1[_V1_BYTE * _O1]; ///< part of T map + unsigned char t4[_V1_BYTE * _O2]; ///< part of T map + unsigned char t3[_O1_BYTE * _O2]; ///< part of T map + + unsigned char l1_F1[_O1_BYTE * N_TRIANGLE_TERMS(_V1)]; ///< part of C-map, F1, Layer1 + unsigned char l1_F2[_O1_BYTE * _V1 * _O1]; ///< part of C-map, F2, Layer1 + + unsigned char l2_F1[_O2_BYTE * N_TRIANGLE_TERMS(_V1)]; ///< part of C-map, F1, Layer2 + unsigned char l2_F2[_O2_BYTE * _V1 * _O1]; ///< part of C-map, F2, Layer2 + + unsigned char l2_F3[_O2_BYTE * _V1 * _O2]; ///< part of C-map, F3, Layer2 + unsigned char l2_F5[_O2_BYTE * N_TRIANGLE_TERMS(_O1)]; ///< part of C-map, F5, Layer2 + unsigned char l2_F6[_O2_BYTE * _O1 * _O2]; ///< part of C-map, F6, Layer2 +} sk_t; + +/// @brief public key for cyclic rainbow +/// +/// public key for cyclic rainbow +/// +typedef struct rainbow_publickey_cyclic { + unsigned char pk_seed[LEN_PKSEED]; ///< seed for generating l1_Q1,l1_Q2,l2_Q1,l2_Q2,l2_Q3,l2_Q5,l2_Q6 + + unsigned char l1_Q3[_O1_BYTE * _V1 * _O2]; ///< Q3, layer1 + unsigned char l1_Q5[_O1_BYTE * N_TRIANGLE_TERMS(_O1)]; ///< Q5, layer1 + unsigned char l1_Q6[_O1_BYTE * _O1 * _O2]; ///< Q6, layer1 + unsigned char l1_Q9[_O1_BYTE * N_TRIANGLE_TERMS(_O2)]; ///< Q9, layer1 + + unsigned char l2_Q9[_O2_BYTE * N_TRIANGLE_TERMS(_O2)]; ///< Q9, layer2 +} cpk_t; + +/// @brief compressed secret key for cyclic rainbow +/// +/// compressed secret key for cyclic rainbow +/// +typedef struct rainbow_secretkey_cyclic { + unsigned char pk_seed[LEN_PKSEED]; ///< seed for generating a part of public key. + unsigned char sk_seed[LEN_SKSEED]; ///< seed for generating a part of secret key. +} csk_t; + + +/// +/// @brief Generate key pairs for cyclic rainbow. +/// +/// @param[out] pk - the public key. +/// @param[out] sk - the secret key. +/// @param[in] pk_seed - seed for generating parts of public key. +/// @param[in] sk_seed - seed for generating secret key. +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_generate_keypair_cyclic(cpk_t *pk, sk_t *sk, const unsigned char *pk_seed, const unsigned char *sk_seed); + +/// +/// @brief Generate compressed key pairs for cyclic rainbow. +/// +/// @param[out] pk - the public key. +/// @param[out] sk - the compressed secret key. +/// @param[in] pk_seed - seed for generating parts of the public key. +/// @param[in] sk_seed - seed for generating the secret key. +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_generate_compact_keypair_cyclic(cpk_t *pk, csk_t *sk, const unsigned char *pk_seed, const unsigned char *sk_seed); + +/// +/// @brief Generate secret key for cyclic rainbow. +/// +/// @param[out] sk - the secret key. +/// @param[in] pk_seed - seed for generating parts of the pbulic key. +/// @param[in] sk_seed - seed for generating the secret key. +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_generate_secretkey_cyclic(sk_t *sk, const unsigned char *pk_seed, const unsigned char *sk_seed); + +//////////////////////////////////// + +/// +/// @brief converting formats of public keys : from cyclic version to classic key +/// +/// @param[out] pk - the classic public key. +/// @param[in] cpk - the cyclic public key. +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_cpk_to_pk(pk_t *pk, const cpk_t *cpk); + +#endif // _RAINBOW_KEYPAIR_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/rainbow_keypair_computation.c b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/rainbow_keypair_computation.c new file mode 100644 index 0000000000..3661f6c8fa --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/rainbow_keypair_computation.c @@ -0,0 +1,213 @@ +/// @file rainbow_keypair_computation.c +/// @brief Implementations for functions in rainbow_keypair_computation.h +/// + +#include "rainbow_keypair_computation.h" +#include "blas.h" +#include "blas_comm.h" +#include "rainbow_blas.h" +#include "rainbow_keypair.h" +#include +#include +#include + +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_extcpk_to_pk(pk_t *pk, const ext_cpk_t *cpk) { + const unsigned char *idx_l1 = cpk->l1_Q1; + const unsigned char *idx_l2 = cpk->l2_Q1; + for (unsigned int i = 0; i < _V1; i++) { + for (unsigned int j = i; j < _V1; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q2; + idx_l2 = cpk->l2_Q2; + for (unsigned int i = 0; i < _V1; i++) { + for (unsigned int j = _V1; j < _V1 + _O1; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q3; + idx_l2 = cpk->l2_Q3; + for (unsigned int i = 0; i < _V1; i++) { + for (unsigned int j = _V1 + _O1; j < _PUB_N; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q5; + idx_l2 = cpk->l2_Q5; + for (unsigned int i = _V1; i < _V1 + _O1; i++) { + for (unsigned int j = i; j < _V1 + _O1; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q6; + idx_l2 = cpk->l2_Q6; + for (unsigned int i = _V1; i < _V1 + _O1; i++) { + for (unsigned int j = _V1 + _O1; j < _PUB_N; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q9; + idx_l2 = cpk->l2_Q9; + for (unsigned int i = _V1 + _O1; i < _PUB_N; i++) { + for (unsigned int j = i; j < _PUB_N; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } +} + +static void calculate_F_from_Q_ref(sk_t *Fs, const sk_t *Qs, sk_t *Ts) { + // Layer 1 + // F_sk.l1_F1s[i] = Q_pk.l1_F1s[i] + memcpy(Fs->l1_F1, Qs->l1_F1, _O1_BYTE * N_TRIANGLE_TERMS(_V1)); + + // F_sk.l1_F2s[i] = ( Q_pk.l1_F1s[i] + Q_pk.l1_F1s[i].transpose() ) * T_sk.t1 + Q_pk.l1_F2s[i] + memcpy(Fs->l1_F2, Qs->l1_F2, _O1_BYTE * _V1 * _O1); + batch_2trimat_madd(Fs->l1_F2, Qs->l1_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O1_BYTE); + + /* + Layer 2 + computations: + + F_sk.l2_F1s[i] = Q_pk.l2_F1s[i] + + Q1_T1 = Q_pk.l2_F1s[i]*T_sk.t1 + F_sk.l2_F2s[i] = Q1_T1 + Q_pk.l2_F2s[i] + Q_pk.l2_F1s[i].transpose() * T_sk.t1 + F_sk.l2_F5s[i] = UT( t1_tr* ( Q1_T1 + Q_pk.l2_F2s[i] ) ) + Q_pk.l2_F5s[i] + + Q1_Q1T_T4 = (Q_pk.l2_F1s[i] + Q_pk.l2_F1s[i].transpose()) * t4 + #Q1_Q1T_T4 = Q1_Q1T * t4 + Q2_T3 = Q_pk.l2_F2s[i]*T_sk.t3 + F_sk.l2_F3s[i] = Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] + F_sk.l2_F6s[i] = t1_tr * ( Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] ) + + Q_pk.l2_F2s[i].transpose() * t4 + + (Q_pk.l2_F5s[i] + Q_pk.l2_F5s[i].transpose())*T_sk.t3 + Q_pk.l2_F6s[i] + + */ + memcpy(Fs->l2_F1, Qs->l2_F1, _O2_BYTE * N_TRIANGLE_TERMS(_V1)); // F_sk.l2_F1s[i] = Q_pk.l2_F1s[i] + + // F_sk.l2_F2s[i] = Q1_T1 + Q_pk.l2_F2s[i] + Q_pk.l2_F1s[i].transpose() * T_sk.t1 + // F_sk.l2_F5s[i] = UT( t1_tr* ( Q1_T1 + Q_pk.l2_F2s[i] ) ) + Q_pk.l2_F5s[i] + memcpy(Fs->l2_F2, Qs->l2_F2, _O2_BYTE * _V1 * _O1); + batch_trimat_madd(Fs->l2_F2, Qs->l2_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O2_BYTE); // Q1_T1+ Q2 + + unsigned char tempQ[_O1 * _O1 * _O2_BYTE + 32]; + memset(tempQ, 0, _O1 * _O1 * _O2_BYTE); + batch_matTr_madd(tempQ, Ts->t1, _V1, _V1_BYTE, _O1, Fs->l2_F2, _O1, _O2_BYTE); // t1_tr*(Q1_T1+Q2) + memcpy(Fs->l2_F5, Qs->l2_F5, _O2_BYTE * N_TRIANGLE_TERMS(_O1)); // F5 + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_UpperTrianglize(Fs->l2_F5, tempQ, _O1, _O2_BYTE); // UT( ... ) + + batch_trimatTr_madd(Fs->l2_F2, Qs->l2_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O2_BYTE); // F2 = Q1_T1 + Q2 + Q1^tr*t1 + + // Q1_Q1T_T4 = (Q_pk.l2_F1s[i] + Q_pk.l2_F1s[i].transpose()) * t4 + // Q2_T3 = Q_pk.l2_F2s[i]*T_sk.t3 + // F_sk.l2_F3s[i] = Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] + memcpy(Fs->l2_F3, Qs->l2_F3, _V1 * _O2 * _O2_BYTE); + batch_2trimat_madd(Fs->l2_F3, Qs->l2_F1, Ts->t4, _V1, _V1_BYTE, _O2, _O2_BYTE); // Q1_Q1T_T4 + batch_mat_madd(Fs->l2_F3, Qs->l2_F2, _V1, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // Q2_T3 + + // F_sk.l2_F6s[i] = t1_tr * ( Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] ) + // + Q_pk.l2_F2s[i].transpose() * t4 + // + (Q_pk.l2_F5s[i] + Q_pk.l2_F5s[i].transpose())*T_sk.t3 + Q_pk.l2_F6s[i] + memcpy(Fs->l2_F6, Qs->l2_F6, _O1 * _O2 * _O2_BYTE); + batch_matTr_madd(Fs->l2_F6, Ts->t1, _V1, _V1_BYTE, _O1, Fs->l2_F3, _O2, _O2_BYTE); // t1_tr * ( Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] ) + batch_2trimat_madd(Fs->l2_F6, Qs->l2_F5, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // (Q_pk.l2_F5s[i] + Q_pk.l2_F5s[i].transpose())*T_sk.t3 + batch_bmatTr_madd(Fs->l2_F6, Qs->l2_F2, _O1, Ts->t4, _V1, _V1_BYTE, _O2, _O2_BYTE); +} + +static void calculate_Q_from_F_cyclic_ref(cpk_t *Qs, const sk_t *Fs, const sk_t *Ts) { + // Layer 1: Computing Q5, Q3, Q6, Q9 + + // Q_pk.l1_F5s[i] = UT( T1tr* (F1 * T1 + F2) ) + const unsigned char *t2 = Ts->t4; + sk_t tempQ; + memcpy(tempQ.l1_F2, Fs->l1_F2, _O1_BYTE * _V1 * _O1); + batch_trimat_madd(tempQ.l1_F2, Fs->l1_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O1_BYTE); // F1*T1 + F2 + memset(tempQ.l2_F1, 0, sizeof(tempQ.l2_F1)); + memset(tempQ.l2_F2, 0, sizeof(tempQ.l2_F2)); + batch_matTr_madd(tempQ.l2_F1, Ts->t1, _V1, _V1_BYTE, _O1, tempQ.l1_F2, _O1, _O1_BYTE); // T1tr*(F1*T1 + F2) + memset(Qs->l1_Q5, 0, _O1_BYTE * N_TRIANGLE_TERMS(_O1)); + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_UpperTrianglize(Qs->l1_Q5, tempQ.l2_F1, _O1, _O1_BYTE); // UT( ... ) // Q5 + + /* + F1_T2 = F1 * t2 + F2_T3 = F2 * t3 + F1_F1T_T2 + F2_T3 = F1_T2 + F2_T3 + F1tr * t2 + Q_pk.l1_F3s[i] = F1_F1T_T2 + F2_T3 + Q_pk.l1_F6s[i] = T1tr* ( F1_F1T_T2 + F2_T3 ) + F2tr * t2 + Q_pk.l1_F9s[i] = UT( T2tr* ( F1_T2 + F2_T3 ) ) + */ + memset(Qs->l1_Q3, 0, _O1_BYTE * _V1 * _O2); + memset(Qs->l1_Q6, 0, _O1_BYTE * _O1 * _O2); + memset(Qs->l1_Q9, 0, _O1_BYTE * N_TRIANGLE_TERMS(_O2)); + + batch_trimat_madd(Qs->l1_Q3, Fs->l1_F1, t2, _V1, _V1_BYTE, _O2, _O1_BYTE); // F1*T2 + batch_mat_madd(Qs->l1_Q3, Fs->l1_F2, _V1, Ts->t3, _O1, _O1_BYTE, _O2, _O1_BYTE); // F1_T2 + F2_T3 + + memset(tempQ.l1_F2, 0, _O1_BYTE * _V1 * _O2); // should be F3. assuming: _O1 >= _O2 + batch_matTr_madd(tempQ.l1_F2, t2, _V1, _V1_BYTE, _O2, Qs->l1_Q3, _O2, _O1_BYTE); // T2tr * ( F1_T2 + F2_T3 ) + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_UpperTrianglize(Qs->l1_Q9, tempQ.l1_F2, _O2, _O1_BYTE); // Q9 + + batch_trimatTr_madd(Qs->l1_Q3, Fs->l1_F1, t2, _V1, _V1_BYTE, _O2, _O1_BYTE); // F1_F1T_T2 + F2_T3 // Q3 + + batch_bmatTr_madd(Qs->l1_Q6, Fs->l1_F2, _O1, t2, _V1, _V1_BYTE, _O2, _O1_BYTE); // F2tr*T2 + batch_matTr_madd(Qs->l1_Q6, Ts->t1, _V1, _V1_BYTE, _O1, Qs->l1_Q3, _O2, _O1_BYTE); // Q6 + /* + Layer 2 + Computing Q9: + + F1_T2 = F1 * t2 + F2_T3 = F2 * t3 + Q9 = UT( T2tr*( F1*T2 + F2*T3 + F3 ) + T3tr*( F5*T3 + F6 ) ) + */ + sk_t tempQ2; + memcpy(tempQ2.l2_F3, Fs->l2_F3, _O2_BYTE * _V1 * _O2); /// F3 actually. + batch_trimat_madd(tempQ2.l2_F3, Fs->l2_F1, t2, _V1, _V1_BYTE, _O2, _O2_BYTE); // F1*T2 + F3 + batch_mat_madd(tempQ2.l2_F3, Fs->l2_F2, _V1, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // F1_T2 + F2_T3 + F3 + + memset(tempQ.l2_F3, 0, _O2_BYTE * _V1 * _O2); + batch_matTr_madd(tempQ.l2_F3, t2, _V1, _V1_BYTE, _O2, tempQ2.l2_F3, _O2, _O2_BYTE); // T2tr * ( ..... ) + + memcpy(tempQ.l2_F6, Fs->l2_F6, _O2_BYTE * _O1 * _O2); + batch_trimat_madd(tempQ.l2_F6, Fs->l2_F5, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // F5*T3 + F6 + + batch_matTr_madd(tempQ.l2_F3, Ts->t3, _O1, _O1_BYTE, _O2, tempQ.l2_F6, _O2, _O2_BYTE); // T2tr*( ..... ) + T3tr*( ..... ) + memset(Qs->l2_Q9, 0, _O2_BYTE * N_TRIANGLE_TERMS(_O2)); + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_UpperTrianglize(Qs->l2_Q9, tempQ.l2_F3, _O2, _O2_BYTE); // Q9 +} + +// Choosing implementations depends on the macros: _BLAS_SSE_ and _BLAS_AVX2_ +#define calculate_F_from_Q_impl calculate_F_from_Q_ref +#define calculate_Q_from_F_cyclic_impl calculate_Q_from_F_cyclic_ref + +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_calculate_F_from_Q(sk_t *Fs, const sk_t *Qs, sk_t *Ts) { + calculate_F_from_Q_impl(Fs, Qs, Ts); +} + +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_calculate_Q_from_F_cyclic(cpk_t *Qs, const sk_t *Fs, const sk_t *Ts) { + calculate_Q_from_F_cyclic_impl(Qs, Fs, Ts); +} diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/rainbow_keypair_computation.h b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/rainbow_keypair_computation.h new file mode 100644 index 0000000000..ea3a279d8c --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/rainbow_keypair_computation.h @@ -0,0 +1,71 @@ +#ifndef _RAINBOW_KEYPAIR_COMP_H_ +#define _RAINBOW_KEYPAIR_COMP_H_ +/// @file rainbow_keypair_computation.h +/// @brief Functions for calculating pk/sk while generating keys. +/// +/// Defining an internal structure of public key. +/// Functions for calculating pk/sk for key generation. +/// + +#include "rainbow_keypair.h" + +/// @brief The (internal use) public key for rainbow +/// +/// The (internal use) public key for rainbow. The public +/// polynomials are divided into l1_Q1, l1_Q2, ... l1_Q9, +/// l2_Q1, .... , l2_Q9. +/// +typedef struct rainbow_extend_publickey { + unsigned char l1_Q1[_O1_BYTE * N_TRIANGLE_TERMS(_V1)]; + unsigned char l1_Q2[_O1_BYTE * _V1 * _O1]; + unsigned char l1_Q3[_O1_BYTE * _V1 * _O2]; + unsigned char l1_Q5[_O1_BYTE * N_TRIANGLE_TERMS(_O1)]; + unsigned char l1_Q6[_O1_BYTE * _O1 * _O2]; + unsigned char l1_Q9[_O1_BYTE * N_TRIANGLE_TERMS(_O2)]; + + unsigned char l2_Q1[_O2_BYTE * N_TRIANGLE_TERMS(_V1)]; + unsigned char l2_Q2[_O2_BYTE * _V1 * _O1]; + unsigned char l2_Q3[_O2_BYTE * _V1 * _O2]; + unsigned char l2_Q5[_O2_BYTE * N_TRIANGLE_TERMS(_O1)]; + unsigned char l2_Q6[_O2_BYTE * _O1 * _O2]; + unsigned char l2_Q9[_O2_BYTE * N_TRIANGLE_TERMS(_O2)]; +} ext_cpk_t; + +/// +/// @brief converting formats of public keys : from ext_cpk_t version to pk_t +/// +/// @param[out] pk - the classic public key. +/// @param[in] cpk - the internel public key. +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_extcpk_to_pk(pk_t *pk, const ext_cpk_t *cpk); +///////////////////////////////////////////////// + +/// +/// @brief Computing public key from secret key +/// +/// @param[out] Qs - the public key +/// @param[in] Fs - parts of the secret key: l1_F1, l1_F2, l2_F1, l2_F2, l2_F3, l2_F5, l2_F6 +/// @param[in] Ts - parts of the secret key: T1, T4, T3 +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_calculate_Q_from_F(ext_cpk_t *Qs, const sk_t *Fs, const sk_t *Ts); + + +/// +/// @brief Computing parts of the sk from parts of pk and sk +/// +/// @param[out] Fs - parts of the sk: l1_F1, l1_F2, l2_F1, l2_F2, l2_F3, l2_F5, l2_F6 +/// @param[in] Qs - parts of the pk: l1_Q1, l1_Q2, l2_Q1, l2_Q2, l2_Q3, l2_Q5, l2_Q6 +/// @param[in] Ts - parts of the sk: T1, T4, T3 +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_calculate_F_from_Q(sk_t *Fs, const sk_t *Qs, sk_t *Ts); + +/// +/// @brief Computing parts of the pk from the secret key +/// +/// @param[out] Qs - parts of the pk: l1_Q3, l1_Q5, l2_Q6, l1_Q9, l2_Q9 +/// @param[in] Fs - parts of the sk: l1_F1, l1_F2, l2_F1, l2_F2, l2_F3, l2_F5, l2_F6 +/// @param[in] Ts - parts of the sk: T1, T4, T3 +/// +void PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_calculate_Q_from_F_cyclic(cpk_t *Qs, const sk_t *Fs, const sk_t *Ts); + +#endif // _RAINBOW_KEYPAIR_COMP_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/sign.c b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/sign.c new file mode 100644 index 0000000000..832411873b --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/sign.c @@ -0,0 +1,76 @@ +/// @file sign.c +/// @brief the implementations for functions in api.h +/// +/// + +#include "api.h" +#include "rainbow.h" +#include "rainbow_config.h" +#include "rainbow_keypair.h" +#include "randombytes.h" +#include "utils_hash.h" +#include +#include + +int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { + unsigned char sk_seed[LEN_SKSEED] = {0}; + randombytes(sk_seed, LEN_SKSEED); + + unsigned char pk_seed[LEN_PKSEED] = {0}; + randombytes(pk_seed, LEN_PKSEED); + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_generate_compact_keypair_cyclic((cpk_t *)pk, (csk_t *)sk, pk_seed, sk_seed); + return 0; +} + +int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { + unsigned char digest[_HASH_LEN]; + + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_hash_msg(digest, _HASH_LEN, m, mlen); + + memcpy(sm, m, mlen); + smlen[0] = mlen + _SIGNATURE_BYTE; + + return PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_rainbow_sign_cyclic(sm + mlen, (const csk_t *)sk, digest); +} + +int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { + int rc; + if (_SIGNATURE_BYTE > smlen) { + rc = -1; + } else { + *mlen = smlen - _SIGNATURE_BYTE; + + unsigned char digest[_HASH_LEN]; + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_hash_msg(digest, _HASH_LEN, sm, *mlen); + + rc = PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_rainbow_verify_cyclic(digest, sm + mlen[0], (const cpk_t *)pk); + } + if (!rc) { + memmove(m, sm, smlen - _SIGNATURE_BYTE); + } else { // bad signature + *mlen = (size_t) -1; + memset(m, 0, smlen); + } + return rc; +} + +int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_crypto_sign_signature( + uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + unsigned char digest[_HASH_LEN]; + + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_hash_msg(digest, _HASH_LEN, m, mlen); + *siglen = _SIGNATURE_BYTE; + return PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_rainbow_sign_cyclic(sig, (const csk_t *)sk, digest); +} + +int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_crypto_sign_verify( + const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + if (siglen != _SIGNATURE_BYTE) { + return -1; + } + unsigned char digest[_HASH_LEN]; + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_hash_msg(digest, _HASH_LEN, m, mlen); + return PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_rainbow_verify_cyclic(digest, sig, (const cpk_t *)pk); +} diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/utils_hash.c b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/utils_hash.c new file mode 100644 index 0000000000..f3bffff165 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/utils_hash.c @@ -0,0 +1,50 @@ +/// @file utils_hash.c +/// @brief the adapter for SHA2 families. +/// +/// + +#include "utils_hash.h" +#include "rainbow_config.h" +#include "sha2.h" + +static inline int _hash(unsigned char *digest, const unsigned char *m, size_t mlen) { + sha512(digest, m, mlen); + return 0; +} + +static inline int expand_hash(unsigned char *digest, size_t n_digest, const unsigned char *hash) { + if (_HASH_LEN >= n_digest) { + for (size_t i = 0; i < n_digest; i++) { + digest[i] = hash[i]; + } + return 0; + } + for (size_t i = 0; i < _HASH_LEN; i++) { + digest[i] = hash[i]; + } + n_digest -= _HASH_LEN; + + while (_HASH_LEN <= n_digest) { + _hash(digest + _HASH_LEN, digest, _HASH_LEN); + + n_digest -= _HASH_LEN; + digest += _HASH_LEN; + } + unsigned char temp[_HASH_LEN]; + if (n_digest) { + _hash(temp, digest, _HASH_LEN); + for (size_t i = 0; i < n_digest; i++) { + digest[_HASH_LEN + i] = temp[i]; + } + } + return 0; +} + +int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_hash_msg(unsigned char *digest, + size_t len_digest, + const unsigned char *m, + size_t mlen) { + unsigned char buf[_HASH_LEN]; + _hash(buf, m, mlen); + return expand_hash(digest, len_digest, buf); +} diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/utils_hash.h b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/utils_hash.h new file mode 100644 index 0000000000..651fd6866e --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/utils_hash.h @@ -0,0 +1,11 @@ +#ifndef _UTILS_HASH_H_ +#define _UTILS_HASH_H_ +/// @file utils_hash.h +/// @brief the interface for adapting hash functions. +/// + +#include + +int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_hash_msg(unsigned char *digest, size_t len_digest, const unsigned char *m, size_t mlen); + +#endif // _UTILS_HASH_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/utils_prng.c b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/utils_prng.c new file mode 100644 index 0000000000..b8fb2638ff --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/utils_prng.c @@ -0,0 +1,97 @@ +/// @file utils_prng.c +/// @brief The implementation of PRNG related functions. +/// + +#include "utils_prng.h" +#include "aes.h" +#include "randombytes.h" +#include "utils_hash.h" +#include +#include + +static void prng_update(const unsigned char *provided_data, + unsigned char *Key, + unsigned char *V) { + unsigned char temp[48]; + aes256ctx ctx; + aes256_keyexp(&ctx, Key); + for (int i = 0; i < 3; i++) { + //increment V + for (int j = 15; j >= 0; j--) { + if (V[j] == 0xff) { + V[j] = 0x00; + } else { + V[j]++; + break; + } + } + aes256_ecb(temp + 16 * i, V, 1, &ctx); + } + if (provided_data != NULL) { + for (int i = 0; i < 48; i++) { + temp[i] ^= provided_data[i]; + } + } + aes256_ctx_release(&ctx); + memcpy(Key, temp, 32); + memcpy(V, temp + 32, 16); +} +static void randombytes_init_with_state(prng_t *state, + unsigned char *entropy_input_48bytes) { + memset(state->Key, 0x00, 32); + memset(state->V, 0x00, 16); + prng_update(entropy_input_48bytes, state->Key, state->V); +} + +static int randombytes_with_state(prng_t *state, + unsigned char *x, + size_t xlen) { + + unsigned char block[16]; + int i = 0; + + aes256ctx ctx; + aes256_keyexp(&ctx, state->Key); + + while (xlen > 0) { + //increment V + for (int j = 15; j >= 0; j--) { + if (state->V[j] == 0xff) { + state->V[j] = 0x00; + } else { + state->V[j]++; + break; + } + } + aes256_ecb(block, state->V, 1, &ctx); + if (xlen > 15) { + memcpy(x + i, block, 16); + i += 16; + xlen -= 16; + } else { + memcpy(x + i, block, xlen); + xlen = 0; + } + } + aes256_ctx_release(&ctx); + prng_update(NULL, state->Key, state->V); + return 0; +} + +int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_prng_set(prng_t *ctx, const void *prng_seed, unsigned long prng_seedlen) { + unsigned char seed[48]; + if (prng_seedlen >= 48) { + memcpy(seed, prng_seed, 48); + } else { + memcpy(seed, prng_seed, prng_seedlen); + PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_hash_msg(seed + prng_seedlen, 48 - (unsigned)prng_seedlen, (const unsigned char *)prng_seed, prng_seedlen); + } + + randombytes_init_with_state(ctx, seed); + + return 0; +} + +int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_prng_gen(prng_t *ctx, unsigned char *out, unsigned long outlen) { + return randombytes_with_state(ctx, out, outlen); +} diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/utils_prng.h b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/utils_prng.h new file mode 100644 index 0000000000..a4e331ee15 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic-compressed_clean/utils_prng.h @@ -0,0 +1,18 @@ +#ifndef _UTILS_PRNG_H_ +#define _UTILS_PRNG_H_ +/// @file utils_prng.h +/// @brief the interface for adapting PRNG functions. +/// +/// + +#include "randombytes.h" + +typedef struct { + unsigned char Key[32]; + unsigned char V[16]; +} prng_t; + +int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_prng_set(prng_t *ctx, const void *prng_seed, unsigned long prng_seedlen); +int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_prng_gen(prng_t *ctx, unsigned char *out, unsigned long outlen); + +#endif // _UTILS_PRNG_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/LICENSE b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/LICENSE new file mode 100644 index 0000000000..cb00a6e354 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/LICENSE @@ -0,0 +1,8 @@ +`Software implementation of Rainbow for NIST R2 submission' by Ming-Shing Chen + +To the extent possible under law, the person who associated CC0 with +`Software implementation of Rainbow for NIST R2 submission' has waived all copyright and related or neighboring rights +to `Software implementation of Rainbow for NIST R2 submission'. + +You should have received a copy of the CC0 legalcode along with this +work. If not, see . diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/api.h b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/api.h new file mode 100644 index 0000000000..e7106779be --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/api.h @@ -0,0 +1,32 @@ +#ifndef PQCLEAN_RAINBOWVCCYCLIC_CLEAN_API_H +#define PQCLEAN_RAINBOWVCCYCLIC_CLEAN_API_H + +#include +#include + +#define PQCLEAN_RAINBOWVCCYCLIC_CLEAN_CRYPTO_SECRETKEYBYTES 1227104 +#define PQCLEAN_RAINBOWVCCYCLIC_CLEAN_CRYPTO_PUBLICKEYBYTES 491936 +#define PQCLEAN_RAINBOWVCCYCLIC_CLEAN_CRYPTO_BYTES 204 +#define PQCLEAN_RAINBOWVCCYCLIC_CLEAN_CRYPTO_ALGNAME "RAINBOW(256,92,48,48) - cyclic" + +int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); + + +int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_crypto_sign_signature( + uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk); + +int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_crypto_sign_verify( + const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk); + +int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_crypto_sign(uint8_t *sm, size_t *smlen, + const uint8_t *m, size_t mlen, + const uint8_t *sk); + +int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_crypto_sign_open(uint8_t *m, size_t *mlen, + const uint8_t *sm, size_t smlen, + const uint8_t *pk); + + +#endif diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/blas.c b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/blas.c new file mode 100644 index 0000000000..6f617dd977 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/blas.c @@ -0,0 +1,31 @@ +#include "blas.h" +#include "gf.h" + +#include + +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_predicated_add(uint8_t *accu_b, uint8_t predicate, const uint8_t *a, size_t _num_byte) { + uint8_t pr_u8 = (uint8_t) ((uint8_t) 0 - predicate); + for (size_t i = 0; i < _num_byte; i++) { + accu_b[i] ^= (a[i] & pr_u8); + } +} + +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_add(uint8_t *accu_b, const uint8_t *a, size_t _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + accu_b[i] ^= a[i]; + } +} + + +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_mul_scalar(uint8_t *a, uint8_t b, size_t _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + a[i] = PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256_mul(a[i], b); + } +} + +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_madd(uint8_t *accu_c, const uint8_t *a, uint8_t gf256_b, size_t _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + accu_c[i] ^= PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256_mul(a[i], gf256_b); + } +} + diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/blas.h b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/blas.h new file mode 100644 index 0000000000..c19fe23bc8 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/blas.h @@ -0,0 +1,19 @@ +#ifndef _BLAS_H_ +#define _BLAS_H_ +/// @file blas.h +/// @brief Functions for implementing basic linear algebra functions. +/// + +#include "rainbow_config.h" +#include +#include + +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_predicated_add(uint8_t *accu_b, uint8_t predicate, const uint8_t *a, size_t _num_byte); +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_add(uint8_t *accu_b, const uint8_t *a, size_t _num_byte); + + +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_mul_scalar(uint8_t *a, uint8_t b, size_t _num_byte); +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_madd(uint8_t *accu_c, const uint8_t *a, uint8_t gf256_b, size_t _num_byte); + + +#endif // _BLAS_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/blas_comm.c b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/blas_comm.c new file mode 100644 index 0000000000..1dd6e4eab4 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/blas_comm.c @@ -0,0 +1,144 @@ +/// @file blas_comm.c +/// @brief The standard implementations for blas_comm.h +/// + +#include "blas_comm.h" +#include "blas.h" +#include "gf.h" +#include "rainbow_config.h" + +#include +#include + +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_set_zero(uint8_t *b, unsigned int _num_byte) { + for (size_t i = 0; i < _num_byte; i++) { + b[i] = 0; + } +} +/// @brief get an element from GF(256) vector . +/// +/// @param[in] a - the input vector a. +/// @param[in] i - the index in the vector a. +/// @return the value of the element. +/// +uint8_t PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_get_ele(const uint8_t *a, unsigned int i) { + return a[i]; +} + +unsigned int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_is_zero(const uint8_t *a, unsigned int _num_byte) { + uint8_t r = 0; + while (_num_byte--) { + r |= a[0]; + a++; + } + return (0 == r); +} + +/// polynomial multplication +/// School boook +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_polymul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int _num) { + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_set_zero(c, _num * 2 - 1); + for (unsigned int i = 0; i < _num; i++) { + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_madd(c + i, a, b[i], _num); + } +} + +static void gf256mat_prod_ref(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b) { + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_set_zero(c, n_A_vec_byte); + for (unsigned int i = 0; i < n_A_width; i++) { + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_madd(c, matA, b[i], n_A_vec_byte); + matA += n_A_vec_byte; + } +} + +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256mat_mul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int len_vec) { + unsigned int n_vec_byte = len_vec; + for (unsigned int k = 0; k < len_vec; k++) { + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_set_zero(c, n_vec_byte); + const uint8_t *bk = b + n_vec_byte * k; + for (unsigned int i = 0; i < len_vec; i++) { + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_madd(c, a + n_vec_byte * i, bk[i], n_vec_byte); + } + c += n_vec_byte; + } +} + +static unsigned int gf256mat_gauss_elim_ref(uint8_t *mat, unsigned int h, unsigned int w) { + unsigned int r8 = 1; + + for (unsigned int i = 0; i < h; i++) { + uint8_t *ai = mat + w * i; + unsigned int skip_len_align4 = i & ((unsigned int)~0x3); + + for (unsigned int j = i + 1; j < h; j++) { + uint8_t *aj = mat + w * j; + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_predicated_add(ai + skip_len_align4, !PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256_is_nonzero(ai[i]), aj + skip_len_align4, w - skip_len_align4); + } + r8 &= PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256_is_nonzero(ai[i]); + uint8_t pivot = ai[i]; + pivot = PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256_inv(pivot); + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_mul_scalar(ai + skip_len_align4, pivot, w - skip_len_align4); + for (unsigned int j = 0; j < h; j++) { + if (i == j) { + continue; + } + uint8_t *aj = mat + w * j; + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_madd(aj + skip_len_align4, ai + skip_len_align4, aj[i], w - skip_len_align4); + } + } + + return r8; +} + +static unsigned int gf256mat_solve_linear_eq_ref(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n) { + uint8_t mat[64 * 64]; + for (unsigned int i = 0; i < n; i++) { + memcpy(mat + i * (n + 1), inp_mat + i * n, n); + mat[i * (n + 1) + n] = c_terms[i]; + } + unsigned int r8 = PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256mat_gauss_elim(mat, n, n + 1); + for (unsigned int i = 0; i < n; i++) { + sol[i] = mat[i * (n + 1) + n]; + } + return r8; +} + +static inline void gf256mat_submat(uint8_t *mat2, unsigned int w2, unsigned int st, const uint8_t *mat, unsigned int w, unsigned int h) { + for (unsigned int i = 0; i < h; i++) { + for (unsigned int j = 0; j < w2; j++) { + mat2[i * w2 + j] = mat[i * w + st + j]; + } + } +} + +unsigned int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256mat_inv(uint8_t *inv_a, const uint8_t *a, unsigned int H, uint8_t *buffer) { + uint8_t *aa = buffer; + for (unsigned int i = 0; i < H; i++) { + uint8_t *ai = aa + i * 2 * H; + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_set_zero(ai, 2 * H); + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_add(ai, a + i * H, H); + ai[H + i] = 1; + } + unsigned int r8 = PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256mat_gauss_elim(aa, H, 2 * H); + gf256mat_submat(inv_a, H, H, aa, 2 * H, H); + return r8; +} + + +// choosing the implementations depends on the macros _BLAS_AVX2_ and _BLAS_SSE + +#define gf256mat_prod_impl gf256mat_prod_ref +#define gf256mat_gauss_elim_impl gf256mat_gauss_elim_ref +#define gf256mat_solve_linear_eq_impl gf256mat_solve_linear_eq_ref +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256mat_prod(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b) { + gf256mat_prod_impl(c, matA, n_A_vec_byte, n_A_width, b); +} + +unsigned int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256mat_gauss_elim(uint8_t *mat, unsigned int h, unsigned int w) { + return gf256mat_gauss_elim_impl(mat, h, w); +} + +unsigned int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256mat_solve_linear_eq(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n) { + return gf256mat_solve_linear_eq_impl(sol, inp_mat, c_terms, n); +} + diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/blas_comm.h b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/blas_comm.h new file mode 100644 index 0000000000..08ae23c083 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/blas_comm.h @@ -0,0 +1,90 @@ +#ifndef _BLAS_COMM_H_ +#define _BLAS_COMM_H_ +/// @file blas_comm.h +/// @brief Common functions for linear algebra. +/// + +#include "rainbow_config.h" +#include + +/// @brief set a vector to 0. +/// +/// @param[in,out] b - the vector b. +/// @param[in] _num_byte - number of bytes for the vector b. +/// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_set_zero(uint8_t *b, unsigned int _num_byte); + +/// @brief get an element from GF(256) vector . +/// +/// @param[in] a - the input vector a. +/// @param[in] i - the index in the vector a. +/// @return the value of the element. +/// +uint8_t PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_get_ele(const uint8_t *a, unsigned int i); + +/// @brief check if a vector is 0. +/// +/// @param[in] a - the vector a. +/// @param[in] _num_byte - number of bytes for the vector a. +/// @return 1(true) if a is 0. 0(false) else. +/// +unsigned int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_is_zero(const uint8_t *a, unsigned int _num_byte); + +/// @brief polynomial multiplication: c = a*b +/// +/// @param[out] c - the output polynomial c +/// @param[in] a - the vector a. +/// @param[in] b - the vector b. +/// @param[in] _num - number of elements for the polynomials a and b. +/// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_polymul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int _num); + +/// @brief matrix-vector multiplication: c = matA * b , in GF(256) +/// +/// @param[out] c - the output vector c +/// @param[in] matA - a column-major matrix A. +/// @param[in] n_A_vec_byte - the size of column vectors in bytes. +/// @param[in] n_A_width - the width of matrix A. +/// @param[in] b - the vector b. +/// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256mat_prod(uint8_t *c, const uint8_t *matA, unsigned int n_A_vec_byte, unsigned int n_A_width, const uint8_t *b); + +/// @brief matrix-matrix multiplication: c = a * b , in GF(256) +/// +/// @param[out] c - the output matrix c +/// @param[in] c - a matrix a. +/// @param[in] b - a matrix b. +/// @param[in] len_vec - the length of column vectors. +/// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256mat_mul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned int len_vec); + +/// @brief Gauss elimination for a matrix, in GF(256) +/// +/// @param[in,out] mat - the matrix. +/// @param[in] h - the height of the matrix. +/// @param[in] w - the width of the matrix. +/// @return 1(true) if success. 0(false) if the matrix is singular. +/// +unsigned int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256mat_gauss_elim(uint8_t *mat, unsigned int h, unsigned int w); + +/// @brief Solving linear equations, in GF(256) +/// +/// @param[out] sol - the solutions. +/// @param[in] inp_mat - the matrix parts of input equations. +/// @param[in] c_terms - the constant terms of the input equations. +/// @param[in] n - the number of equations. +/// @return 1(true) if success. 0(false) if the matrix is singular. +/// +unsigned int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256mat_solve_linear_eq(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned int n); + +/// @brief Computing the inverse matrix, in GF(256) +/// +/// @param[out] inv_a - the output of matrix a. +/// @param[in] a - a matrix a. +/// @param[in] H - height of matrix a, i.e., matrix a is an HxH matrix. +/// @param[in] buffer - The buffer for computations. it has to be as large as 2 input matrixes. +/// @return 1(true) if success. 0(false) if the matrix is singular. +/// +unsigned int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256mat_inv(uint8_t *inv_a, const uint8_t *a, unsigned int H, uint8_t *buffer); + +#endif // _BLAS_COMM_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/gf.c b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/gf.c new file mode 100644 index 0000000000..f2b0b8590c --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/gf.c @@ -0,0 +1,91 @@ +#include "gf.h" + +//// gf4 := gf2[x]/x^2+x+1 +static inline uint8_t gf4_mul_2(uint8_t a) { + uint8_t r = (uint8_t)(a << 1); + r ^= (uint8_t)((a >> 1) * 7); + return r; +} + +static inline uint8_t gf4_mul(uint8_t a, uint8_t b) { + uint8_t r = (uint8_t)(a * (b & 1)); + return r ^ (uint8_t)(gf4_mul_2(a) * (b >> 1)); +} + +static inline uint8_t gf4_squ(uint8_t a) { + return a ^ (a >> 1); +} + +//// gf16 := gf4[y]/y^2+y+x +uint8_t PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf16_mul(uint8_t a, uint8_t b) { + uint8_t a0 = a & 3; + uint8_t a1 = (a >> 2); + uint8_t b0 = b & 3; + uint8_t b1 = (b >> 2); + uint8_t a0b0 = gf4_mul(a0, b0); + uint8_t a1b1 = gf4_mul(a1, b1); + uint8_t a0b1_a1b0 = gf4_mul(a0 ^ a1, b0 ^ b1) ^ a0b0 ^ a1b1; + uint8_t a1b1_x2 = gf4_mul_2(a1b1); + return (uint8_t)((a0b1_a1b0 ^ a1b1) << 2 ^ a0b0 ^ a1b1_x2); +} + +static inline uint8_t gf16_squ(uint8_t a) { + uint8_t a0 = a & 3; + uint8_t a1 = (a >> 2); + a1 = gf4_squ(a1); + uint8_t a1squ_x2 = gf4_mul_2(a1); + return (uint8_t)((a1 << 2) ^ a1squ_x2 ^ gf4_squ(a0)); +} + +uint8_t PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256_is_nonzero(uint8_t a) { + unsigned int a8 = a; + unsigned int r = ((unsigned int)0) - a8; + r >>= 8; + return r & 1; +} + +static inline uint8_t gf4_mul_3(uint8_t a) { + uint8_t msk = (uint8_t)((a - 2) >> 1); + return (uint8_t)((msk & ((int)a * 3)) | ((~msk) & ((int)a - 1))); +} +static inline uint8_t gf16_mul_8(uint8_t a) { + uint8_t a0 = a & 3; + uint8_t a1 = a >> 2; + return (uint8_t)((gf4_mul_2(a0 ^ a1) << 2) | gf4_mul_3(a1)); +} + +// gf256 := gf16[X]/X^2+X+xy +uint8_t PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256_mul(uint8_t a, uint8_t b) { + uint8_t a0 = a & 15; + uint8_t a1 = (a >> 4); + uint8_t b0 = b & 15; + uint8_t b1 = (b >> 4); + uint8_t a0b0 = PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf16_mul(a0, b0); + uint8_t a1b1 = PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf16_mul(a1, b1); + uint8_t a0b1_a1b0 = PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf16_mul(a0 ^ a1, b0 ^ b1) ^ a0b0 ^ a1b1; + uint8_t a1b1_x8 = gf16_mul_8(a1b1); + return (uint8_t)((a0b1_a1b0 ^ a1b1) << 4 ^ a0b0 ^ a1b1_x8); +} + +static inline uint8_t gf256_squ(uint8_t a) { + uint8_t a0 = a & 15; + uint8_t a1 = (a >> 4); + a1 = gf16_squ(a1); + uint8_t a1squ_x8 = gf16_mul_8(a1); + return (uint8_t)((a1 << 4) ^ a1squ_x8 ^ gf16_squ(a0)); +} + +uint8_t PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256_inv(uint8_t a) { + // 128+64+32+16+8+4+2 = 254 + uint8_t a2 = gf256_squ(a); + uint8_t a4 = gf256_squ(a2); + uint8_t a8 = gf256_squ(a4); + uint8_t a4_2 = PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256_mul(a4, a2); + uint8_t a8_4_2 = PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256_mul(a4_2, a8); + uint8_t a64_ = gf256_squ(a8_4_2); + a64_ = gf256_squ(a64_); + a64_ = gf256_squ(a64_); + uint8_t a64_2 = PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256_mul(a64_, a8_4_2); + uint8_t a128_ = gf256_squ(a64_2); + return PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256_mul(a2, a128_); +} diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/gf.h b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/gf.h new file mode 100644 index 0000000000..1bde8af639 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/gf.h @@ -0,0 +1,19 @@ +#ifndef _GF16_H_ +#define _GF16_H_ + +#include "rainbow_config.h" +#include + +/// @file gf16.h +/// @brief Library for arithmetics in GF(16) and GF(256) +/// + +uint8_t PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf16_mul(uint8_t a, uint8_t b); + + +uint8_t PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256_is_nonzero(uint8_t a); +uint8_t PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256_inv(uint8_t a); +uint8_t PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256_mul(uint8_t a, uint8_t b); + + +#endif // _GF16_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/parallel_matrix_op.c b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/parallel_matrix_op.c new file mode 100644 index 0000000000..04b1beb612 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/parallel_matrix_op.c @@ -0,0 +1,183 @@ +/// @file parallel_matrix_op.c +/// @brief the standard implementations for functions in parallel_matrix_op.h +/// +/// the standard implementations for functions in parallel_matrix_op.h +/// + +#include "parallel_matrix_op.h" +#include "blas.h" +#include "blas_comm.h" + +/// +/// @brief Calculate the corresponding index in an array for an upper-triangle(UT) matrix. +/// +/// @param[in] i_row - the i-th row in an upper-triangle matrix. +/// @param[in] j_col - the j-th column in an upper-triangle matrix. +/// @param[in] dim - the dimension of the upper-triangle matrix, i.e., an dim x dim matrix. +/// @return the corresponding index in an array storage. +/// +unsigned int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_idx_of_trimat(unsigned int i_row, unsigned int j_col, unsigned int dim) { + return (dim + dim - i_row + 1) * i_row / 2 + j_col - i_row; +} + +/// +/// @brief Calculate the corresponding index in an array for an upper-triangle or lower-triangle matrix. +/// +/// @param[in] i_row - the i-th row in a triangle matrix. +/// @param[in] j_col - the j-th column in a triangle matrix. +/// @param[in] dim - the dimension of the triangle matrix, i.e., an dim x dim matrix. +/// @return the corresponding index in an array storage. +/// +static inline unsigned int idx_of_2trimat(unsigned int i_row, unsigned int j_col, unsigned int n_var) { + if (i_row > j_col) { + return PQCLEAN_RAINBOWVCCYCLIC_CLEAN_idx_of_trimat(j_col, i_row, n_var); + } + return PQCLEAN_RAINBOWVCCYCLIC_CLEAN_idx_of_trimat(i_row, j_col, n_var); +} + +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_UpperTrianglize(unsigned char *btriC, const unsigned char *bA, unsigned int Awidth, unsigned int size_batch) { + unsigned char *runningC = btriC; + unsigned int Aheight = Awidth; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < i; j++) { + unsigned int idx = PQCLEAN_RAINBOWVCCYCLIC_CLEAN_idx_of_trimat(j, i, Aheight); + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_add(btriC + idx * size_batch, bA + size_batch * (i * Awidth + j), size_batch); + } + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_add(runningC, bA + size_batch * (i * Awidth + i), size_batch * (Aheight - i)); + runningC += size_batch * (Aheight - i); + } +} + +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Awidth = Bheight; + unsigned int Aheight = Awidth; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + if (k < i) { + continue; + } + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_madd(bC, &btriA[(k - i) * size_batch], PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + btriA += (Aheight - i) * size_batch; + } +} + +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_trimatTr_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Aheight = Bheight; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + if (i < k) { + continue; + } + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_madd(bC, &btriA[size_batch * (PQCLEAN_RAINBOWVCCYCLIC_CLEAN_idx_of_trimat(k, i, Aheight))], PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_2trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Aheight = Bheight; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + if (i == k) { + continue; + } + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_madd(bC, &btriA[size_batch * (idx_of_2trimat(i, k, Aheight))], PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_matTr_madd_gf256(unsigned char *bC, const unsigned char *A_to_tr, unsigned int Aheight, unsigned int size_Acolvec, unsigned int Awidth, + const unsigned char *bB, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Atr_height = Awidth; + unsigned int Atr_width = Aheight; + for (unsigned int i = 0; i < Atr_height; i++) { + for (unsigned int j = 0; j < Atr_width; j++) { + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_madd(bC, &bB[j * Bwidth * size_batch], PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_get_ele(&A_to_tr[size_Acolvec * i], j), size_batch * Bwidth); + } + bC += size_batch * Bwidth; + } +} + +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_bmatTr_madd_gf256(unsigned char *bC, const unsigned char *bA_to_tr, unsigned int Awidth_before_tr, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + const unsigned char *bA = bA_to_tr; + unsigned int Aheight = Awidth_before_tr; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_madd(bC, &bA[size_batch * (i + k * Aheight)], PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_mat_madd_gf256(unsigned char *bC, const unsigned char *bA, unsigned int Aheight, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch) { + unsigned int Awidth = Bheight; + for (unsigned int i = 0; i < Aheight; i++) { + for (unsigned int j = 0; j < Bwidth; j++) { + for (unsigned int k = 0; k < Bheight; k++) { + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_madd(bC, &bA[k * size_batch], PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_get_ele(&B[j * size_Bcolvec], k), size_batch); + } + bC += size_batch; + } + bA += (Awidth) * size_batch; + } +} + +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_quad_trimat_eval_gf256(unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned int dim, unsigned int size_batch) { + unsigned char tmp[256]; + + unsigned char _x[256]; + for (unsigned int i = 0; i < dim; i++) { + _x[i] = PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_get_ele(x, i); + } + + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_set_zero(y, size_batch); + for (unsigned int i = 0; i < dim; i++) { + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_set_zero(tmp, size_batch); + for (unsigned int j = i; j < dim; j++) { + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_madd(tmp, trimat, _x[j], size_batch); + trimat += size_batch; + } + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_madd(y, tmp, _x[i], size_batch); + } +} + +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_quad_recmat_eval_gf256(unsigned char *z, const unsigned char *y, unsigned int dim_y, const unsigned char *mat, + const unsigned char *x, unsigned dim_x, unsigned size_batch) { + unsigned char tmp[128]; + + unsigned char _x[128]; + for (unsigned int i = 0; i < dim_x; i++) { + _x[i] = PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_get_ele(x, i); + } + unsigned char _y[128]; + for (unsigned int i = 0; i < dim_y; i++) { + _y[i] = PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_get_ele(y, i); + } + + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_set_zero(z, size_batch); + for (unsigned int i = 0; i < dim_y; i++) { + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_set_zero(tmp, size_batch); + for (unsigned int j = 0; j < dim_x; j++) { + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_madd(tmp, mat, _x[j], size_batch); + mat += size_batch; + } + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_madd(z, tmp, _y[i], size_batch); + } +} + diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/parallel_matrix_op.h b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/parallel_matrix_op.h new file mode 100644 index 0000000000..2a3308de10 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/parallel_matrix_op.h @@ -0,0 +1,260 @@ +#ifndef _P_MATRIX_OP_H_ +#define _P_MATRIX_OP_H_ +/// @file parallel_matrix_op.h +/// @brief Librarys for operations of batched matrixes. +/// +/// + +//////////////// Section: triangle matrix <-> rectangle matrix /////////////////////////////////// + +/// +/// @brief Calculate the corresponding index in an array for an upper-triangle(UT) matrix. +/// +/// @param[in] i_row - the i-th row in an upper-triangle matrix. +/// @param[in] j_col - the j-th column in an upper-triangle matrix. +/// @param[in] dim - the dimension of the upper-triangle matrix, i.e., an dim x dim matrix. +/// @return the corresponding index in an array storage. +/// +unsigned int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_idx_of_trimat(unsigned int i_row, unsigned int j_col, unsigned int dim); + +/// +/// @brief Upper trianglize a rectangle matrix to the corresponding upper-trangle matrix. +/// +/// @param[out] btriC - the batched upper-trianglized matrix C. +/// @param[in] bA - a batched retangle matrix A. +/// @param[in] bwidth - the width of the batched matrix A, i.e., A is a Awidth x Awidth matrix. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_UpperTrianglize(unsigned char *btriC, const unsigned char *bA, unsigned int Awidth, unsigned int size_batch); + +//////////////////// Section: matrix multiplications /////////////////////////////// + +/// +/// @brief bC += btriA * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_trimat_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += btriA * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += btriA^Tr * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. A will be transposed while multiplying. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_trimatTr_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += btriA^Tr * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A, which will be transposed while multiplying. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_trimatTr_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += (btriA + btriA^Tr) *B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. The operand for multiplication is (btriA + btriA^Tr). +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_2trimat_madd_gf16(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += (btriA + btriA^Tr) *B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] btriA - a batched UT matrix A. The operand for multiplication is (btriA + btriA^Tr). +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_2trimat_madd_gf256(unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += A^Tr * bB , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] A_to_tr - a column-major matrix A. The operand for multiplication is A^Tr. +/// @param[in] Aheight - the height of A. +/// @param[in] size_Acolvec - the size of a column vector in A. +/// @param[in] Awidth - the width of A. +/// @param[in] bB - a batched matrix B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_matTr_madd_gf16(unsigned char *bC, + const unsigned char *A_to_tr, unsigned int Aheight, unsigned int size_Acolvec, unsigned int Awidth, + const unsigned char *bB, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += A^Tr * bB , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] A_to_tr - a column-major matrix A. The operand for multiplication is A^Tr. +/// @param[in] Aheight - the height of A. +/// @param[in] size_Acolvec - the size of a column vector in A. +/// @param[in] Awidth - the width of A. +/// @param[in] bB - a batched matrix B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_matTr_madd_gf256(unsigned char *bC, + const unsigned char *A_to_tr, unsigned int Aheight, unsigned int size_Acolvec, unsigned int Awidth, + const unsigned char *bB, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA^Tr * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA_to_tr - a batched matrix A. The operand for multiplication is (bA^Tr). +/// @param[in] Awidth_befor_tr - the width of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_bmatTr_madd_gf16(unsigned char *bC, const unsigned char *bA_to_tr, unsigned int Awidth_before_tr, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA^Tr * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA_to_tr - a batched matrix A. The operand for multiplication is (bA^Tr). +/// @param[in] Awidth_befor_tr - the width of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_bmatTr_madd_gf256(unsigned char *bC, const unsigned char *bA_to_tr, unsigned int Awidth_before_tr, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA * B , in GF(16) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA - a batched matrix A. +/// @param[in] Aheigh - the height of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_mat_madd_gf16(unsigned char *bC, const unsigned char *bA, unsigned int Aheight, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +/// +/// @brief bC += bA * B , in GF(256) +/// +/// @param[out] bC - the batched matrix C. +/// @param[in] bA - a batched matrix A. +/// @param[in] Aheigh - the height of A. +/// @param[in] B - a column-major matrix B. +/// @param[in] Bheight - the height of B. +/// @param[in] size_Bcolvec - the size of the column vector in B. +/// @param[in] Bwidth - the width of B. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_mat_madd_gf256(unsigned char *bC, const unsigned char *bA, unsigned int Aheight, + const unsigned char *B, unsigned int Bheight, unsigned int size_Bcolvec, unsigned int Bwidth, unsigned int size_batch); + +//////////////////// Section: "quadratric" matrix evaluation /////////////////////////////// + +/// +/// @brief y = x^Tr * trimat * x , in GF(16) +/// +/// @param[out] y - the returned batched element y. +/// @param[in] trimat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim - the dimension of matrix trimat (and x). +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_quad_trimat_eval_gf16(unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned int dim, unsigned int size_batch); + +/// +/// @brief y = x^Tr * trimat * x , in GF(256) +/// +/// @param[out] y - the returned batched element y. +/// @param[in] trimat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim - the dimension of matrix trimat (and x). +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_quad_trimat_eval_gf256(unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned int dim, unsigned int size_batch); + +/// +/// @brief z = y^Tr * mat * x , in GF(16) +/// +/// @param[out] z - the returned batched element z. +/// @param[in] y - an input vector y. +/// @param[in] dim_y - the length of y. +/// @param[in] mat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim_x - the length of x. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_quad_recmat_eval_gf16(unsigned char *z, const unsigned char *y, unsigned int dim_y, + const unsigned char *mat, const unsigned char *x, unsigned int dim_x, unsigned int size_batch); + +/// +/// @brief z = y^Tr * mat * x , in GF(256) +/// +/// @param[out] z - the returned batched element z. +/// @param[in] y - an input vector y. +/// @param[in] dim_y - the length of y. +/// @param[in] mat - a batched matrix. +/// @param[in] x - an input vector x. +/// @param[in] dim_x - the length of x. +/// @param[in] size_batch - number of the batched elements in the corresponding position of the matrix. +/// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_quad_recmat_eval_gf256(unsigned char *z, const unsigned char *y, unsigned int dim_y, + const unsigned char *mat, const unsigned char *x, unsigned int dim_x, unsigned int size_batch); + +#endif // _P_MATRIX_OP_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/rainbow.c b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/rainbow.c new file mode 100644 index 0000000000..6d8631ad2c --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/rainbow.c @@ -0,0 +1,173 @@ +/// @file rainbow.c +/// @brief The standard implementations for functions in rainbow.h +/// + +#include "blas.h" +#include "parallel_matrix_op.h" +#include "rainbow.h" +#include "rainbow_blas.h" +#include "rainbow_config.h" +#include "rainbow_keypair.h" +#include "utils_hash.h" +#include "utils_prng.h" +#include +#include +#include + +#define MAX_ATTEMPT_FRMAT 128 + +int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_rainbow_sign(uint8_t *signature, const sk_t *sk, const uint8_t *_digest) { + uint8_t mat_l1[_O1 * _O1_BYTE]; + uint8_t mat_l2[_O2 * _O2_BYTE]; + uint8_t mat_buffer[2 * _MAX_O * _MAX_O_BYTE]; + + // setup PRNG + prng_t prng_sign; + uint8_t prng_preseed[LEN_SKSEED + _HASH_LEN]; + memcpy(prng_preseed, sk->sk_seed, LEN_SKSEED); + memcpy(prng_preseed + LEN_SKSEED, _digest, _HASH_LEN); // prng_preseed = sk_seed || digest + uint8_t prng_seed[_HASH_LEN]; + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_hash_msg(prng_seed, _HASH_LEN, prng_preseed, _HASH_LEN + LEN_SKSEED); + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_prng_set(&prng_sign, prng_seed, _HASH_LEN); // seed = H( sk_seed || digest ) + for (unsigned int i = 0; i < LEN_SKSEED + _HASH_LEN; i++) { + prng_preseed[i] ^= prng_preseed[i]; // clean + } + for (unsigned int i = 0; i < _HASH_LEN; i++) { + prng_seed[i] ^= prng_seed[i]; // clean + } + + // roll vinegars. + uint8_t vinegar[_V1_BYTE]; + unsigned int n_attempt = 0; + unsigned int l1_succ = 0; + while (!l1_succ) { + if (MAX_ATTEMPT_FRMAT <= n_attempt) { + break; + } + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_prng_gen(&prng_sign, vinegar, _V1_BYTE); // generating vinegars + gfmat_prod(mat_l1, sk->l1_F2, _O1 * _O1_BYTE, _V1, vinegar); // generating the linear equations for layer 1 + l1_succ = gfmat_inv(mat_l1, mat_l1, _O1, mat_buffer); // check if the linear equation solvable + n_attempt++; + } + + // Given the vinegars, pre-compute variables needed for layer 2 + uint8_t r_l1_F1[_O1_BYTE] = {0}; + uint8_t r_l2_F1[_O2_BYTE] = {0}; + batch_quad_trimat_eval(r_l1_F1, sk->l1_F1, vinegar, _V1, _O1_BYTE); + batch_quad_trimat_eval(r_l2_F1, sk->l2_F1, vinegar, _V1, _O2_BYTE); + uint8_t mat_l2_F3[_O2 * _O2_BYTE]; + uint8_t mat_l2_F2[_O1 * _O2_BYTE]; + gfmat_prod(mat_l2_F3, sk->l2_F3, _O2 * _O2_BYTE, _V1, vinegar); + gfmat_prod(mat_l2_F2, sk->l2_F2, _O1 * _O2_BYTE, _V1, vinegar); + + // Some local variables. + uint8_t _z[_PUB_M_BYTE]; + uint8_t y[_PUB_M_BYTE]; + uint8_t *x_v1 = vinegar; + uint8_t x_o1[_O1_BYTE]; + uint8_t x_o2[_O1_BYTE]; + + uint8_t digest_salt[_HASH_LEN + _SALT_BYTE]; + memcpy(digest_salt, _digest, _HASH_LEN); + uint8_t *salt = digest_salt + _HASH_LEN; + + uint8_t temp_o[_MAX_O_BYTE + 32] = {0}; + unsigned int succ = 0; + while (!succ) { + if (MAX_ATTEMPT_FRMAT <= n_attempt) { + break; + } + // The computation: H(digest||salt) --> z --S--> y --C-map--> x --T--> w + + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_prng_gen(&prng_sign, salt, _SALT_BYTE); // roll the salt + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_hash_msg(_z, _PUB_M_BYTE, digest_salt, _HASH_LEN + _SALT_BYTE); // H(digest||salt) + + // y = S^-1 * z + memcpy(y, _z, _PUB_M_BYTE); // identity part of S + gfmat_prod(temp_o, sk->s1, _O1_BYTE, _O2, _z + _O1_BYTE); + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_add(y, temp_o, _O1_BYTE); + + // Central Map: + // layer 1: calculate x_o1 + memcpy(temp_o, r_l1_F1, _O1_BYTE); + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_add(temp_o, y, _O1_BYTE); + gfmat_prod(x_o1, mat_l1, _O1_BYTE, _O1, temp_o); + + // layer 2: calculate x_o2 + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_set_zero(temp_o, _O2_BYTE); + gfmat_prod(temp_o, mat_l2_F2, _O2_BYTE, _O1, x_o1); // F2 + batch_quad_trimat_eval(mat_l2, sk->l2_F5, x_o1, _O1, _O2_BYTE); // F5 + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_add(temp_o, mat_l2, _O2_BYTE); + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_add(temp_o, r_l2_F1, _O2_BYTE); // F1 + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_add(temp_o, y + _O1_BYTE, _O2_BYTE); + + // generate the linear equations of the 2nd layer + gfmat_prod(mat_l2, sk->l2_F6, _O2 * _O2_BYTE, _O1, x_o1); // F6 + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_add(mat_l2, mat_l2_F3, _O2 * _O2_BYTE); // F3 + succ = gfmat_inv(mat_l2, mat_l2, _O2, mat_buffer); + gfmat_prod(x_o2, mat_l2, _O2_BYTE, _O2, temp_o); // solve l2 eqs + + n_attempt++; + }; + // w = T^-1 * y + uint8_t w[_PUB_N_BYTE]; + // identity part of T. + memcpy(w, x_v1, _V1_BYTE); + memcpy(w + _V1_BYTE, x_o1, _O1_BYTE); + memcpy(w + _V2_BYTE, x_o2, _O2_BYTE); + // Computing the t1 part. + gfmat_prod(y, sk->t1, _V1_BYTE, _O1, x_o1); + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_add(w, y, _V1_BYTE); + // Computing the t4 part. + gfmat_prod(y, sk->t4, _V1_BYTE, _O2, x_o2); + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_add(w, y, _V1_BYTE); + // Computing the t3 part. + gfmat_prod(y, sk->t3, _O1_BYTE, _O2, x_o2); + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_add(w + _V1_BYTE, y, _O1_BYTE); + + memset(signature, 0, _SIGNATURE_BYTE); // set the output 0 + // clean + memset(&prng_sign, 0, sizeof(prng_t)); + memset(vinegar, 0, _V1_BYTE); + memset(r_l1_F1, 0, _O1_BYTE); + memset(r_l2_F1, 0, _O2_BYTE); + memset(_z, 0, _PUB_M_BYTE); + memset(y, 0, _PUB_M_BYTE); + memset(x_o1, 0, _O1_BYTE); + memset(x_o2, 0, _O2_BYTE); + memset(temp_o, 0, sizeof(temp_o)); + + // return: copy w and salt to the signature. + if (MAX_ATTEMPT_FRMAT <= n_attempt) { + return -1; + } + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_add(signature, w, _PUB_N_BYTE); + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_add(signature + _PUB_N_BYTE, salt, _SALT_BYTE); + return 0; +} + +int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_rainbow_verify(const uint8_t *digest, const uint8_t *signature, const pk_t *pk) { + unsigned char digest_ck[_PUB_M_BYTE]; + // public_map( digest_ck , pk , signature ); Evaluating the quadratic public polynomials. + batch_quad_trimat_eval(digest_ck, pk->pk, signature, _PUB_N, _PUB_M_BYTE); + + unsigned char correct[_PUB_M_BYTE]; + unsigned char digest_salt[_HASH_LEN + _SALT_BYTE]; + memcpy(digest_salt, digest, _HASH_LEN); + memcpy(digest_salt + _HASH_LEN, signature + _PUB_N_BYTE, _SALT_BYTE); + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_hash_msg(correct, _PUB_M_BYTE, digest_salt, _HASH_LEN + _SALT_BYTE); // H( digest || salt ) + + // check consistancy. + unsigned char cc = 0; + for (unsigned int i = 0; i < _PUB_M_BYTE; i++) { + cc |= (digest_ck[i] ^ correct[i]); + } + return (0 == cc) ? 0 : -1; +} + + +int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_rainbow_verify_cyclic(const uint8_t *digest, const uint8_t *signature, const cpk_t *_pk) { + unsigned char pk[sizeof(pk_t) + 32]; + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_cpk_to_pk((pk_t *)pk, _pk); // generating classic public key. + return PQCLEAN_RAINBOWVCCYCLIC_CLEAN_rainbow_verify(digest, signature, (pk_t *)pk); +} diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/rainbow.h b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/rainbow.h new file mode 100644 index 0000000000..2592550726 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/rainbow.h @@ -0,0 +1,42 @@ +#ifndef _RAINBOW_H_ +#define _RAINBOW_H_ +/// @file rainbow.h +/// @brief APIs for rainbow. +/// + +#include "rainbow_config.h" +#include "rainbow_keypair.h" + +#include + +/// +/// @brief Signing function for classical secret key. +/// +/// @param[out] signature - the signature. +/// @param[in] sk - the secret key. +/// @param[in] digest - the digest. +/// +int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_rainbow_sign(uint8_t *signature, const sk_t *sk, const uint8_t *digest); + +/// +/// @brief Verifying function. +/// +/// @param[in] digest - the digest. +/// @param[in] signature - the signature. +/// @param[in] pk - the public key. +/// @return 0 for successful verified. -1 for failed verification. +/// +int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_rainbow_verify(const uint8_t *digest, const uint8_t *signature, const pk_t *pk); + + +/// +/// @brief Verifying function for cyclic public keys. +/// +/// @param[in] digest - the digest. +/// @param[in] signature - the signature. +/// @param[in] pk - the public key of cyclic rainbow. +/// @return 0 for successful verified. -1 for failed verification. +/// +int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_rainbow_verify_cyclic(const uint8_t *digest, const uint8_t *signature, const cpk_t *pk); + +#endif // _RAINBOW_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/rainbow_blas.h b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/rainbow_blas.h new file mode 100644 index 0000000000..8cf3e6912d --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/rainbow_blas.h @@ -0,0 +1,32 @@ +#ifndef _RAINBOW_BLAS_H_ +#define _RAINBOW_BLAS_H_ +/// @file rainbow_blas.h +/// @brief Defining the functions used in rainbow.c acconding to the definitions in rainbow_config.h +/// +/// Defining the functions used in rainbow.c acconding to the definitions in rainbow_config.h + +#include "blas.h" +#include "blas_comm.h" +#include "parallel_matrix_op.h" +#include "rainbow_config.h" + + +#define gfv_get_ele PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_get_ele +#define gfv_mul_scalar PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_mul_scalar +#define gfv_madd PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_madd + +#define gfmat_prod PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256mat_prod +#define gfmat_inv PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256mat_inv + +#define batch_trimat_madd PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_trimat_madd_gf256 +#define batch_trimatTr_madd PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_trimatTr_madd_gf256 +#define batch_2trimat_madd PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_2trimat_madd_gf256 +#define batch_matTr_madd PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_matTr_madd_gf256 +#define batch_bmatTr_madd PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_bmatTr_madd_gf256 +#define batch_mat_madd PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_mat_madd_gf256 + +#define batch_quad_trimat_eval PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_quad_trimat_eval_gf256 +#define batch_quad_recmat_eval PQCLEAN_RAINBOWVCCYCLIC_CLEAN_batch_quad_recmat_eval_gf256 + + +#endif // _RAINBOW_BLAS_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/rainbow_config.h b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/rainbow_config.h new file mode 100644 index 0000000000..f691dfb11a --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/rainbow_config.h @@ -0,0 +1,48 @@ +#ifndef _H_RAINBOW_CONFIG_H_ +#define _H_RAINBOW_CONFIG_H_ + +/// @file rainbow_config.h +/// @brief Defining the parameters of the Rainbow and the corresponding constants. +/// + +#define _GFSIZE 256 +#define _V1 92 +#define _O1 48 +#define _O2 48 +#define _MAX_O 48 +#define _HASH_LEN 64 + + +#define _V2 ((_V1) + (_O1)) + +/// size of N, in # of gf elements. +#define _PUB_N (_V1 + _O1 + _O2) + +/// size of M, in # gf elements. +#define _PUB_M (_O1 + _O2) + +/// size of variables, in # bytes. + +// GF256 +#define _V1_BYTE (_V1) +#define _V2_BYTE (_V2) +#define _O1_BYTE (_O1) +#define _O2_BYTE (_O2) +#define _MAX_O_BYTE (_MAX_O) +#define _PUB_N_BYTE (_PUB_N) +#define _PUB_M_BYTE (_PUB_M) + + +/// length of seed for public key, in # bytes +#define LEN_PKSEED 32 + +/// length of seed for secret key, in # bytes +#define LEN_SKSEED 32 + +/// length of salt for a signature, in # bytes +#define _SALT_BYTE 16 + +/// length of a signature +#define _SIGNATURE_BYTE (_PUB_N_BYTE + _SALT_BYTE) + +#endif // _H_RAINBOW_CONFIG_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/rainbow_keypair.c b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/rainbow_keypair.c new file mode 100644 index 0000000000..066f716900 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/rainbow_keypair.c @@ -0,0 +1,157 @@ +/// @file rainbow_keypair.c +/// @brief implementations of functions in rainbow_keypair.h +/// + +#include "rainbow_keypair.h" +#include "blas.h" +#include "blas_comm.h" +#include "rainbow_blas.h" +#include "rainbow_keypair_computation.h" +#include "utils_prng.h" +#include +#include +#include + +static void generate_S_T(unsigned char *s_and_t, prng_t *prng0) { + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_prng_gen(prng0, s_and_t, _O1_BYTE * _O2); // S1 + s_and_t += _O1_BYTE * _O2; + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_prng_gen(prng0, s_and_t, _V1_BYTE * _O1); // T1 + s_and_t += _V1_BYTE * _O1; + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_prng_gen(prng0, s_and_t, _V1_BYTE * _O2); // T2 + s_and_t += _V1_BYTE * _O2; + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_prng_gen(prng0, s_and_t, _O1_BYTE * _O2); // T3 +} + +static unsigned int generate_l1_F12(unsigned char *sk, prng_t *prng0) { + unsigned int n_byte_generated = 0; + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_prng_gen(prng0, sk, _O1_BYTE * N_TRIANGLE_TERMS(_V1)); // l1_F1 + sk += _O1_BYTE * N_TRIANGLE_TERMS(_V1); + n_byte_generated += _O1_BYTE * N_TRIANGLE_TERMS(_V1); + + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_prng_gen(prng0, sk, _O1_BYTE * _V1 * _O1); // l1_F2 + n_byte_generated += _O1_BYTE * _V1 * _O1; + return n_byte_generated; +} + +static unsigned int generate_l2_F12356(unsigned char *sk, prng_t *prng0) { + unsigned int n_byte_generated = 0; + + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * N_TRIANGLE_TERMS(_V1)); // l2_F1 + sk += _O2_BYTE * N_TRIANGLE_TERMS(_V1); + n_byte_generated += _O2_BYTE * N_TRIANGLE_TERMS(_V1); + + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * _V1 * _O1); // l2_F2 + sk += _O2_BYTE * _V1 * _O1; + n_byte_generated += _O2_BYTE * _V1 * _O1; + + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * _V1 * _O2); // l2_F3 + sk += _O2_BYTE * _V1 * _O1; + n_byte_generated += _O2_BYTE * _V1 * _O1; + + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * N_TRIANGLE_TERMS(_O1)); // l2_F5 + sk += _O2_BYTE * N_TRIANGLE_TERMS(_O1); + n_byte_generated += _O2_BYTE * N_TRIANGLE_TERMS(_O1); + + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_prng_gen(prng0, sk, _O2_BYTE * _O1 * _O2); // l2_F6 + n_byte_generated += _O2_BYTE * _O1 * _O2; + + return n_byte_generated; +} + +static void generate_B1_B2(unsigned char *sk, prng_t *prng0) { + sk += generate_l1_F12(sk, prng0); + generate_l2_F12356(sk, prng0); +} + +static void calculate_t4(unsigned char *t2_to_t4, const unsigned char *t1, const unsigned char *t3) { + // t4 = T_sk.t1 * T_sk.t3 - T_sk.t2 + unsigned char temp[_V1_BYTE + 32]; + unsigned char *t4 = t2_to_t4; + for (unsigned int i = 0; i < _O2; i++) { /// t3 width + gfmat_prod(temp, t1, _V1_BYTE, _O1, t3); + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_add(t4, temp, _V1_BYTE); + t4 += _V1_BYTE; + t3 += _O1_BYTE; + } +} + +static void obsfucate_l1_polys(unsigned char *l1_polys, const unsigned char *l2_polys, unsigned int n_terms, const unsigned char *s1) { + unsigned char temp[_O1_BYTE + 32]; + while (n_terms--) { + gfmat_prod(temp, s1, _O1_BYTE, _O2, l2_polys); + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_gf256v_add(l1_polys, temp, _O1_BYTE); + l1_polys += _O1_BYTE; + l2_polys += _O2_BYTE; + } +} + +/////////////////// Classic ////////////////////////////////// + + +///////////////////// Cyclic ////////////////////////////////// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_generate_keypair_cyclic(cpk_t *pk, sk_t *sk, const unsigned char *pk_seed, const unsigned char *sk_seed) { + memcpy(pk->pk_seed, pk_seed, LEN_PKSEED); + memcpy(sk->sk_seed, sk_seed, LEN_SKSEED); + + // prng for sk + prng_t prng; + prng_t *prng0 = &prng; + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_prng_set(prng0, sk_seed, LEN_SKSEED); + generate_S_T(sk->s1, prng0); // S,T: only a part of sk + + unsigned char t2[sizeof(sk->t4)]; + memcpy(t2, sk->t4, _V1_BYTE * _O2); // temporarily store t2 + calculate_t4(sk->t4, sk->t1, sk->t3); // t2 <- t4 + + // prng for pk + sk_t inst_Qs; + sk_t *Qs = &inst_Qs; + prng_t *prng1 = &prng; + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_prng_set(prng1, pk_seed, LEN_PKSEED); + generate_B1_B2(Qs->l1_F1, prng1); // generating l1_Q1, l1_Q2, l2_Q1, l2_Q2, l2_Q3, l2_Q5, l2_Q6 + obsfucate_l1_polys(Qs->l1_F1, Qs->l2_F1, N_TRIANGLE_TERMS(_V1), sk->s1); + obsfucate_l1_polys(Qs->l1_F2, Qs->l2_F2, _V1 * _O1, sk->s1); + // so far, the Qs contains l1_F1, l1_F2, l2_F1, l2_F2, l2_F3, l2_F5, l2_F6. + + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_calculate_F_from_Q(sk, Qs, sk); // calcuate the rest parts of secret key from Qs and S,T + + unsigned char t4[sizeof(sk->t4)]; + memcpy(t4, sk->t4, _V1_BYTE * _O2); // temporarily store t4 + memcpy(sk->t4, t2, _V1_BYTE * _O2); // restore t2 + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_calculate_Q_from_F_cyclic(pk, sk, sk); // calculate the rest parts of public key: l1_Q3, l1_Q5, l1_Q6, l1_Q9, l2_Q9 + memcpy(sk->t4, t4, _V1_BYTE * _O2); // restore t4 + + obsfucate_l1_polys(pk->l1_Q3, Qs->l2_F3, _V1 * _O2, sk->s1); + obsfucate_l1_polys(pk->l1_Q5, Qs->l2_F5, N_TRIANGLE_TERMS(_O1), sk->s1); + obsfucate_l1_polys(pk->l1_Q6, Qs->l2_F6, _O1 * _O2, sk->s1); + obsfucate_l1_polys(pk->l1_Q9, pk->l2_Q9, N_TRIANGLE_TERMS(_O2), sk->s1); + + // clean + memset(&prng, 0, sizeof(prng_t)); +} + + + +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_cpk_to_pk(pk_t *rpk, const cpk_t *cpk) { + // procedure: cpk_t --> extcpk_t --> pk_t + + // convert from cpk_t to extcpk_t + ext_cpk_t pk; + + // setup prng + prng_t prng0; + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_prng_set(&prng0, cpk->pk_seed, LEN_SKSEED); + + // generating parts of key with prng + generate_l1_F12(pk.l1_Q1, &prng0); + // copying parts of key from input. l1_Q3, l1_Q5, l1_Q6, l1_Q9 + memcpy(pk.l1_Q3, cpk->l1_Q3, _O1_BYTE * (_V1 * _O2 + N_TRIANGLE_TERMS(_O1) + _O1 * _O2 + N_TRIANGLE_TERMS(_O2))); + + // generating parts of key with prng + generate_l2_F12356(pk.l2_Q1, &prng0); + // copying parts of key from input: l2_Q9 + memcpy(pk.l2_Q9, cpk->l2_Q9, _O2_BYTE * N_TRIANGLE_TERMS(_O2)); + + // convert from extcpk_t to pk_t + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_extcpk_to_pk(rpk, &pk); +} diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/rainbow_keypair.h b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/rainbow_keypair.h new file mode 100644 index 0000000000..67ac998e00 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/rainbow_keypair.h @@ -0,0 +1,94 @@ +#ifndef _RAINBOW_KEYPAIR_H_ +#define _RAINBOW_KEYPAIR_H_ +/// @file rainbow_keypair.h +/// @brief Formats of key pairs and functions for generating key pairs. +/// Formats of key pairs and functions for generating key pairs. +/// + +#include "rainbow_config.h" + +#define N_TRIANGLE_TERMS(n_var) ((n_var) * ((n_var) + 1) / 2) + +/// @brief public key for classic rainbow +/// +/// public key for classic rainbow +/// +typedef struct rainbow_publickey { + unsigned char pk[(_PUB_M_BYTE)*N_TRIANGLE_TERMS(_PUB_N)]; +} pk_t; + +/// @brief secret key for classic rainbow +/// +/// secret key for classic rainbow +/// +typedef struct rainbow_secretkey { + /// + /// seed for generating secret key. + /// Generating S, T, and F for classic rainbow. + /// Generating S and T only for cyclic rainbow. + unsigned char sk_seed[LEN_SKSEED]; + + unsigned char s1[_O1_BYTE * _O2]; ///< part of S map + unsigned char t1[_V1_BYTE * _O1]; ///< part of T map + unsigned char t4[_V1_BYTE * _O2]; ///< part of T map + unsigned char t3[_O1_BYTE * _O2]; ///< part of T map + + unsigned char l1_F1[_O1_BYTE * N_TRIANGLE_TERMS(_V1)]; ///< part of C-map, F1, Layer1 + unsigned char l1_F2[_O1_BYTE * _V1 * _O1]; ///< part of C-map, F2, Layer1 + + unsigned char l2_F1[_O2_BYTE * N_TRIANGLE_TERMS(_V1)]; ///< part of C-map, F1, Layer2 + unsigned char l2_F2[_O2_BYTE * _V1 * _O1]; ///< part of C-map, F2, Layer2 + + unsigned char l2_F3[_O2_BYTE * _V1 * _O2]; ///< part of C-map, F3, Layer2 + unsigned char l2_F5[_O2_BYTE * N_TRIANGLE_TERMS(_O1)]; ///< part of C-map, F5, Layer2 + unsigned char l2_F6[_O2_BYTE * _O1 * _O2]; ///< part of C-map, F6, Layer2 +} sk_t; + +/// @brief public key for cyclic rainbow +/// +/// public key for cyclic rainbow +/// +typedef struct rainbow_publickey_cyclic { + unsigned char pk_seed[LEN_PKSEED]; ///< seed for generating l1_Q1,l1_Q2,l2_Q1,l2_Q2,l2_Q3,l2_Q5,l2_Q6 + + unsigned char l1_Q3[_O1_BYTE * _V1 * _O2]; ///< Q3, layer1 + unsigned char l1_Q5[_O1_BYTE * N_TRIANGLE_TERMS(_O1)]; ///< Q5, layer1 + unsigned char l1_Q6[_O1_BYTE * _O1 * _O2]; ///< Q6, layer1 + unsigned char l1_Q9[_O1_BYTE * N_TRIANGLE_TERMS(_O2)]; ///< Q9, layer1 + + unsigned char l2_Q9[_O2_BYTE * N_TRIANGLE_TERMS(_O2)]; ///< Q9, layer2 +} cpk_t; + +/// @brief compressed secret key for cyclic rainbow +/// +/// compressed secret key for cyclic rainbow +/// +typedef struct rainbow_secretkey_cyclic { + unsigned char pk_seed[LEN_PKSEED]; ///< seed for generating a part of public key. + unsigned char sk_seed[LEN_SKSEED]; ///< seed for generating a part of secret key. +} csk_t; + + +/// +/// @brief Generate key pairs for cyclic rainbow. +/// +/// @param[out] pk - the public key. +/// @param[out] sk - the secret key. +/// @param[in] pk_seed - seed for generating parts of public key. +/// @param[in] sk_seed - seed for generating secret key. +/// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_generate_keypair_cyclic(cpk_t *pk, sk_t *sk, const unsigned char *pk_seed, const unsigned char *sk_seed); + + + +//////////////////////////////////// + +/// +/// @brief converting formats of public keys : from cyclic version to classic key +/// +/// @param[out] pk - the classic public key. +/// @param[in] cpk - the cyclic public key. +/// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_cpk_to_pk(pk_t *pk, const cpk_t *cpk); + +#endif // _RAINBOW_KEYPAIR_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/rainbow_keypair_computation.c b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/rainbow_keypair_computation.c new file mode 100644 index 0000000000..db23a90765 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/rainbow_keypair_computation.c @@ -0,0 +1,213 @@ +/// @file rainbow_keypair_computation.c +/// @brief Implementations for functions in rainbow_keypair_computation.h +/// + +#include "rainbow_keypair_computation.h" +#include "blas.h" +#include "blas_comm.h" +#include "rainbow_blas.h" +#include "rainbow_keypair.h" +#include +#include +#include + +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_extcpk_to_pk(pk_t *pk, const ext_cpk_t *cpk) { + const unsigned char *idx_l1 = cpk->l1_Q1; + const unsigned char *idx_l2 = cpk->l2_Q1; + for (unsigned int i = 0; i < _V1; i++) { + for (unsigned int j = i; j < _V1; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWVCCYCLIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q2; + idx_l2 = cpk->l2_Q2; + for (unsigned int i = 0; i < _V1; i++) { + for (unsigned int j = _V1; j < _V1 + _O1; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWVCCYCLIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q3; + idx_l2 = cpk->l2_Q3; + for (unsigned int i = 0; i < _V1; i++) { + for (unsigned int j = _V1 + _O1; j < _PUB_N; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWVCCYCLIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q5; + idx_l2 = cpk->l2_Q5; + for (unsigned int i = _V1; i < _V1 + _O1; i++) { + for (unsigned int j = i; j < _V1 + _O1; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWVCCYCLIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q6; + idx_l2 = cpk->l2_Q6; + for (unsigned int i = _V1; i < _V1 + _O1; i++) { + for (unsigned int j = _V1 + _O1; j < _PUB_N; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWVCCYCLIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } + idx_l1 = cpk->l1_Q9; + idx_l2 = cpk->l2_Q9; + for (unsigned int i = _V1 + _O1; i < _PUB_N; i++) { + for (unsigned int j = i; j < _PUB_N; j++) { + unsigned int pub_idx = PQCLEAN_RAINBOWVCCYCLIC_CLEAN_idx_of_trimat(i, j, _PUB_N); + memcpy(&pk->pk[_PUB_M_BYTE * pub_idx], idx_l1, _O1_BYTE); + memcpy((&pk->pk[_PUB_M_BYTE * pub_idx]) + _O1_BYTE, idx_l2, _O2_BYTE); + idx_l1 += _O1_BYTE; + idx_l2 += _O2_BYTE; + } + } +} + +static void calculate_F_from_Q_ref(sk_t *Fs, const sk_t *Qs, sk_t *Ts) { + // Layer 1 + // F_sk.l1_F1s[i] = Q_pk.l1_F1s[i] + memcpy(Fs->l1_F1, Qs->l1_F1, _O1_BYTE * N_TRIANGLE_TERMS(_V1)); + + // F_sk.l1_F2s[i] = ( Q_pk.l1_F1s[i] + Q_pk.l1_F1s[i].transpose() ) * T_sk.t1 + Q_pk.l1_F2s[i] + memcpy(Fs->l1_F2, Qs->l1_F2, _O1_BYTE * _V1 * _O1); + batch_2trimat_madd(Fs->l1_F2, Qs->l1_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O1_BYTE); + + /* + Layer 2 + computations: + + F_sk.l2_F1s[i] = Q_pk.l2_F1s[i] + + Q1_T1 = Q_pk.l2_F1s[i]*T_sk.t1 + F_sk.l2_F2s[i] = Q1_T1 + Q_pk.l2_F2s[i] + Q_pk.l2_F1s[i].transpose() * T_sk.t1 + F_sk.l2_F5s[i] = UT( t1_tr* ( Q1_T1 + Q_pk.l2_F2s[i] ) ) + Q_pk.l2_F5s[i] + + Q1_Q1T_T4 = (Q_pk.l2_F1s[i] + Q_pk.l2_F1s[i].transpose()) * t4 + #Q1_Q1T_T4 = Q1_Q1T * t4 + Q2_T3 = Q_pk.l2_F2s[i]*T_sk.t3 + F_sk.l2_F3s[i] = Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] + F_sk.l2_F6s[i] = t1_tr * ( Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] ) + + Q_pk.l2_F2s[i].transpose() * t4 + + (Q_pk.l2_F5s[i] + Q_pk.l2_F5s[i].transpose())*T_sk.t3 + Q_pk.l2_F6s[i] + + */ + memcpy(Fs->l2_F1, Qs->l2_F1, _O2_BYTE * N_TRIANGLE_TERMS(_V1)); // F_sk.l2_F1s[i] = Q_pk.l2_F1s[i] + + // F_sk.l2_F2s[i] = Q1_T1 + Q_pk.l2_F2s[i] + Q_pk.l2_F1s[i].transpose() * T_sk.t1 + // F_sk.l2_F5s[i] = UT( t1_tr* ( Q1_T1 + Q_pk.l2_F2s[i] ) ) + Q_pk.l2_F5s[i] + memcpy(Fs->l2_F2, Qs->l2_F2, _O2_BYTE * _V1 * _O1); + batch_trimat_madd(Fs->l2_F2, Qs->l2_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O2_BYTE); // Q1_T1+ Q2 + + unsigned char tempQ[_O1 * _O1 * _O2_BYTE + 32]; + memset(tempQ, 0, _O1 * _O1 * _O2_BYTE); + batch_matTr_madd(tempQ, Ts->t1, _V1, _V1_BYTE, _O1, Fs->l2_F2, _O1, _O2_BYTE); // t1_tr*(Q1_T1+Q2) + memcpy(Fs->l2_F5, Qs->l2_F5, _O2_BYTE * N_TRIANGLE_TERMS(_O1)); // F5 + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_UpperTrianglize(Fs->l2_F5, tempQ, _O1, _O2_BYTE); // UT( ... ) + + batch_trimatTr_madd(Fs->l2_F2, Qs->l2_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O2_BYTE); // F2 = Q1_T1 + Q2 + Q1^tr*t1 + + // Q1_Q1T_T4 = (Q_pk.l2_F1s[i] + Q_pk.l2_F1s[i].transpose()) * t4 + // Q2_T3 = Q_pk.l2_F2s[i]*T_sk.t3 + // F_sk.l2_F3s[i] = Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] + memcpy(Fs->l2_F3, Qs->l2_F3, _V1 * _O2 * _O2_BYTE); + batch_2trimat_madd(Fs->l2_F3, Qs->l2_F1, Ts->t4, _V1, _V1_BYTE, _O2, _O2_BYTE); // Q1_Q1T_T4 + batch_mat_madd(Fs->l2_F3, Qs->l2_F2, _V1, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // Q2_T3 + + // F_sk.l2_F6s[i] = t1_tr * ( Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] ) + // + Q_pk.l2_F2s[i].transpose() * t4 + // + (Q_pk.l2_F5s[i] + Q_pk.l2_F5s[i].transpose())*T_sk.t3 + Q_pk.l2_F6s[i] + memcpy(Fs->l2_F6, Qs->l2_F6, _O1 * _O2 * _O2_BYTE); + batch_matTr_madd(Fs->l2_F6, Ts->t1, _V1, _V1_BYTE, _O1, Fs->l2_F3, _O2, _O2_BYTE); // t1_tr * ( Q1_Q1T_T4 + Q2_T3 + Q_pk.l2_F3s[i] ) + batch_2trimat_madd(Fs->l2_F6, Qs->l2_F5, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // (Q_pk.l2_F5s[i] + Q_pk.l2_F5s[i].transpose())*T_sk.t3 + batch_bmatTr_madd(Fs->l2_F6, Qs->l2_F2, _O1, Ts->t4, _V1, _V1_BYTE, _O2, _O2_BYTE); +} + +static void calculate_Q_from_F_cyclic_ref(cpk_t *Qs, const sk_t *Fs, const sk_t *Ts) { + // Layer 1: Computing Q5, Q3, Q6, Q9 + + // Q_pk.l1_F5s[i] = UT( T1tr* (F1 * T1 + F2) ) + const unsigned char *t2 = Ts->t4; + sk_t tempQ; + memcpy(tempQ.l1_F2, Fs->l1_F2, _O1_BYTE * _V1 * _O1); + batch_trimat_madd(tempQ.l1_F2, Fs->l1_F1, Ts->t1, _V1, _V1_BYTE, _O1, _O1_BYTE); // F1*T1 + F2 + memset(tempQ.l2_F1, 0, sizeof(tempQ.l2_F1)); + memset(tempQ.l2_F2, 0, sizeof(tempQ.l2_F2)); + batch_matTr_madd(tempQ.l2_F1, Ts->t1, _V1, _V1_BYTE, _O1, tempQ.l1_F2, _O1, _O1_BYTE); // T1tr*(F1*T1 + F2) + memset(Qs->l1_Q5, 0, _O1_BYTE * N_TRIANGLE_TERMS(_O1)); + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_UpperTrianglize(Qs->l1_Q5, tempQ.l2_F1, _O1, _O1_BYTE); // UT( ... ) // Q5 + + /* + F1_T2 = F1 * t2 + F2_T3 = F2 * t3 + F1_F1T_T2 + F2_T3 = F1_T2 + F2_T3 + F1tr * t2 + Q_pk.l1_F3s[i] = F1_F1T_T2 + F2_T3 + Q_pk.l1_F6s[i] = T1tr* ( F1_F1T_T2 + F2_T3 ) + F2tr * t2 + Q_pk.l1_F9s[i] = UT( T2tr* ( F1_T2 + F2_T3 ) ) + */ + memset(Qs->l1_Q3, 0, _O1_BYTE * _V1 * _O2); + memset(Qs->l1_Q6, 0, _O1_BYTE * _O1 * _O2); + memset(Qs->l1_Q9, 0, _O1_BYTE * N_TRIANGLE_TERMS(_O2)); + + batch_trimat_madd(Qs->l1_Q3, Fs->l1_F1, t2, _V1, _V1_BYTE, _O2, _O1_BYTE); // F1*T2 + batch_mat_madd(Qs->l1_Q3, Fs->l1_F2, _V1, Ts->t3, _O1, _O1_BYTE, _O2, _O1_BYTE); // F1_T2 + F2_T3 + + memset(tempQ.l1_F2, 0, _O1_BYTE * _V1 * _O2); // should be F3. assuming: _O1 >= _O2 + batch_matTr_madd(tempQ.l1_F2, t2, _V1, _V1_BYTE, _O2, Qs->l1_Q3, _O2, _O1_BYTE); // T2tr * ( F1_T2 + F2_T3 ) + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_UpperTrianglize(Qs->l1_Q9, tempQ.l1_F2, _O2, _O1_BYTE); // Q9 + + batch_trimatTr_madd(Qs->l1_Q3, Fs->l1_F1, t2, _V1, _V1_BYTE, _O2, _O1_BYTE); // F1_F1T_T2 + F2_T3 // Q3 + + batch_bmatTr_madd(Qs->l1_Q6, Fs->l1_F2, _O1, t2, _V1, _V1_BYTE, _O2, _O1_BYTE); // F2tr*T2 + batch_matTr_madd(Qs->l1_Q6, Ts->t1, _V1, _V1_BYTE, _O1, Qs->l1_Q3, _O2, _O1_BYTE); // Q6 + /* + Layer 2 + Computing Q9: + + F1_T2 = F1 * t2 + F2_T3 = F2 * t3 + Q9 = UT( T2tr*( F1*T2 + F2*T3 + F3 ) + T3tr*( F5*T3 + F6 ) ) + */ + sk_t tempQ2; + memcpy(tempQ2.l2_F3, Fs->l2_F3, _O2_BYTE * _V1 * _O2); /// F3 actually. + batch_trimat_madd(tempQ2.l2_F3, Fs->l2_F1, t2, _V1, _V1_BYTE, _O2, _O2_BYTE); // F1*T2 + F3 + batch_mat_madd(tempQ2.l2_F3, Fs->l2_F2, _V1, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // F1_T2 + F2_T3 + F3 + + memset(tempQ.l2_F3, 0, _O2_BYTE * _V1 * _O2); + batch_matTr_madd(tempQ.l2_F3, t2, _V1, _V1_BYTE, _O2, tempQ2.l2_F3, _O2, _O2_BYTE); // T2tr * ( ..... ) + + memcpy(tempQ.l2_F6, Fs->l2_F6, _O2_BYTE * _O1 * _O2); + batch_trimat_madd(tempQ.l2_F6, Fs->l2_F5, Ts->t3, _O1, _O1_BYTE, _O2, _O2_BYTE); // F5*T3 + F6 + + batch_matTr_madd(tempQ.l2_F3, Ts->t3, _O1, _O1_BYTE, _O2, tempQ.l2_F6, _O2, _O2_BYTE); // T2tr*( ..... ) + T3tr*( ..... ) + memset(Qs->l2_Q9, 0, _O2_BYTE * N_TRIANGLE_TERMS(_O2)); + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_UpperTrianglize(Qs->l2_Q9, tempQ.l2_F3, _O2, _O2_BYTE); // Q9 +} + +// Choosing implementations depends on the macros: _BLAS_SSE_ and _BLAS_AVX2_ +#define calculate_F_from_Q_impl calculate_F_from_Q_ref +#define calculate_Q_from_F_cyclic_impl calculate_Q_from_F_cyclic_ref + +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_calculate_F_from_Q(sk_t *Fs, const sk_t *Qs, sk_t *Ts) { + calculate_F_from_Q_impl(Fs, Qs, Ts); +} + +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_calculate_Q_from_F_cyclic(cpk_t *Qs, const sk_t *Fs, const sk_t *Ts) { + calculate_Q_from_F_cyclic_impl(Qs, Fs, Ts); +} diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/rainbow_keypair_computation.h b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/rainbow_keypair_computation.h new file mode 100644 index 0000000000..053e470036 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/rainbow_keypair_computation.h @@ -0,0 +1,71 @@ +#ifndef _RAINBOW_KEYPAIR_COMP_H_ +#define _RAINBOW_KEYPAIR_COMP_H_ +/// @file rainbow_keypair_computation.h +/// @brief Functions for calculating pk/sk while generating keys. +/// +/// Defining an internal structure of public key. +/// Functions for calculating pk/sk for key generation. +/// + +#include "rainbow_keypair.h" + +/// @brief The (internal use) public key for rainbow +/// +/// The (internal use) public key for rainbow. The public +/// polynomials are divided into l1_Q1, l1_Q2, ... l1_Q9, +/// l2_Q1, .... , l2_Q9. +/// +typedef struct rainbow_extend_publickey { + unsigned char l1_Q1[_O1_BYTE * N_TRIANGLE_TERMS(_V1)]; + unsigned char l1_Q2[_O1_BYTE * _V1 * _O1]; + unsigned char l1_Q3[_O1_BYTE * _V1 * _O2]; + unsigned char l1_Q5[_O1_BYTE * N_TRIANGLE_TERMS(_O1)]; + unsigned char l1_Q6[_O1_BYTE * _O1 * _O2]; + unsigned char l1_Q9[_O1_BYTE * N_TRIANGLE_TERMS(_O2)]; + + unsigned char l2_Q1[_O2_BYTE * N_TRIANGLE_TERMS(_V1)]; + unsigned char l2_Q2[_O2_BYTE * _V1 * _O1]; + unsigned char l2_Q3[_O2_BYTE * _V1 * _O2]; + unsigned char l2_Q5[_O2_BYTE * N_TRIANGLE_TERMS(_O1)]; + unsigned char l2_Q6[_O2_BYTE * _O1 * _O2]; + unsigned char l2_Q9[_O2_BYTE * N_TRIANGLE_TERMS(_O2)]; +} ext_cpk_t; + +/// +/// @brief converting formats of public keys : from ext_cpk_t version to pk_t +/// +/// @param[out] pk - the classic public key. +/// @param[in] cpk - the internel public key. +/// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_extcpk_to_pk(pk_t *pk, const ext_cpk_t *cpk); +///////////////////////////////////////////////// + +/// +/// @brief Computing public key from secret key +/// +/// @param[out] Qs - the public key +/// @param[in] Fs - parts of the secret key: l1_F1, l1_F2, l2_F1, l2_F2, l2_F3, l2_F5, l2_F6 +/// @param[in] Ts - parts of the secret key: T1, T4, T3 +/// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_calculate_Q_from_F(ext_cpk_t *Qs, const sk_t *Fs, const sk_t *Ts); + + +/// +/// @brief Computing parts of the sk from parts of pk and sk +/// +/// @param[out] Fs - parts of the sk: l1_F1, l1_F2, l2_F1, l2_F2, l2_F3, l2_F5, l2_F6 +/// @param[in] Qs - parts of the pk: l1_Q1, l1_Q2, l2_Q1, l2_Q2, l2_Q3, l2_Q5, l2_Q6 +/// @param[in] Ts - parts of the sk: T1, T4, T3 +/// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_calculate_F_from_Q(sk_t *Fs, const sk_t *Qs, sk_t *Ts); + +/// +/// @brief Computing parts of the pk from the secret key +/// +/// @param[out] Qs - parts of the pk: l1_Q3, l1_Q5, l2_Q6, l1_Q9, l2_Q9 +/// @param[in] Fs - parts of the sk: l1_F1, l1_F2, l2_F1, l2_F2, l2_F3, l2_F5, l2_F6 +/// @param[in] Ts - parts of the sk: T1, T4, T3 +/// +void PQCLEAN_RAINBOWVCCYCLIC_CLEAN_calculate_Q_from_F_cyclic(cpk_t *Qs, const sk_t *Fs, const sk_t *Ts); + +#endif // _RAINBOW_KEYPAIR_COMP_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/sign.c b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/sign.c new file mode 100644 index 0000000000..41a3d999c2 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/sign.c @@ -0,0 +1,76 @@ +/// @file sign.c +/// @brief the implementations for functions in api.h +/// +/// + +#include "api.h" +#include "rainbow.h" +#include "rainbow_config.h" +#include "rainbow_keypair.h" +#include "randombytes.h" +#include "utils_hash.h" +#include +#include + +int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_crypto_sign_keypair(unsigned char *pk, unsigned char *sk) { + unsigned char sk_seed[LEN_SKSEED] = {0}; + randombytes(sk_seed, LEN_SKSEED); + + unsigned char pk_seed[LEN_PKSEED] = {0}; + randombytes(pk_seed, LEN_PKSEED); + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_generate_keypair_cyclic((cpk_t *)pk, (sk_t *)sk, pk_seed, sk_seed); + return 0; +} + +int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_crypto_sign(unsigned char *sm, size_t *smlen, const unsigned char *m, size_t mlen, const unsigned char *sk) { + unsigned char digest[_HASH_LEN]; + + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_hash_msg(digest, _HASH_LEN, m, mlen); + + memcpy(sm, m, mlen); + smlen[0] = mlen + _SIGNATURE_BYTE; + + return PQCLEAN_RAINBOWVCCYCLIC_CLEAN_rainbow_sign(sm + mlen, (const sk_t *)sk, digest); +} + +int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { + int rc; + if (_SIGNATURE_BYTE > smlen) { + rc = -1; + } else { + *mlen = smlen - _SIGNATURE_BYTE; + + unsigned char digest[_HASH_LEN]; + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_hash_msg(digest, _HASH_LEN, sm, *mlen); + + rc = PQCLEAN_RAINBOWVCCYCLIC_CLEAN_rainbow_verify_cyclic(digest, sm + mlen[0], (const cpk_t *)pk); + } + if (!rc) { + memmove(m, sm, smlen - _SIGNATURE_BYTE); + } else { // bad signature + *mlen = (size_t) -1; + memset(m, 0, smlen); + } + return rc; +} + +int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_crypto_sign_signature( + uint8_t *sig, size_t *siglen, + const uint8_t *m, size_t mlen, const uint8_t *sk) { + unsigned char digest[_HASH_LEN]; + + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_hash_msg(digest, _HASH_LEN, m, mlen); + *siglen = _SIGNATURE_BYTE; + return PQCLEAN_RAINBOWVCCYCLIC_CLEAN_rainbow_sign(sig, (const sk_t *)sk, digest); +} + +int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_crypto_sign_verify( + const uint8_t *sig, size_t siglen, + const uint8_t *m, size_t mlen, const uint8_t *pk) { + if (siglen != _SIGNATURE_BYTE) { + return -1; + } + unsigned char digest[_HASH_LEN]; + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_hash_msg(digest, _HASH_LEN, m, mlen); + return PQCLEAN_RAINBOWVCCYCLIC_CLEAN_rainbow_verify_cyclic(digest, sig, (const cpk_t *)pk); +} diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/utils_hash.c b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/utils_hash.c new file mode 100644 index 0000000000..37ee106496 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/utils_hash.c @@ -0,0 +1,50 @@ +/// @file utils_hash.c +/// @brief the adapter for SHA2 families. +/// +/// + +#include "utils_hash.h" +#include "rainbow_config.h" +#include "sha2.h" + +static inline int _hash(unsigned char *digest, const unsigned char *m, size_t mlen) { + sha512(digest, m, mlen); + return 0; +} + +static inline int expand_hash(unsigned char *digest, size_t n_digest, const unsigned char *hash) { + if (_HASH_LEN >= n_digest) { + for (size_t i = 0; i < n_digest; i++) { + digest[i] = hash[i]; + } + return 0; + } + for (size_t i = 0; i < _HASH_LEN; i++) { + digest[i] = hash[i]; + } + n_digest -= _HASH_LEN; + + while (_HASH_LEN <= n_digest) { + _hash(digest + _HASH_LEN, digest, _HASH_LEN); + + n_digest -= _HASH_LEN; + digest += _HASH_LEN; + } + unsigned char temp[_HASH_LEN]; + if (n_digest) { + _hash(temp, digest, _HASH_LEN); + for (size_t i = 0; i < n_digest; i++) { + digest[_HASH_LEN + i] = temp[i]; + } + } + return 0; +} + +int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_hash_msg(unsigned char *digest, + size_t len_digest, + const unsigned char *m, + size_t mlen) { + unsigned char buf[_HASH_LEN]; + _hash(buf, m, mlen); + return expand_hash(digest, len_digest, buf); +} diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/utils_hash.h b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/utils_hash.h new file mode 100644 index 0000000000..6c38bbd518 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/utils_hash.h @@ -0,0 +1,11 @@ +#ifndef _UTILS_HASH_H_ +#define _UTILS_HASH_H_ +/// @file utils_hash.h +/// @brief the interface for adapting hash functions. +/// + +#include + +int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_hash_msg(unsigned char *digest, size_t len_digest, const unsigned char *m, size_t mlen); + +#endif // _UTILS_HASH_H_ diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/utils_prng.c b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/utils_prng.c new file mode 100644 index 0000000000..d390fa9825 --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/utils_prng.c @@ -0,0 +1,97 @@ +/// @file utils_prng.c +/// @brief The implementation of PRNG related functions. +/// + +#include "utils_prng.h" +#include "aes.h" +#include "randombytes.h" +#include "utils_hash.h" +#include +#include + +static void prng_update(const unsigned char *provided_data, + unsigned char *Key, + unsigned char *V) { + unsigned char temp[48]; + aes256ctx ctx; + aes256_keyexp(&ctx, Key); + for (int i = 0; i < 3; i++) { + //increment V + for (int j = 15; j >= 0; j--) { + if (V[j] == 0xff) { + V[j] = 0x00; + } else { + V[j]++; + break; + } + } + aes256_ecb(temp + 16 * i, V, 1, &ctx); + } + if (provided_data != NULL) { + for (int i = 0; i < 48; i++) { + temp[i] ^= provided_data[i]; + } + } + aes256_ctx_release(&ctx); + memcpy(Key, temp, 32); + memcpy(V, temp + 32, 16); +} +static void randombytes_init_with_state(prng_t *state, + unsigned char *entropy_input_48bytes) { + memset(state->Key, 0x00, 32); + memset(state->V, 0x00, 16); + prng_update(entropy_input_48bytes, state->Key, state->V); +} + +static int randombytes_with_state(prng_t *state, + unsigned char *x, + size_t xlen) { + + unsigned char block[16]; + int i = 0; + + aes256ctx ctx; + aes256_keyexp(&ctx, state->Key); + + while (xlen > 0) { + //increment V + for (int j = 15; j >= 0; j--) { + if (state->V[j] == 0xff) { + state->V[j] = 0x00; + } else { + state->V[j]++; + break; + } + } + aes256_ecb(block, state->V, 1, &ctx); + if (xlen > 15) { + memcpy(x + i, block, 16); + i += 16; + xlen -= 16; + } else { + memcpy(x + i, block, xlen); + xlen = 0; + } + } + aes256_ctx_release(&ctx); + prng_update(NULL, state->Key, state->V); + return 0; +} + +int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_prng_set(prng_t *ctx, const void *prng_seed, unsigned long prng_seedlen) { + unsigned char seed[48]; + if (prng_seedlen >= 48) { + memcpy(seed, prng_seed, 48); + } else { + memcpy(seed, prng_seed, prng_seedlen); + PQCLEAN_RAINBOWVCCYCLIC_CLEAN_hash_msg(seed + prng_seedlen, 48 - (unsigned)prng_seedlen, (const unsigned char *)prng_seed, prng_seedlen); + } + + randombytes_init_with_state(ctx, seed); + + return 0; +} + +int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_prng_gen(prng_t *ctx, unsigned char *out, unsigned long outlen) { + return randombytes_with_state(ctx, out, outlen); +} diff --git a/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/utils_prng.h b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/utils_prng.h new file mode 100644 index 0000000000..35c4f0a7ec --- /dev/null +++ b/src/sig/rainbow/pqclean_rainbowVc-cyclic_clean/utils_prng.h @@ -0,0 +1,18 @@ +#ifndef _UTILS_PRNG_H_ +#define _UTILS_PRNG_H_ +/// @file utils_prng.h +/// @brief the interface for adapting PRNG functions. +/// +/// + +#include "randombytes.h" + +typedef struct { + unsigned char Key[32]; + unsigned char V[16]; +} prng_t; + +int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_prng_set(prng_t *ctx, const void *prng_seed, unsigned long prng_seedlen); +int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_prng_gen(prng_t *ctx, unsigned char *out, unsigned long outlen); + +#endif // _UTILS_PRNG_H_ diff --git a/src/sig/rainbow/sig_rainbow.h b/src/sig/rainbow/sig_rainbow.h new file mode 100644 index 0000000000..431e181863 --- /dev/null +++ b/src/sig/rainbow/sig_rainbow.h @@ -0,0 +1,105 @@ +#ifndef _OQS_SIG_RAINBOW_H +#define _OQS_SIG_RAINBOW_H + +#include + +#ifdef OQS_ENABLE_SIG_rainbow_Ia_classic +#define OQS_SIG_rainbow_Ia_classic_length_public_key 148992 +#define OQS_SIG_rainbow_Ia_classic_length_secret_key 92960 +#define OQS_SIG_rainbow_Ia_classic_length_signature 64 + +OQS_SIG *OQS_SIG_rainbow_Ia_classic_new(void); +OQS_API OQS_STATUS OQS_SIG_rainbow_Ia_classic_keypair(uint8_t *public_key, uint8_t *secret_key); +OQS_API OQS_STATUS OQS_SIG_rainbow_Ia_classic_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); +OQS_API OQS_STATUS OQS_SIG_rainbow_Ia_classic_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +#endif + +#ifdef OQS_ENABLE_SIG_rainbow_Ia_cyclic +#define OQS_SIG_rainbow_Ia_cyclic_length_public_key 58144 +#define OQS_SIG_rainbow_Ia_cyclic_length_secret_key 92960 +#define OQS_SIG_rainbow_Ia_cyclic_length_signature 64 + +OQS_SIG *OQS_SIG_rainbow_Ia_cyclic_new(void); +OQS_API OQS_STATUS OQS_SIG_rainbow_Ia_cyclic_keypair(uint8_t *public_key, uint8_t *secret_key); +OQS_API OQS_STATUS OQS_SIG_rainbow_Ia_cyclic_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); +OQS_API OQS_STATUS OQS_SIG_rainbow_Ia_cyclic_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +#endif + +#ifdef OQS_ENABLE_SIG_rainbow_Ia_cyclic_compressed +#define OQS_SIG_rainbow_Ia_cyclic_compressed_length_public_key 58144 +#define OQS_SIG_rainbow_Ia_cyclic_compressed_length_secret_key 64 +#define OQS_SIG_rainbow_Ia_cyclic_compressed_length_signature 64 + +OQS_SIG *OQS_SIG_rainbow_Ia_cyclic_compressed_new(void); +OQS_API OQS_STATUS OQS_SIG_rainbow_Ia_cyclic_compressed_keypair(uint8_t *public_key, uint8_t *secret_key); +OQS_API OQS_STATUS OQS_SIG_rainbow_Ia_cyclic_compressed_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); +OQS_API OQS_STATUS OQS_SIG_rainbow_Ia_cyclic_compressed_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +#endif + +#ifdef OQS_ENABLE_SIG_rainbow_IIIc_classic +#define OQS_SIG_rainbow_IIIc_classic_length_public_key 710640 +#define OQS_SIG_rainbow_IIIc_classic_length_secret_key 511448 +#define OQS_SIG_rainbow_IIIc_classic_length_signature 156 + +OQS_SIG *OQS_SIG_rainbow_IIIc_classic_new(void); +OQS_API OQS_STATUS OQS_SIG_rainbow_IIIc_classic_keypair(uint8_t *public_key, uint8_t *secret_key); +OQS_API OQS_STATUS OQS_SIG_rainbow_IIIc_classic_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); +OQS_API OQS_STATUS OQS_SIG_rainbow_IIIc_classic_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +#endif + +#ifdef OQS_ENABLE_SIG_rainbow_IIIc_cyclic +#define OQS_SIG_rainbow_IIIc_cyclic_length_public_key 206744 +#define OQS_SIG_rainbow_IIIc_cyclic_length_secret_key 511448 +#define OQS_SIG_rainbow_IIIc_cyclic_length_signature 156 + +OQS_SIG *OQS_SIG_rainbow_IIIc_cyclic_new(void); +OQS_API OQS_STATUS OQS_SIG_rainbow_IIIc_cyclic_keypair(uint8_t *public_key, uint8_t *secret_key); +OQS_API OQS_STATUS OQS_SIG_rainbow_IIIc_cyclic_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); +OQS_API OQS_STATUS OQS_SIG_rainbow_IIIc_cyclic_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +#endif + +#ifdef OQS_ENABLE_SIG_rainbow_IIIc_cyclic_compressed +#define OQS_SIG_rainbow_IIIc_cyclic_compressed_length_public_key 206744 +#define OQS_SIG_rainbow_IIIc_cyclic_compressed_length_secret_key 64 +#define OQS_SIG_rainbow_IIIc_cyclic_compressed_length_signature 156 + +OQS_SIG *OQS_SIG_rainbow_IIIc_cyclic_compressed_new(void); +OQS_API OQS_STATUS OQS_SIG_rainbow_IIIc_cyclic_compressed_keypair(uint8_t *public_key, uint8_t *secret_key); +OQS_API OQS_STATUS OQS_SIG_rainbow_IIIc_cyclic_compressed_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); +OQS_API OQS_STATUS OQS_SIG_rainbow_IIIc_cyclic_compressed_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +#endif + +#ifdef OQS_ENABLE_SIG_rainbow_Vc_classic +#define OQS_SIG_rainbow_Vc_classic_length_public_key 1705536 +#define OQS_SIG_rainbow_Vc_classic_length_secret_key 1227104 +#define OQS_SIG_rainbow_Vc_classic_length_signature 204 + +OQS_SIG *OQS_SIG_rainbow_Vc_classic_new(void); +OQS_API OQS_STATUS OQS_SIG_rainbow_Vc_classic_keypair(uint8_t *public_key, uint8_t *secret_key); +OQS_API OQS_STATUS OQS_SIG_rainbow_Vc_classic_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); +OQS_API OQS_STATUS OQS_SIG_rainbow_Vc_classic_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +#endif + +#ifdef OQS_ENABLE_SIG_rainbow_Vc_cyclic +#define OQS_SIG_rainbow_Vc_cyclic_length_public_key 491936 +#define OQS_SIG_rainbow_Vc_cyclic_length_secret_key 1227104 +#define OQS_SIG_rainbow_Vc_cyclic_length_signature 204 + +OQS_SIG *OQS_SIG_rainbow_Vc_cyclic_new(void); +OQS_API OQS_STATUS OQS_SIG_rainbow_Vc_cyclic_keypair(uint8_t *public_key, uint8_t *secret_key); +OQS_API OQS_STATUS OQS_SIG_rainbow_Vc_cyclic_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); +OQS_API OQS_STATUS OQS_SIG_rainbow_Vc_cyclic_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +#endif + +#ifdef OQS_ENABLE_SIG_rainbow_Vc_cyclic_compressed +#define OQS_SIG_rainbow_Vc_cyclic_compressed_length_public_key 491936 +#define OQS_SIG_rainbow_Vc_cyclic_compressed_length_secret_key 64 +#define OQS_SIG_rainbow_Vc_cyclic_compressed_length_signature 204 + +OQS_SIG *OQS_SIG_rainbow_Vc_cyclic_compressed_new(void); +OQS_API OQS_STATUS OQS_SIG_rainbow_Vc_cyclic_compressed_keypair(uint8_t *public_key, uint8_t *secret_key); +OQS_API OQS_STATUS OQS_SIG_rainbow_Vc_cyclic_compressed_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key); +OQS_API OQS_STATUS OQS_SIG_rainbow_Vc_cyclic_compressed_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key); +#endif + +#endif diff --git a/src/sig/rainbow/sig_rainbow_IIIc_classic.c b/src/sig/rainbow/sig_rainbow_IIIc_classic.c new file mode 100644 index 0000000000..29c5893a90 --- /dev/null +++ b/src/sig/rainbow/sig_rainbow_IIIc_classic.c @@ -0,0 +1,44 @@ +#include + +#include + +#ifdef OQS_ENABLE_SIG_rainbow_IIIc_classic + +OQS_SIG *OQS_SIG_rainbow_IIIc_classic_new() { + + OQS_SIG *sig = malloc(sizeof(OQS_SIG)); + if (sig == NULL) { + return NULL; + } + sig->method_name = OQS_SIG_alg_rainbow_IIIc_classic; + sig->alg_version = "https://github.com/fast-crypto-lab/rainbow-submission-round2/commit/af826fcb78f6af51a02d0352cff28a9690467bfd"; + + sig->claimed_nist_level = 3; + sig->euf_cma = true; + + sig->length_public_key = OQS_SIG_rainbow_IIIc_classic_length_public_key; + sig->length_secret_key = OQS_SIG_rainbow_IIIc_classic_length_secret_key; + sig->length_signature = OQS_SIG_rainbow_IIIc_classic_length_signature; + + sig->keypair = OQS_SIG_rainbow_IIIc_classic_keypair; + sig->sign = OQS_SIG_rainbow_IIIc_classic_sign; + sig->verify = OQS_SIG_rainbow_IIIc_classic_verify; + + return sig; +} + +int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); + +OQS_API OQS_STATUS OQS_SIG_rainbow_IIIc_classic_keypair(uint8_t *public_key, uint8_t *secret_key) { + return (OQS_STATUS) PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_crypto_sign_keypair(public_key, secret_key); +} +OQS_API OQS_STATUS OQS_SIG_rainbow_IIIc_classic_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { + return (OQS_STATUS) PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); +} +OQS_API OQS_STATUS OQS_SIG_rainbow_IIIc_classic_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { + return (OQS_STATUS) PQCLEAN_RAINBOWIIICCLASSIC_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); +} + +#endif diff --git a/src/sig/rainbow/sig_rainbow_IIIc_cyclic.c b/src/sig/rainbow/sig_rainbow_IIIc_cyclic.c new file mode 100644 index 0000000000..75f76d5868 --- /dev/null +++ b/src/sig/rainbow/sig_rainbow_IIIc_cyclic.c @@ -0,0 +1,44 @@ +#include + +#include + +#ifdef OQS_ENABLE_SIG_rainbow_IIIc_cyclic + +OQS_SIG *OQS_SIG_rainbow_IIIc_cyclic_new() { + + OQS_SIG *sig = malloc(sizeof(OQS_SIG)); + if (sig == NULL) { + return NULL; + } + sig->method_name = OQS_SIG_alg_rainbow_IIIc_cyclic; + sig->alg_version = "https://github.com/fast-crypto-lab/rainbow-submission-round2/commit/af826fcb78f6af51a02d0352cff28a9690467bfd"; + + sig->claimed_nist_level = 3; + sig->euf_cma = true; + + sig->length_public_key = OQS_SIG_rainbow_IIIc_cyclic_length_public_key; + sig->length_secret_key = OQS_SIG_rainbow_IIIc_cyclic_length_secret_key; + sig->length_signature = OQS_SIG_rainbow_IIIc_cyclic_length_signature; + + sig->keypair = OQS_SIG_rainbow_IIIc_cyclic_keypair; + sig->sign = OQS_SIG_rainbow_IIIc_cyclic_sign; + sig->verify = OQS_SIG_rainbow_IIIc_cyclic_verify; + + return sig; +} + +int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); + +OQS_API OQS_STATUS OQS_SIG_rainbow_IIIc_cyclic_keypair(uint8_t *public_key, uint8_t *secret_key) { + return (OQS_STATUS) PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_crypto_sign_keypair(public_key, secret_key); +} +OQS_API OQS_STATUS OQS_SIG_rainbow_IIIc_cyclic_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { + return (OQS_STATUS) PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); +} +OQS_API OQS_STATUS OQS_SIG_rainbow_IIIc_cyclic_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { + return (OQS_STATUS) PQCLEAN_RAINBOWIIICCYCLIC_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); +} + +#endif diff --git a/src/sig/rainbow/sig_rainbow_IIIc_cyclic_compressed.c b/src/sig/rainbow/sig_rainbow_IIIc_cyclic_compressed.c new file mode 100644 index 0000000000..908d5464d0 --- /dev/null +++ b/src/sig/rainbow/sig_rainbow_IIIc_cyclic_compressed.c @@ -0,0 +1,44 @@ +#include + +#include + +#ifdef OQS_ENABLE_SIG_rainbow_IIIc_cyclic_compressed + +OQS_SIG *OQS_SIG_rainbow_IIIc_cyclic_compressed_new() { + + OQS_SIG *sig = malloc(sizeof(OQS_SIG)); + if (sig == NULL) { + return NULL; + } + sig->method_name = OQS_SIG_alg_rainbow_IIIc_cyclic_compressed; + sig->alg_version = "https://github.com/fast-crypto-lab/rainbow-submission-round2/commit/af826fcb78f6af51a02d0352cff28a9690467bfd"; + + sig->claimed_nist_level = 3; + sig->euf_cma = true; + + sig->length_public_key = OQS_SIG_rainbow_IIIc_cyclic_compressed_length_public_key; + sig->length_secret_key = OQS_SIG_rainbow_IIIc_cyclic_compressed_length_secret_key; + sig->length_signature = OQS_SIG_rainbow_IIIc_cyclic_compressed_length_signature; + + sig->keypair = OQS_SIG_rainbow_IIIc_cyclic_compressed_keypair; + sig->sign = OQS_SIG_rainbow_IIIc_cyclic_compressed_sign; + sig->verify = OQS_SIG_rainbow_IIIc_cyclic_compressed_verify; + + return sig; +} + +int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); + +OQS_API OQS_STATUS OQS_SIG_rainbow_IIIc_cyclic_compressed_keypair(uint8_t *public_key, uint8_t *secret_key) { + return (OQS_STATUS) PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_crypto_sign_keypair(public_key, secret_key); +} +OQS_API OQS_STATUS OQS_SIG_rainbow_IIIc_cyclic_compressed_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { + return (OQS_STATUS) PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); +} +OQS_API OQS_STATUS OQS_SIG_rainbow_IIIc_cyclic_compressed_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { + return (OQS_STATUS) PQCLEAN_RAINBOWIIICCYCLICCOMPRESSED_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); +} + +#endif diff --git a/src/sig/rainbow/sig_rainbow_Ia_classic.c b/src/sig/rainbow/sig_rainbow_Ia_classic.c new file mode 100644 index 0000000000..2fa8bdac84 --- /dev/null +++ b/src/sig/rainbow/sig_rainbow_Ia_classic.c @@ -0,0 +1,44 @@ +#include + +#include + +#ifdef OQS_ENABLE_SIG_rainbow_Ia_classic + +OQS_SIG *OQS_SIG_rainbow_Ia_classic_new() { + + OQS_SIG *sig = malloc(sizeof(OQS_SIG)); + if (sig == NULL) { + return NULL; + } + sig->method_name = OQS_SIG_alg_rainbow_Ia_classic; + sig->alg_version = "https://github.com/fast-crypto-lab/rainbow-submission-round2/commit/af826fcb78f6af51a02d0352cff28a9690467bfd"; + + sig->claimed_nist_level = 1; + sig->euf_cma = true; + + sig->length_public_key = OQS_SIG_rainbow_Ia_classic_length_public_key; + sig->length_secret_key = OQS_SIG_rainbow_Ia_classic_length_secret_key; + sig->length_signature = OQS_SIG_rainbow_Ia_classic_length_signature; + + sig->keypair = OQS_SIG_rainbow_Ia_classic_keypair; + sig->sign = OQS_SIG_rainbow_Ia_classic_sign; + sig->verify = OQS_SIG_rainbow_Ia_classic_verify; + + return sig; +} + +int PQCLEAN_RAINBOWIACLASSIC_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +int PQCLEAN_RAINBOWIACLASSIC_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_RAINBOWIACLASSIC_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); + +OQS_API OQS_STATUS OQS_SIG_rainbow_Ia_classic_keypair(uint8_t *public_key, uint8_t *secret_key) { + return (OQS_STATUS) PQCLEAN_RAINBOWIACLASSIC_CLEAN_crypto_sign_keypair(public_key, secret_key); +} +OQS_API OQS_STATUS OQS_SIG_rainbow_Ia_classic_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { + return (OQS_STATUS) PQCLEAN_RAINBOWIACLASSIC_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); +} +OQS_API OQS_STATUS OQS_SIG_rainbow_Ia_classic_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { + return (OQS_STATUS) PQCLEAN_RAINBOWIACLASSIC_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); +} + +#endif diff --git a/src/sig/rainbow/sig_rainbow_Ia_cyclic.c b/src/sig/rainbow/sig_rainbow_Ia_cyclic.c new file mode 100644 index 0000000000..63b90b5767 --- /dev/null +++ b/src/sig/rainbow/sig_rainbow_Ia_cyclic.c @@ -0,0 +1,44 @@ +#include + +#include + +#ifdef OQS_ENABLE_SIG_rainbow_Ia_cyclic + +OQS_SIG *OQS_SIG_rainbow_Ia_cyclic_new() { + + OQS_SIG *sig = malloc(sizeof(OQS_SIG)); + if (sig == NULL) { + return NULL; + } + sig->method_name = OQS_SIG_alg_rainbow_Ia_cyclic; + sig->alg_version = "https://github.com/fast-crypto-lab/rainbow-submission-round2/commit/af826fcb78f6af51a02d0352cff28a9690467bfd"; + + sig->claimed_nist_level = 1; + sig->euf_cma = true; + + sig->length_public_key = OQS_SIG_rainbow_Ia_cyclic_length_public_key; + sig->length_secret_key = OQS_SIG_rainbow_Ia_cyclic_length_secret_key; + sig->length_signature = OQS_SIG_rainbow_Ia_cyclic_length_signature; + + sig->keypair = OQS_SIG_rainbow_Ia_cyclic_keypair; + sig->sign = OQS_SIG_rainbow_Ia_cyclic_sign; + sig->verify = OQS_SIG_rainbow_Ia_cyclic_verify; + + return sig; +} + +int PQCLEAN_RAINBOWIACYCLIC_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +int PQCLEAN_RAINBOWIACYCLIC_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_RAINBOWIACYCLIC_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); + +OQS_API OQS_STATUS OQS_SIG_rainbow_Ia_cyclic_keypair(uint8_t *public_key, uint8_t *secret_key) { + return (OQS_STATUS) PQCLEAN_RAINBOWIACYCLIC_CLEAN_crypto_sign_keypair(public_key, secret_key); +} +OQS_API OQS_STATUS OQS_SIG_rainbow_Ia_cyclic_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { + return (OQS_STATUS) PQCLEAN_RAINBOWIACYCLIC_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); +} +OQS_API OQS_STATUS OQS_SIG_rainbow_Ia_cyclic_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { + return (OQS_STATUS) PQCLEAN_RAINBOWIACYCLIC_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); +} + +#endif diff --git a/src/sig/rainbow/sig_rainbow_Ia_cyclic_compressed.c b/src/sig/rainbow/sig_rainbow_Ia_cyclic_compressed.c new file mode 100644 index 0000000000..7b1156835f --- /dev/null +++ b/src/sig/rainbow/sig_rainbow_Ia_cyclic_compressed.c @@ -0,0 +1,44 @@ +#include + +#include + +#ifdef OQS_ENABLE_SIG_rainbow_Ia_cyclic_compressed + +OQS_SIG *OQS_SIG_rainbow_Ia_cyclic_compressed_new() { + + OQS_SIG *sig = malloc(sizeof(OQS_SIG)); + if (sig == NULL) { + return NULL; + } + sig->method_name = OQS_SIG_alg_rainbow_Ia_cyclic_compressed; + sig->alg_version = "https://github.com/fast-crypto-lab/rainbow-submission-round2/commit/af826fcb78f6af51a02d0352cff28a9690467bfd"; + + sig->claimed_nist_level = 1; + sig->euf_cma = true; + + sig->length_public_key = OQS_SIG_rainbow_Ia_cyclic_compressed_length_public_key; + sig->length_secret_key = OQS_SIG_rainbow_Ia_cyclic_compressed_length_secret_key; + sig->length_signature = OQS_SIG_rainbow_Ia_cyclic_compressed_length_signature; + + sig->keypair = OQS_SIG_rainbow_Ia_cyclic_compressed_keypair; + sig->sign = OQS_SIG_rainbow_Ia_cyclic_compressed_sign; + sig->verify = OQS_SIG_rainbow_Ia_cyclic_compressed_verify; + + return sig; +} + +int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); + +OQS_API OQS_STATUS OQS_SIG_rainbow_Ia_cyclic_compressed_keypair(uint8_t *public_key, uint8_t *secret_key) { + return (OQS_STATUS) PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_crypto_sign_keypair(public_key, secret_key); +} +OQS_API OQS_STATUS OQS_SIG_rainbow_Ia_cyclic_compressed_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { + return (OQS_STATUS) PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); +} +OQS_API OQS_STATUS OQS_SIG_rainbow_Ia_cyclic_compressed_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { + return (OQS_STATUS) PQCLEAN_RAINBOWIACYCLICCOMPRESSED_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); +} + +#endif diff --git a/src/sig/rainbow/sig_rainbow_Vc_classic.c b/src/sig/rainbow/sig_rainbow_Vc_classic.c new file mode 100644 index 0000000000..933eceac8c --- /dev/null +++ b/src/sig/rainbow/sig_rainbow_Vc_classic.c @@ -0,0 +1,44 @@ +#include + +#include + +#ifdef OQS_ENABLE_SIG_rainbow_Vc_classic + +OQS_SIG *OQS_SIG_rainbow_Vc_classic_new() { + + OQS_SIG *sig = malloc(sizeof(OQS_SIG)); + if (sig == NULL) { + return NULL; + } + sig->method_name = OQS_SIG_alg_rainbow_Vc_classic; + sig->alg_version = "https://github.com/fast-crypto-lab/rainbow-submission-round2/commit/af826fcb78f6af51a02d0352cff28a9690467bfd"; + + sig->claimed_nist_level = 5; + sig->euf_cma = true; + + sig->length_public_key = OQS_SIG_rainbow_Vc_classic_length_public_key; + sig->length_secret_key = OQS_SIG_rainbow_Vc_classic_length_secret_key; + sig->length_signature = OQS_SIG_rainbow_Vc_classic_length_signature; + + sig->keypair = OQS_SIG_rainbow_Vc_classic_keypair; + sig->sign = OQS_SIG_rainbow_Vc_classic_sign; + sig->verify = OQS_SIG_rainbow_Vc_classic_verify; + + return sig; +} + +int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_RAINBOWVCCLASSIC_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); + +OQS_API OQS_STATUS OQS_SIG_rainbow_Vc_classic_keypair(uint8_t *public_key, uint8_t *secret_key) { + return (OQS_STATUS) PQCLEAN_RAINBOWVCCLASSIC_CLEAN_crypto_sign_keypair(public_key, secret_key); +} +OQS_API OQS_STATUS OQS_SIG_rainbow_Vc_classic_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { + return (OQS_STATUS) PQCLEAN_RAINBOWVCCLASSIC_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); +} +OQS_API OQS_STATUS OQS_SIG_rainbow_Vc_classic_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { + return (OQS_STATUS) PQCLEAN_RAINBOWVCCLASSIC_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); +} + +#endif diff --git a/src/sig/rainbow/sig_rainbow_Vc_cyclic.c b/src/sig/rainbow/sig_rainbow_Vc_cyclic.c new file mode 100644 index 0000000000..a39381c6e8 --- /dev/null +++ b/src/sig/rainbow/sig_rainbow_Vc_cyclic.c @@ -0,0 +1,44 @@ +#include + +#include + +#ifdef OQS_ENABLE_SIG_rainbow_Vc_cyclic + +OQS_SIG *OQS_SIG_rainbow_Vc_cyclic_new() { + + OQS_SIG *sig = malloc(sizeof(OQS_SIG)); + if (sig == NULL) { + return NULL; + } + sig->method_name = OQS_SIG_alg_rainbow_Vc_cyclic; + sig->alg_version = "https://github.com/fast-crypto-lab/rainbow-submission-round2/commit/af826fcb78f6af51a02d0352cff28a9690467bfd"; + + sig->claimed_nist_level = 5; + sig->euf_cma = true; + + sig->length_public_key = OQS_SIG_rainbow_Vc_cyclic_length_public_key; + sig->length_secret_key = OQS_SIG_rainbow_Vc_cyclic_length_secret_key; + sig->length_signature = OQS_SIG_rainbow_Vc_cyclic_length_signature; + + sig->keypair = OQS_SIG_rainbow_Vc_cyclic_keypair; + sig->sign = OQS_SIG_rainbow_Vc_cyclic_sign; + sig->verify = OQS_SIG_rainbow_Vc_cyclic_verify; + + return sig; +} + +int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_RAINBOWVCCYCLIC_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); + +OQS_API OQS_STATUS OQS_SIG_rainbow_Vc_cyclic_keypair(uint8_t *public_key, uint8_t *secret_key) { + return (OQS_STATUS) PQCLEAN_RAINBOWVCCYCLIC_CLEAN_crypto_sign_keypair(public_key, secret_key); +} +OQS_API OQS_STATUS OQS_SIG_rainbow_Vc_cyclic_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { + return (OQS_STATUS) PQCLEAN_RAINBOWVCCYCLIC_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); +} +OQS_API OQS_STATUS OQS_SIG_rainbow_Vc_cyclic_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { + return (OQS_STATUS) PQCLEAN_RAINBOWVCCYCLIC_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); +} + +#endif diff --git a/src/sig/rainbow/sig_rainbow_Vc_cyclic_compressed.c b/src/sig/rainbow/sig_rainbow_Vc_cyclic_compressed.c new file mode 100644 index 0000000000..53afef9cda --- /dev/null +++ b/src/sig/rainbow/sig_rainbow_Vc_cyclic_compressed.c @@ -0,0 +1,44 @@ +#include + +#include + +#ifdef OQS_ENABLE_SIG_rainbow_Vc_cyclic_compressed + +OQS_SIG *OQS_SIG_rainbow_Vc_cyclic_compressed_new() { + + OQS_SIG *sig = malloc(sizeof(OQS_SIG)); + if (sig == NULL) { + return NULL; + } + sig->method_name = OQS_SIG_alg_rainbow_Vc_cyclic_compressed; + sig->alg_version = "https://github.com/fast-crypto-lab/rainbow-submission-round2/commit/af826fcb78f6af51a02d0352cff28a9690467bfd"; + + sig->claimed_nist_level = 5; + sig->euf_cma = true; + + sig->length_public_key = OQS_SIG_rainbow_Vc_cyclic_compressed_length_public_key; + sig->length_secret_key = OQS_SIG_rainbow_Vc_cyclic_compressed_length_secret_key; + sig->length_signature = OQS_SIG_rainbow_Vc_cyclic_compressed_length_signature; + + sig->keypair = OQS_SIG_rainbow_Vc_cyclic_compressed_keypair; + sig->sign = OQS_SIG_rainbow_Vc_cyclic_compressed_sign; + sig->verify = OQS_SIG_rainbow_Vc_cyclic_compressed_verify; + + return sig; +} + +int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_crypto_sign_keypair(uint8_t *pk, uint8_t *sk); +int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_crypto_sign_signature(uint8_t *sig, size_t *siglen, const uint8_t *m, size_t mlen, const uint8_t *sk); +int PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_crypto_sign_verify(const uint8_t *sig, size_t siglen, const uint8_t *m, size_t mlen, const uint8_t *pk); + +OQS_API OQS_STATUS OQS_SIG_rainbow_Vc_cyclic_compressed_keypair(uint8_t *public_key, uint8_t *secret_key) { + return (OQS_STATUS) PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_crypto_sign_keypair(public_key, secret_key); +} +OQS_API OQS_STATUS OQS_SIG_rainbow_Vc_cyclic_compressed_sign(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key) { + return (OQS_STATUS) PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_crypto_sign_signature(signature, signature_len, message, message_len, secret_key); +} +OQS_API OQS_STATUS OQS_SIG_rainbow_Vc_cyclic_compressed_verify(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key) { + return (OQS_STATUS) PQCLEAN_RAINBOWVCCYCLICCOMPRESSED_CLEAN_crypto_sign_verify(signature, signature_len, message, message_len, public_key); +} + +#endif diff --git a/src/sig/sig.c b/src/sig/sig.c index 63a2ce85cc..3360c30474 100644 --- a/src/sig/sig.c +++ b/src/sig/sig.c @@ -21,6 +21,15 @@ OQS_API const char *OQS_SIG_alg_identifier(size_t i) { OQS_SIG_alg_falcon_1024, OQS_SIG_alg_mqdss_31_48, OQS_SIG_alg_mqdss_31_64, + OQS_SIG_alg_rainbow_Ia_classic, + OQS_SIG_alg_rainbow_Ia_cyclic, + OQS_SIG_alg_rainbow_Ia_cyclic_compressed, + OQS_SIG_alg_rainbow_IIIc_classic, + OQS_SIG_alg_rainbow_IIIc_cyclic, + OQS_SIG_alg_rainbow_IIIc_cyclic_compressed, + OQS_SIG_alg_rainbow_Vc_classic, + OQS_SIG_alg_rainbow_Vc_cyclic, + OQS_SIG_alg_rainbow_Vc_cyclic_compressed, OQS_SIG_alg_sphincs_haraka_128f_robust, OQS_SIG_alg_sphincs_haraka_128f_simple, OQS_SIG_alg_sphincs_haraka_128s_robust, @@ -129,6 +138,60 @@ OQS_API int OQS_SIG_alg_is_enabled(const char *method_name) { return 1; #else return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_alg_rainbow_Ia_classic)) { +#ifdef OQS_ENABLE_SIG_rainbow_Ia_classic + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_alg_rainbow_Ia_cyclic)) { +#ifdef OQS_ENABLE_SIG_rainbow_Ia_cyclic + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_alg_rainbow_Ia_cyclic_compressed)) { +#ifdef OQS_ENABLE_SIG_rainbow_Ia_cyclic_compressed + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_alg_rainbow_IIIc_classic)) { +#ifdef OQS_ENABLE_SIG_rainbow_IIIc_classic + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_alg_rainbow_IIIc_cyclic)) { +#ifdef OQS_ENABLE_SIG_rainbow_IIIc_cyclic + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_alg_rainbow_IIIc_cyclic_compressed)) { +#ifdef OQS_ENABLE_SIG_rainbow_IIIc_cyclic_compressed + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_alg_rainbow_Vc_classic)) { +#ifdef OQS_ENABLE_SIG_rainbow_Vc_classic + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_alg_rainbow_Vc_cyclic)) { +#ifdef OQS_ENABLE_SIG_rainbow_Vc_cyclic + return 1; +#else + return 0; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_alg_rainbow_Vc_cyclic_compressed)) { +#ifdef OQS_ENABLE_SIG_rainbow_Vc_cyclic_compressed + return 1; +#else + return 0; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_haraka_128f_robust)) { #ifdef OQS_ENABLE_SIG_sphincs_haraka_128f_robust @@ -467,6 +530,60 @@ OQS_API OQS_SIG *OQS_SIG_new(const char *method_name) { return OQS_SIG_mqdss_31_64_new(); #else return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_alg_rainbow_Ia_classic)) { +#ifdef OQS_ENABLE_SIG_rainbow_Ia_classic + return OQS_SIG_rainbow_Ia_classic_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_alg_rainbow_Ia_cyclic)) { +#ifdef OQS_ENABLE_SIG_rainbow_Ia_cyclic + return OQS_SIG_rainbow_Ia_cyclic_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_alg_rainbow_Ia_cyclic_compressed)) { +#ifdef OQS_ENABLE_SIG_rainbow_Ia_cyclic_compressed + return OQS_SIG_rainbow_Ia_cyclic_compressed_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_alg_rainbow_IIIc_classic)) { +#ifdef OQS_ENABLE_SIG_rainbow_IIIc_classic + return OQS_SIG_rainbow_IIIc_classic_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_alg_rainbow_IIIc_cyclic)) { +#ifdef OQS_ENABLE_SIG_rainbow_IIIc_cyclic + return OQS_SIG_rainbow_IIIc_cyclic_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_alg_rainbow_IIIc_cyclic_compressed)) { +#ifdef OQS_ENABLE_SIG_rainbow_IIIc_cyclic_compressed + return OQS_SIG_rainbow_IIIc_cyclic_compressed_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_alg_rainbow_Vc_classic)) { +#ifdef OQS_ENABLE_SIG_rainbow_Vc_classic + return OQS_SIG_rainbow_Vc_classic_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_alg_rainbow_Vc_cyclic)) { +#ifdef OQS_ENABLE_SIG_rainbow_Vc_cyclic + return OQS_SIG_rainbow_Vc_cyclic_new(); +#else + return NULL; +#endif + } else if (0 == strcasecmp(method_name, OQS_SIG_alg_rainbow_Vc_cyclic_compressed)) { +#ifdef OQS_ENABLE_SIG_rainbow_Vc_cyclic_compressed + return OQS_SIG_rainbow_Vc_cyclic_compressed_new(); +#else + return NULL; #endif } else if (0 == strcasecmp(method_name, OQS_SIG_alg_sphincs_haraka_128f_robust)) { #ifdef OQS_ENABLE_SIG_sphincs_haraka_128f_robust diff --git a/src/sig/sig.h b/src/sig/sig.h index 7a2352d1ed..121a14a5f9 100644 --- a/src/sig/sig.h +++ b/src/sig/sig.h @@ -68,6 +68,24 @@ extern "C" { #define OQS_SIG_alg_mqdss_31_48 "MQDSS-31-48" /** Algorithm identifier for MQDSS-31-64 */ #define OQS_SIG_alg_mqdss_31_64 "MQDSS-31-64" +/** Algorithm identifier for Rainbow-Ia-Classic */ +#define OQS_SIG_alg_rainbow_Ia_classic "Rainbow-Ia-Classic" +/** Algorithm identifier for Rainbow-Ia-Cyclic */ +#define OQS_SIG_alg_rainbow_Ia_cyclic "Rainbow-Ia-Cyclic" +/** Algorithm identifier for Rainbow-Ia-Cyclic-Compressed */ +#define OQS_SIG_alg_rainbow_Ia_cyclic_compressed "Rainbow-Ia-Cyclic-Compressed" +/** Algorithm identifier for Rainbow-IIIc-Classic */ +#define OQS_SIG_alg_rainbow_IIIc_classic "Rainbow-IIIc-Classic" +/** Algorithm identifier for Rainbow-IIIc-Cyclic */ +#define OQS_SIG_alg_rainbow_IIIc_cyclic "Rainbow-IIIc-Cyclic" +/** Algorithm identifier for Rainbow-IIIc-Cyclic-Compressed */ +#define OQS_SIG_alg_rainbow_IIIc_cyclic_compressed "Rainbow-IIIc-Cyclic-Compressed" +/** Algorithm identifier for Rainbow-Vc-Classic */ +#define OQS_SIG_alg_rainbow_Vc_classic "Rainbow-Vc-Classic" +/** Algorithm identifier for Rainbow-Vc-Cyclic */ +#define OQS_SIG_alg_rainbow_Vc_cyclic "Rainbow-Vc-Cyclic" +/** Algorithm identifier for Rainbow-Vc-Cyclic-Compressed */ +#define OQS_SIG_alg_rainbow_Vc_cyclic_compressed "Rainbow-Vc-Cyclic-Compressed" /** Algorithm identifier for SPHINCS+-Haraka-128f-robust */ #define OQS_SIG_alg_sphincs_haraka_128f_robust "SPHINCS+-Haraka-128f-robust" /** Algorithm identifier for SPHINCS+-Haraka-128f-simple */ @@ -144,7 +162,7 @@ extern "C" { // EDIT-WHEN-ADDING-SIG ///// OQS_COPY_FROM_PQCLEAN_FRAGMENT_ALGS_LENGTH_START /** Number of algorithm identifiers above (including default). */ -#define OQS_SIG_algs_length 55 +#define OQS_SIG_algs_length 64 ///// OQS_COPY_FROM_PQCLEAN_FRAGMENT_ALGS_LENGTH_END /** @@ -326,6 +344,9 @@ OQS_API void OQS_SIG_free(OQS_SIG *sig); #ifdef OQS_ENABLE_SIG_MQDSS #include #endif /* OQS_ENABLE_SIG_MQDSS */ +#ifdef OQS_ENABLE_SIG_RAINBOW +#include +#endif /* OQS_ENABLE_SIG_RAINBOW */ #ifdef OQS_ENABLE_SIG_SPHINCS #include #endif /* OQS_ENABLE_SIG_SPHINCS */ diff --git a/tests/kat_sig.c b/tests/kat_sig.c index 825f1fcaf8..a0b659fa2f 100644 --- a/tests/kat_sig.c +++ b/tests/kat_sig.c @@ -160,6 +160,96 @@ OQS_STATUS combine_message_signature(uint8_t **signed_msg, size_t *signed_msg_le memcpy(*signed_msg, signature, signature_len); memcpy(*signed_msg + signature_len, msg, msg_len); return OQS_SUCCESS; + } else if (0 == strcmp(sig->method_name, "Rainbow-Ia-Classic")) { + // signed_msg = msg || signature + *signed_msg_len = msg_len + signature_len; + *signed_msg = malloc(*signed_msg_len); + if (*signed_msg == NULL) { + return OQS_ERROR; + } + memcpy(*signed_msg, msg, msg_len); + memcpy(*signed_msg + msg_len, signature, signature_len); + return OQS_SUCCESS; + } else if (0 == strcmp(sig->method_name, "Rainbow-Ia-Cyclic")) { + // signed_msg = msg || signature + *signed_msg_len = msg_len + signature_len; + *signed_msg = malloc(*signed_msg_len); + if (*signed_msg == NULL) { + return OQS_ERROR; + } + memcpy(*signed_msg, msg, msg_len); + memcpy(*signed_msg + msg_len, signature, signature_len); + return OQS_SUCCESS; + } else if (0 == strcmp(sig->method_name, "Rainbow-Ia-Cyclic-Compressed")) { + // signed_msg = msg || signature + *signed_msg_len = msg_len + signature_len; + *signed_msg = malloc(*signed_msg_len); + if (*signed_msg == NULL) { + return OQS_ERROR; + } + memcpy(*signed_msg, msg, msg_len); + memcpy(*signed_msg + msg_len, signature, signature_len); + return OQS_SUCCESS; + } else if (0 == strcmp(sig->method_name, "Rainbow-IIIc-Classic")) { + // signed_msg = msg || signature + *signed_msg_len = msg_len + signature_len; + *signed_msg = malloc(*signed_msg_len); + if (*signed_msg == NULL) { + return OQS_ERROR; + } + memcpy(*signed_msg, msg, msg_len); + memcpy(*signed_msg + msg_len, signature, signature_len); + return OQS_SUCCESS; + } else if (0 == strcmp(sig->method_name, "Rainbow-IIIc-Cyclic")) { + // signed_msg = msg || signature + *signed_msg_len = msg_len + signature_len; + *signed_msg = malloc(*signed_msg_len); + if (*signed_msg == NULL) { + return OQS_ERROR; + } + memcpy(*signed_msg, msg, msg_len); + memcpy(*signed_msg + msg_len, signature, signature_len); + return OQS_SUCCESS; + } else if (0 == strcmp(sig->method_name, "Rainbow-IIIc-Cyclic-Compressed")) { + // signed_msg = msg || signature + *signed_msg_len = msg_len + signature_len; + *signed_msg = malloc(*signed_msg_len); + if (*signed_msg == NULL) { + return OQS_ERROR; + } + memcpy(*signed_msg, msg, msg_len); + memcpy(*signed_msg + msg_len, signature, signature_len); + return OQS_SUCCESS; + } else if (0 == strcmp(sig->method_name, "Rainbow-Vc-Classic")) { + // signed_msg = msg || signature + *signed_msg_len = msg_len + signature_len; + *signed_msg = malloc(*signed_msg_len); + if (*signed_msg == NULL) { + return OQS_ERROR; + } + memcpy(*signed_msg, msg, msg_len); + memcpy(*signed_msg + msg_len, signature, signature_len); + return OQS_SUCCESS; + } else if (0 == strcmp(sig->method_name, "Rainbow-Vc-Cyclic")) { + // signed_msg = msg || signature + *signed_msg_len = msg_len + signature_len; + *signed_msg = malloc(*signed_msg_len); + if (*signed_msg == NULL) { + return OQS_ERROR; + } + memcpy(*signed_msg, msg, msg_len); + memcpy(*signed_msg + msg_len, signature, signature_len); + return OQS_SUCCESS; + } else if (0 == strcmp(sig->method_name, "Rainbow-Vc-Cyclic-Compressed")) { + // signed_msg = msg || signature + *signed_msg_len = msg_len + signature_len; + *signed_msg = malloc(*signed_msg_len); + if (*signed_msg == NULL) { + return OQS_ERROR; + } + memcpy(*signed_msg, msg, msg_len); + memcpy(*signed_msg + msg_len, signature, signature_len); + return OQS_SUCCESS; } else if (0 == strcmp(sig->method_name, "SPHINCS+-Haraka-128f-robust")) { // signed_msg = signature || msg *signed_msg_len = signature_len + msg_len;