From cb0e8367c68a914b6cb0e4ca9d03fc14c6ce134f Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Mon, 3 Jun 2019 17:58:59 +0200 Subject: [PATCH] initial rainbow version. still with preprocessor conditionals --- crypto_sign/rainbowIa-classic/META.yml | 17 + crypto_sign/rainbowIa-classic/clean/LICENSE | 1 + crypto_sign/rainbowIa-classic/clean/Makefile | 20 + .../clean/Makefile.Microsoft_nmake | 19 + crypto_sign/rainbowIa-classic/clean/api.h | 62 +++ crypto_sign/rainbowIa-classic/clean/blas.h | 23 ++ .../rainbowIa-classic/clean/blas_comm.c | 276 +++++++++++++ .../rainbowIa-classic/clean/blas_comm.h | 210 ++++++++++ .../rainbowIa-classic/clean/blas_u32.h | 175 +++++++++ crypto_sign/rainbowIa-classic/clean/gf16.h | 262 +++++++++++++ .../rainbowIa-classic/clean/hash_len_config.h | 14 + .../clean/parallel_matrix_op.c | 349 +++++++++++++++++ .../clean/parallel_matrix_op.h | 316 +++++++++++++++ crypto_sign/rainbowIa-classic/clean/rainbow.c | 195 ++++++++++ crypto_sign/rainbowIa-classic/clean/rainbow.h | 64 +++ .../rainbowIa-classic/clean/rainbow_blas.h | 57 +++ .../rainbowIa-classic/clean/rainbow_config.h | 100 +++++ .../rainbowIa-classic/clean/rainbow_keypair.c | 267 +++++++++++++ .../rainbowIa-classic/clean/rainbow_keypair.h | 148 +++++++ .../clean/rainbow_keypair_computation.c | 367 ++++++++++++++++++ .../clean/rainbow_keypair_computation.h | 79 ++++ crypto_sign/rainbowIa-classic/clean/sign.c | 150 +++++++ .../rainbowIa-classic/clean/utils_hash.c | 65 ++++ .../rainbowIa-classic/clean/utils_hash.h | 16 + .../rainbowIa-classic/clean/utils_prng.c | 96 +++++ .../rainbowIa-classic/clean/utils_prng.h | 22 ++ 26 files changed, 3370 insertions(+) create mode 100644 crypto_sign/rainbowIa-classic/META.yml create mode 100644 crypto_sign/rainbowIa-classic/clean/LICENSE create mode 100644 crypto_sign/rainbowIa-classic/clean/Makefile create mode 100644 crypto_sign/rainbowIa-classic/clean/Makefile.Microsoft_nmake create mode 100644 crypto_sign/rainbowIa-classic/clean/api.h create mode 100644 crypto_sign/rainbowIa-classic/clean/blas.h create mode 100644 crypto_sign/rainbowIa-classic/clean/blas_comm.c create mode 100644 crypto_sign/rainbowIa-classic/clean/blas_comm.h create mode 100644 crypto_sign/rainbowIa-classic/clean/blas_u32.h create mode 100644 crypto_sign/rainbowIa-classic/clean/gf16.h create mode 100644 crypto_sign/rainbowIa-classic/clean/hash_len_config.h create mode 100644 crypto_sign/rainbowIa-classic/clean/parallel_matrix_op.c create mode 100644 crypto_sign/rainbowIa-classic/clean/parallel_matrix_op.h create mode 100644 crypto_sign/rainbowIa-classic/clean/rainbow.c create mode 100644 crypto_sign/rainbowIa-classic/clean/rainbow.h create mode 100644 crypto_sign/rainbowIa-classic/clean/rainbow_blas.h create mode 100644 crypto_sign/rainbowIa-classic/clean/rainbow_config.h create mode 100644 crypto_sign/rainbowIa-classic/clean/rainbow_keypair.c create mode 100644 crypto_sign/rainbowIa-classic/clean/rainbow_keypair.h create mode 100644 crypto_sign/rainbowIa-classic/clean/rainbow_keypair_computation.c create mode 100644 crypto_sign/rainbowIa-classic/clean/rainbow_keypair_computation.h create mode 100644 crypto_sign/rainbowIa-classic/clean/sign.c create mode 100644 crypto_sign/rainbowIa-classic/clean/utils_hash.c create mode 100644 crypto_sign/rainbowIa-classic/clean/utils_hash.h create mode 100644 crypto_sign/rainbowIa-classic/clean/utils_prng.c create mode 100644 crypto_sign/rainbowIa-classic/clean/utils_prng.h diff --git a/crypto_sign/rainbowIa-classic/META.yml b/crypto_sign/rainbowIa-classic/META.yml new file mode 100644 index 00000000..928b1c2c --- /dev/null +++ b/crypto_sign/rainbowIa-classic/META.yml @@ -0,0 +1,17 @@ +name: Rainbow-Ia-classic +type: signature +claimed-nist-level: 1 +length-public-key: 148992 +length-secret-key: 92960 +length-signature: 64 +nistkat-sha256: b75c6fcda2100e2f6f56e9b97c4cbdda4b533116ab217f24f12e08788eb37fd0 +testvectors-sha256: edc48db3f93a66c0aa497fbbdba0bad173e3ab9cd0e3f651004b3e94d2187b75 +principal-submitter: Jintai Ding +auxiliary-submitters: + - Ming-Shing Chen + - Albrecht Petzoldt + - Dieter Schmidt + - Bo-Yin Yang +implementations: + - name: clean + version: https://csrc.nist.gov/CSRC/media/Projects/Post-Quantum-Cryptography/documents/round-2/submissions/Rainbow-Round2.zip diff --git a/crypto_sign/rainbowIa-classic/clean/LICENSE b/crypto_sign/rainbowIa-classic/clean/LICENSE new file mode 100644 index 00000000..dd6d86a4 --- /dev/null +++ b/crypto_sign/rainbowIa-classic/clean/LICENSE @@ -0,0 +1 @@ +XXX diff --git a/crypto_sign/rainbowIa-classic/clean/Makefile b/crypto_sign/rainbowIa-classic/clean/Makefile new file mode 100644 index 00000000..28ff0036 --- /dev/null +++ b/crypto_sign/rainbowIa-classic/clean/Makefile @@ -0,0 +1,20 @@ +# This Makefile can be used with GNU Make or BSD Make + +LIB=librainbowIa-classic_clean.a + +HEADERS = api.h blas_comm.h blas.h blas_u32.h gf16.h hash_len_config.h parallel_matrix_op.h rainbow_blas.h rainbow_config.h rainbow.h rainbow_keypair_computation.h rainbow_keypair.h utils_hash.h utils_prng.h +OBJECTS = blas_comm.o parallel_matrix_op.o rainbow.o rainbow_keypair.o rainbow_keypair_computation.o sign.o utils_hash.o utils_prng.o + +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) + +all: $(LIB) + +%.o: %.c $(HEADERS) + $(CC) $(CFLAGS) -c -o $@ $< + +$(LIB): $(OBJECTS) + $(AR) -r $@ $(OBJECTS) + +clean: + $(RM) $(OBJECTS) + $(RM) $(LIB) diff --git a/crypto_sign/rainbowIa-classic/clean/Makefile.Microsoft_nmake b/crypto_sign/rainbowIa-classic/clean/Makefile.Microsoft_nmake new file mode 100644 index 00000000..2f44877e --- /dev/null +++ b/crypto_sign/rainbowIa-classic/clean/Makefile.Microsoft_nmake @@ -0,0 +1,19 @@ +# This Makefile can be used with Microsoft Visual Studio's nmake using the command: +# nmake /f Makefile.Microsoft_nmake + +LIBRARY=librainbowIa-classic_clean.lib +OBJECTS = blas_comm.obj parallel_matrix_op.obj rainbow.obj rainbow_keypair.obj rainbow_keypair_computation.obj sign.obj utils_hash.obj utils_prng.obj + +CFLAGS=/nologo /I ..\..\..\common /W4 /WX + +all: $(LIBRARY) + +# Make sure objects are recompiled if headers change. +$(OBJECTS): *.h + +$(LIBRARY): $(OBJECTS) + LIB.EXE /NOLOGO /WX /OUT:$@ $** + +clean: + -DEL $(OBJECTS) + -DEL $(LIBRARY) diff --git a/crypto_sign/rainbowIa-classic/clean/api.h b/crypto_sign/rainbowIa-classic/clean/api.h new file mode 100644 index 00000000..c47a5ff5 --- /dev/null +++ b/crypto_sign/rainbowIa-classic/clean/api.h @@ -0,0 +1,62 @@ +#ifndef PQCLEAN_RAINBOWIACLASSIC_CLEAN_API_H +#define PQCLEAN_RAINBOWIACLASSIC_CLEAN_API_H + +#include +#include + +#define _RAINBOW_CLASSIC +//#define _RAINBOW_CYCLIC +//#define _RAINBOW_CYCLIC_COMPRESSED + +#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" + +//TODO: remove this after creating the other parameter sets + +//#if defined _RAINBOW_CLASSIC +// +//#define PQCLEAN_RAINBOWIACLASSIC_CLEAN_CRYPTO_SECRETKEYBYTES sizeof(sk_t) +//#define PQCLEAN_RAINBOWIACLASSIC_CLEAN_CRYPTO_PUBLICKEYBYTES sizeof(pk_t) +// +//#elif defined _RAINBOW_CYCLIC +// +//#define CRYPTO_SECRETKEYBYTES sizeof(sk_t) +//#define CRYPTO_PUBLICKEYBYTES sizeof(cpk_t) +// +//#elif defined _RAINBOW_CYCLIC_COMPRESSED +// +//#define CRYPTO_SECRETKEYBYTES sizeof(csk_t) +//#define CRYPTO_PUBLICKEYBYTES sizeof(cpk_t) +// +//#else +//error here +//#endif +// +// +//#define PQCLEAN_RAINBOWIACLASSIC_CLEAN_CRYPTO_BYTES _SIGNATURE_BYTE +// +//#define PQCLEAN_RAINBOWIACLASSIC_CLEAN_CRYPTO_ALGNAME _S_NAME _SUFFIX + +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/crypto_sign/rainbowIa-classic/clean/blas.h b/crypto_sign/rainbowIa-classic/clean/blas.h new file mode 100644 index 00000000..c54a9269 --- /dev/null +++ b/crypto_sign/rainbowIa-classic/clean/blas.h @@ -0,0 +1,23 @@ +/// @file blas.h +/// @brief Defining the implementations for linear algebra functions depending on the machine architecture. +/// + +#ifndef _BLAS_H_ +#define _BLAS_H_ + +#include "blas_comm.h" +#include "blas_u32.h" + +#define gf16v_mul_scalar _gf16v_mul_scalar_u32 +#define gf16v_madd _gf16v_madd_u32 + +#define gf256v_add _gf256v_add_u32 +#define gf256v_mul_scalar _gf256v_mul_scalar_u32 +#define gf256v_madd _gf256v_madd_u32 + +#define gf256v_predicated_add _gf256v_predicated_add_u32 +#define gf16v_dot _gf16v_dot_u32 + + +#endif // _BLAS_H_ + diff --git a/crypto_sign/rainbowIa-classic/clean/blas_comm.c b/crypto_sign/rainbowIa-classic/clean/blas_comm.c new file mode 100644 index 00000000..8d45ba95 --- /dev/null +++ b/crypto_sign/rainbowIa-classic/clean/blas_comm.c @@ -0,0 +1,276 @@ +/// @file blas_comm.c +/// @brief The standard implementations for blas_comm.h +/// + +#include "blas_comm.h" +#include "blas.h" + +#include // FIXME(js): don't use assert() and don't deal with NDEBUG +#include +#include + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_set_zero(uint8_t *b, unsigned _num_byte) { + gf256v_add(b, b, _num_byte); +} + +unsigned PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_is_zero(const uint8_t *a, unsigned _num_byte) { + uint8_t r = 0; + while ( _num_byte-- ) { + r |= a[0]; + a++; + } + return (0 == r); +} + +///////////////// multiplications //////////////////////////////// + +/// polynomial multplication +/// School boook + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_polymul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned _num) { + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_set_zero(c, _num * 2 - 1); + for (unsigned i = 0; i < _num; i++) { + gf256v_madd(c + i, a, b[i], _num); + } +} + +/////////// matrix-vector + +static void gf16mat_prod_ref(uint8_t *c, const uint8_t *matA, unsigned n_A_vec_byte, unsigned n_A_width, const uint8_t *b) { + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_set_zero(c, n_A_vec_byte); + for (unsigned i = 0; i < n_A_width; i++) { + uint8_t bb = gf16v_get_ele(b, i); + gf16v_madd(c, matA, bb, n_A_vec_byte); + matA += n_A_vec_byte; + } +} + +static void gf256mat_prod_ref(uint8_t *c, const uint8_t *matA, unsigned n_A_vec_byte, unsigned n_A_width, const uint8_t *b) { + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_set_zero(c, n_A_vec_byte); + for (unsigned i = 0; i < n_A_width; i++) { + gf256v_madd(c, matA, b[i], n_A_vec_byte); + matA += n_A_vec_byte; + } +} + + +/////////// matrix-matrix + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16mat_mul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned len_vec) { + unsigned n_vec_byte = (len_vec + 1) / 2; + for (unsigned 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 i = 0; i < len_vec; i++) { + uint8_t bb = gf16v_get_ele(bk, i); + gf16v_madd(c, a + n_vec_byte * i, bb, n_vec_byte); + } + c += n_vec_byte; + } +} + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256mat_mul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned len_vec) { + unsigned n_vec_byte = len_vec; + for (unsigned 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 i = 0; i < len_vec; i++) { + gf256v_madd(c, a + n_vec_byte * i, bk[i], n_vec_byte); + } + c += n_vec_byte; + } +} + +///////////////// algorithms: gaussian elim ////////////////// + +static +unsigned gf16mat_gauss_elim_ref(uint8_t *mat, unsigned h, unsigned w) { + /// assert( 0==(w&1) ); w must be even !!! + unsigned n_w_byte = (w + 1) / 2; + unsigned r8 = 1; + for (unsigned i = 0; i < h; i++) { + unsigned offset_byte = i >> 1; + uint8_t *ai = mat + n_w_byte * i; + for (unsigned j = i + 1; j < h; j++) { + uint8_t *aj = mat + n_w_byte * j; + gf256v_predicated_add(ai + offset_byte, !gf16_is_nonzero(gf16v_get_ele(ai, i)), aj + offset_byte, n_w_byte - offset_byte); + } + uint8_t pivot = gf16v_get_ele(ai, i); + r8 &= gf16_is_nonzero(pivot); + pivot = gf16_inv(pivot); + offset_byte = (i + 1) >> 1; + gf16v_mul_scalar(ai + offset_byte, pivot, n_w_byte - offset_byte); + for (unsigned j = 0; j < h; j++) { + if (i == j) { + continue; + } + uint8_t *aj = mat + n_w_byte * j; + gf16v_madd(aj + offset_byte, ai + offset_byte, gf16v_get_ele(aj, i), n_w_byte - offset_byte); + } + } + return r8; +} + +static +unsigned gf16mat_solve_linear_eq_ref(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned n) { + assert(64 >= n); + uint8_t mat[64 * 33]; + unsigned n_byte = (n + 1) >> 1; + for (unsigned 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] = gf16v_get_ele(c_terms, i); + } + unsigned r8 = PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16mat_gauss_elim(mat, n, n + 2); /// XXX: this function is ``defined'' in blas.h + for (unsigned i = 0; i < n; i++) { + gf16v_set_ele(sol, i, mat[i * (n_byte + 1) + n_byte]); + } + return r8; +} + +static inline void gf16mat_submat(uint8_t *mat2, unsigned w2, unsigned st, const uint8_t *mat, unsigned w, unsigned h) { + unsigned n_byte_w1 = (w + 1) / 2; + unsigned n_byte_w2 = (w2 + 1) / 2; + unsigned st_2 = st / 2; + for (unsigned i = 0; i < h; i++) { + for (unsigned j = 0; j < n_byte_w2; j++) { + mat2[i * n_byte_w2 + j] = mat[i * n_byte_w1 + st_2 + j]; + } + } +} + +unsigned PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16mat_inv(uint8_t *inv_a, const uint8_t *a, unsigned H, uint8_t *buffer) { + unsigned n_w_byte = (H + 1) / 2; + + uint8_t *aa = buffer; + for (unsigned 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); + gf256v_add(ai, a + i * n_w_byte, n_w_byte); + gf16v_set_ele(ai + n_w_byte, i, 1); + } + unsigned r8 = PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16mat_gauss_elim(aa, H, 2 * H); /// XXX: would 2*H fail if H is odd ??? + gf16mat_submat(inv_a, H, H, aa, 2 * H, H); + return r8; +} + + +///////////////////////////////////////////////// + +static +unsigned gf256mat_gauss_elim_ref( uint8_t *mat, unsigned h, unsigned w ) { + unsigned r8 = 1; + + for (unsigned i = 0; i < h; i++) { + uint8_t *ai = mat + w * i; + unsigned skip_len_align4 = i & ((unsigned)~0x3); + + for (unsigned j = i + 1; j < h; j++) { + uint8_t *aj = mat + w * j; +// gf256v_predicated_add( ai + i , !gf256_is_nonzero(ai[i]) , aj + i , w-i ); + gf256v_predicated_add( ai + skip_len_align4, !gf256_is_nonzero(ai[i]), aj + skip_len_align4, w - skip_len_align4 ); + } + r8 &= gf256_is_nonzero(ai[i]); + uint8_t pivot = ai[i]; + pivot = gf256_inv( pivot ); +// gf256v_mul_scalar( ai + (i+1) , pivot , w - (i+1) ); + gf256v_mul_scalar( ai + skip_len_align4, pivot, w - skip_len_align4 ); + for (unsigned j = 0; j < h; j++) { + if (i == j) { + continue; + } + uint8_t *aj = mat + w * j; +// gf256v_madd( aj + (i+1) , ai + (i+1) , aj[i] , w - (i+1) ); + gf256v_madd( aj + skip_len_align4, ai + skip_len_align4, aj[i], w - skip_len_align4 ); + } + } + + return r8; +} + +static +unsigned gf256mat_solve_linear_eq_ref( uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned n ) { + assert( 63 >= n ); + uint8_t mat[ 64 * 64 ]; + for (unsigned i = 0; i < n; i++) { + memcpy( mat + i * (n + 1), inp_mat + i * n, n ); + mat[i * (n + 1) + n] = c_terms[i]; + } + unsigned r8 = PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256mat_gauss_elim( mat, n, n + 1 ); /// XXX: this function is ``defined'' in blas.h + for (unsigned i = 0; i < n; i++) { + sol[i] = mat[i * (n + 1) + n]; + } + return r8; +} + + + +static inline +void gf256mat_submat( uint8_t *mat2, unsigned w2, unsigned st, const uint8_t *mat, unsigned w, unsigned h ) { + for (unsigned i = 0; i < h; i++) { + for (unsigned j = 0; j < w2; j++) { + mat2[i * w2 + j] = mat[i * w + st + j]; + } + } +} + + +unsigned PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256mat_inv( uint8_t *inv_a, const uint8_t *a, unsigned H, uint8_t *buffer ) { + uint8_t *aa = buffer; + for (unsigned i = 0; i < H; i++) { + uint8_t *ai = aa + i * 2 * H; + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_set_zero( ai, 2 * H ); + gf256v_add( ai, a + i * H, H ); + ai[H + i] = 1; + } + unsigned r8 = PQCLEAN_RAINBOWIACLASSIC_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 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 +#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_RAINBOWIACLASSIC_CLEAN_gf16mat_prod(uint8_t *c, const uint8_t *matA, unsigned n_A_vec_byte, unsigned n_A_width, const uint8_t *b) { + gf16mat_prod_impl( c, matA, n_A_vec_byte, n_A_width, b); +} + + +unsigned PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16mat_gauss_elim(uint8_t *mat, unsigned h, unsigned w) { + return gf16mat_gauss_elim_impl( mat, h, w); +} + +unsigned PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16mat_solve_linear_eq( uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned n ) { + return gf16mat_solve_linear_eq_impl( sol, inp_mat, c_terms, n ); +} + + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256mat_prod(uint8_t *c, const uint8_t *matA, unsigned n_A_vec_byte, unsigned n_A_width, const uint8_t *b) { + gf256mat_prod_impl( c, matA, n_A_vec_byte, n_A_width, b); +} + +unsigned PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256mat_gauss_elim( uint8_t *mat, unsigned h, unsigned w ) { + return gf256mat_gauss_elim_impl( mat, h, w ); +} + + +unsigned PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256mat_solve_linear_eq( uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned n ) { + return gf256mat_solve_linear_eq_impl( sol, inp_mat, c_terms, n ); +} diff --git a/crypto_sign/rainbowIa-classic/clean/blas_comm.h b/crypto_sign/rainbowIa-classic/clean/blas_comm.h new file mode 100644 index 00000000..5b779430 --- /dev/null +++ b/crypto_sign/rainbowIa-classic/clean/blas_comm.h @@ -0,0 +1,210 @@ +/// @file blas_comm.h +/// @brief Common functions for linear algebra. +/// +#ifndef _BLAS_COMM_H_ +#define _BLAS_COMM_H_ + +#include + + +/// @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. +/// +static inline uint8_t gf16v_get_ele(const uint8_t *a, unsigned i) { + uint8_t r = a[i >> 1]; + uint8_t r0 = r & 0xf; + uint8_t r1 = r >> 4; + uint8_t m = (uint8_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 inline uint8_t gf16v_set_ele(uint8_t *a, unsigned i, uint8_t v) { + uint8_t m = (uint8_t) (0xf ^ (-(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; +} + + +/// @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. +/// +static inline uint8_t gf256v_get_ele(const uint8_t *a, unsigned i) { + return a[i]; +} + + +/// @brief set an element for a GF(256) 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 inline uint8_t gf256v_set_ele(uint8_t *a, unsigned i, uint8_t v) { + a[i] = v; + return v; +} + + +///////////////////////////////////// + + +/// @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 _num_byte); + + +/// @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 PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_is_zero(const uint8_t *a, unsigned _num_byte); + + + +///////////////// Section: multiplications //////////////////////////////// + + +/// @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_RAINBOWIACLASSIC_CLEAN_gf256v_polymul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned _num); + + +/// @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 n_A_vec_byte, unsigned n_A_width, const uint8_t *b); + + +/// @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_RAINBOWIACLASSIC_CLEAN_gf256mat_prod(uint8_t *c, const uint8_t *matA, unsigned n_A_vec_byte, unsigned n_A_width, const uint8_t *b); + + +/// @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 len_vec); + + +/// @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_RAINBOWIACLASSIC_CLEAN_gf256mat_mul(uint8_t *c, const uint8_t *a, const uint8_t *b, unsigned len_vec); + + + + +///////////////// algorithms: gaussian elim ////////////////// + + +/// @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 PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16mat_gauss_elim(uint8_t *mat, unsigned h, unsigned 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 PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16mat_solve_linear_eq(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned n); + + +/// @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 PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256mat_gauss_elim(uint8_t *mat, unsigned h, unsigned 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 PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256mat_solve_linear_eq(uint8_t *sol, const uint8_t *inp_mat, const uint8_t *c_terms, unsigned n); + + + +//////////////// Section: inversion for matrices ////////////////////////// + + +/// @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 PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf16mat_inv(uint8_t *inv_a, const uint8_t *a, unsigned H, uint8_t *buffer); + + +/// @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 PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256mat_inv(uint8_t *inv_a, const uint8_t *a, unsigned H, uint8_t *buffer); + +#endif // _BLAS_COMM_H_ + diff --git a/crypto_sign/rainbowIa-classic/clean/blas_u32.h b/crypto_sign/rainbowIa-classic/clean/blas_u32.h new file mode 100644 index 00000000..81ea3411 --- /dev/null +++ b/crypto_sign/rainbowIa-classic/clean/blas_u32.h @@ -0,0 +1,175 @@ +/// @file blas_u32.h +/// @brief Inlined functions for implementing basic linear algebra functions for uint32 arch. +/// + +#ifndef _BLAS_U32_H_ +#define _BLAS_U32_H_ + +#include "gf16.h" + +#include + +static inline void _gf256v_add_u32(uint8_t *accu_b, const uint8_t *a, unsigned _num_byte) { + unsigned n_u32 = _num_byte >> 2; + uint32_t *b_u32 = (uint32_t *) accu_b; + const uint32_t *a_u32 = (const uint32_t *) a; + for (unsigned i = 0; i < n_u32; i++) { + b_u32[i] ^= a_u32[i]; + } + + a += (n_u32 << 2); + accu_b += (n_u32 << 2); + unsigned rem = _num_byte & 3; + for (unsigned i = 0; i < rem; i++) { + accu_b[i] ^= a[i]; + } +} + +static inline void _gf256v_predicated_add_u32(uint8_t *accu_b, uint8_t predicate, const uint8_t *a, unsigned _num_byte) { + uint32_t pr_u32 = ((uint32_t) 0) - ((uint32_t) predicate); + uint8_t pr_u8 = pr_u32 & 0xff; + + unsigned n_u32 = _num_byte >> 2; + uint32_t *b_u32 = (uint32_t *) accu_b; + const uint32_t *a_u32 = (const uint32_t *) a; + for (unsigned i = 0; i < n_u32; i++) { + b_u32[i] ^= (a_u32[i] & pr_u32); + } + + a += (n_u32 << 2); + accu_b += (n_u32 << 2); + unsigned rem = _num_byte & 3; + for (unsigned i = 0; i < rem; i++) { + accu_b[i] ^= (a[i] & pr_u8); + } +} + + +static inline void _gf16v_mul_scalar_u32(uint8_t *a, uint8_t gf16_b, unsigned _num_byte) { + unsigned n_u32 = _num_byte >> 2; + uint32_t *a_u32 = (uint32_t *) a; + for (unsigned i = 0; i < n_u32; i++) { + a_u32[i] = gf16v_mul_u32(a_u32[i], gf16_b); + } + + union tmp_32 { + uint8_t u8[4]; + uint32_t u32; + } t; + a += (n_u32 << 2); + unsigned rem = _num_byte & 3; + for (unsigned i = 0; i < rem; i++) { + t.u8[i] = a[i]; + } + t.u32 = gf16v_mul_u32(t.u32, gf16_b); + for (unsigned i = 0; i < rem; i++) { + a[i] = t.u8[i]; + } +} + +static inline void _gf256v_mul_scalar_u32(uint8_t *a, uint8_t b, unsigned _num_byte) { + unsigned n_u32 = _num_byte >> 2; + uint32_t *a_u32 = (uint32_t *) a; + for (unsigned i = 0; i < n_u32; i++) { + a_u32[i] = gf256v_mul_u32(a_u32[i], b); + } + + union tmp_32 { + uint8_t u8[4]; + uint32_t u32; + } t; + a += (n_u32 << 2); + unsigned rem = _num_byte & 3; + for (unsigned i = 0; i < rem; i++) { + t.u8[i] = a[i]; + } + t.u32 = gf256v_mul_u32(t.u32, b); + for (unsigned i = 0; i < rem; i++) { + a[i] = t.u8[i]; + } +} + + +static inline void _gf16v_madd_u32(uint8_t *accu_c, const uint8_t *a, uint8_t gf16_b, unsigned _num_byte) { + unsigned n_u32 = _num_byte >> 2; + uint32_t *c_u32 = (uint32_t *) accu_c; + const uint32_t *a_u32 = (const uint32_t *) a; + for (unsigned i = 0; i < n_u32; i++) { + c_u32[i] ^= gf16v_mul_u32(a_u32[i], gf16_b); + } + + // TODO: this will certainly not work on Big Endian + union tmp_32 { + uint8_t u8[4]; + uint32_t u32; + } t; + t.u32 = 0; + accu_c += (n_u32 << 2); + a += (n_u32 << 2); + unsigned rem = _num_byte & 3; + for (unsigned i = 0; i < rem; i++) { + t.u8[i] = a[i]; + } + t.u32 = gf16v_mul_u32(t.u32, gf16_b); + for (unsigned i = 0; i < rem; i++) { + accu_c[i] ^= t.u8[i]; + } +} + +static inline void _gf256v_madd_u32(uint8_t *accu_c, const uint8_t *a, uint8_t gf256_b, unsigned _num_byte) { + unsigned n_u32 = _num_byte >> 2; + uint32_t *c_u32 = (uint32_t *) accu_c; + const uint32_t *a_u32 = (const uint32_t *) a; + for (unsigned i = 0; i < n_u32; i++) { + c_u32[i] ^= gf256v_mul_u32(a_u32[i], gf256_b); + } + + // TODO: this will certainly not work on Big Endian + union tmp_32 { + uint8_t u8[4]; + uint32_t u32; + } t; + t.u32 = 0; + accu_c += (n_u32 << 2); + a += (n_u32 << 2); + unsigned rem = _num_byte & 3; + for (unsigned i = 0; i < rem; i++) { + t.u8[i] = a[i]; + } + t.u32 = gf256v_mul_u32(t.u32, gf256_b); + for (unsigned i = 0; i < rem; i++) { + accu_c[i] ^= t.u8[i]; + } +} + + +static inline uint8_t _gf16v_dot_u32(const uint8_t *a, const uint8_t *b, unsigned _num_byte) { + unsigned n_u32 = _num_byte >> 2; + const uint32_t *a_u32 = (const uint32_t *) a; + const uint32_t *b_u32 = (const uint32_t *) b; + uint32_t r = 0; + for (unsigned i = 0; i < n_u32; i++) { + r ^= gf16v_mul_u32_u32(a_u32[i], b_u32[i]); + } + + unsigned rem = _num_byte & 3; + if (rem) { + union tmp_32 { + uint8_t u8[4]; + uint32_t u32; + } ta, tb; + ta.u32 = 0; + tb.u32 = 0; + for (unsigned i = 0; i < rem; i++) { + ta.u8[i] = a[(n_u32 << 2) + i]; + } + for (unsigned i = 0; i < rem; i++) { + tb.u8[i] = b[(n_u32 << 2) + i]; + } + r ^= gf16v_mul_u32_u32(ta.u32, tb.u32); + } + return gf16v_reduce_u32(r); +} + +#endif // _BLAS_U32_H_ + diff --git a/crypto_sign/rainbowIa-classic/clean/gf16.h b/crypto_sign/rainbowIa-classic/clean/gf16.h new file mode 100644 index 00000000..ace634d8 --- /dev/null +++ b/crypto_sign/rainbowIa-classic/clean/gf16.h @@ -0,0 +1,262 @@ +/// @file gf16.h +/// @brief Library for arithmetics in GF(16) and GF(256) +/// + +#ifndef _GF16_H_ +#define _GF16_H_ + +#include + +// 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_3(uint8_t a) { + uint8_t msk = (uint8_t) (a - 2) >> 1; + return (uint8_t)((msk & (a * 3)) | ((~msk) & (a - 1))); +} + +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); +} + +static inline uint8_t gf4_inv(uint8_t a) { + return a ^ (a >> 1); +} + +static inline uint32_t gf4v_mul_2_u32(uint32_t a) { + uint32_t bit0 = a & 0x55555555; + uint32_t bit1 = a & 0xaaaaaaaa; + return (bit0 << 1) ^ bit1 ^ (bit1 >> 1); +} + +static inline uint32_t gf4v_mul_3_u32(uint32_t a) { + uint32_t bit0 = a & 0x55555555; + uint32_t bit1 = a & 0xaaaaaaaa; + return (bit0 << 1) ^ bit0 ^ (bit1 >> 1); +} + +static inline uint32_t gf4v_mul_u32(uint32_t a, uint8_t b) { + uint32_t bit0_b = ((uint32_t) 0) - ((uint32_t)(b & 1)); + uint32_t bit1_b = ((uint32_t) 0) - ((uint32_t)((b >> 1) & 1)); + return (a & bit0_b) ^ (bit1_b & gf4v_mul_2_u32(a)); +} + +static inline uint32_t _gf4v_mul_u32_u32(uint32_t a0, uint32_t a1, uint32_t b0, uint32_t b1) { + uint32_t c0 = a0 & b0; + uint32_t c2 = a1 & b1; + uint32_t c1_ = (a0 ^ a1) & (b0 ^ b1); + return ((c1_ ^ c0) << 1) ^ c0 ^ c2; +} + +static inline uint32_t gf4v_mul_u32_u32(uint32_t a, uint32_t b) { + uint32_t a0 = a & 0x55555555; + uint32_t a1 = (a >> 1) & 0x55555555; + uint32_t b0 = b & 0x55555555; + uint32_t b1 = (b >> 1) & 0x55555555; + + return _gf4v_mul_u32_u32(a0, a1, b0, b1); +} + +static inline uint32_t gf4v_squ_u32(uint32_t a) { + uint32_t bit1 = a & 0xaaaaaaaa; + return a ^ (bit1 >> 1); +} + +////////////////////////////////////////////////////////////////////////////////// + +static inline uint8_t gf16_is_nonzero(uint8_t a) { + unsigned a4 = a & 0xf; + unsigned r = ((unsigned) 0) - a4; + r >>= 4; + return r & 1; +} + +// gf16 := gf4[y]/y^2+y+x +static inline uint8_t 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)); +} + +static inline uint8_t 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 = gf16_mul(a4, a2); + return gf16_mul(a8, a6); +} + +static inline uint8_t gf16_mul_4(uint8_t a) { + return (uint8_t)((((a << 2) ^ a) & (8 + 4)) ^ gf4_mul_2(a >> 2)); +} + +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)); +} + +//////////// + +// gf16 := gf4[y]/y^2+y+x + +static inline uint32_t gf16v_mul_u32(uint32_t a, uint8_t b) { + uint32_t axb0 = gf4v_mul_u32(a, b); + uint32_t axb1 = gf4v_mul_u32(a, b >> 2); + uint32_t a0b1 = (axb1 << 2) & 0xcccccccc; + uint32_t a1b1 = axb1 & 0xcccccccc; + uint32_t a1b1_2 = a1b1 >> 2; + + return axb0 ^ a0b1 ^ a1b1 ^ gf4v_mul_2_u32(a1b1_2); +} + +static inline uint32_t _gf16v_mul_u32_u32(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t b0, uint32_t b1, uint32_t b2, uint32_t b3) { + uint32_t c0 = _gf4v_mul_u32_u32(a0, a1, b0, b1); + uint32_t c1_ = _gf4v_mul_u32_u32(a0 ^ a2, a1 ^ a3, b0 ^ b2, b1 ^ b3); + + uint32_t c2_0 = a2 & b2; + uint32_t c2_2 = a3 & b3; + uint32_t c2_1_ = (a2 ^ a3) & (b2 ^ b3); + uint32_t c2_r0 = c2_0 ^ c2_2; + uint32_t c2_r1 = c2_0 ^ c2_1_; + //uint32_t c2 = c2_r0^(c2_r1<<1); + // GF(4) x2: (bit0<<1)^bit1^(bit1>>1); + return ((c1_ ^ c0) << 2) ^ c0 ^ (c2_r0 << 1) ^ c2_r1 ^ (c2_r1 << 1); +} + +static inline uint32_t gf16v_mul_u32_u32(uint32_t a, uint32_t b) { + uint32_t a0 = a & 0x11111111; + uint32_t a1 = (a >> 1) & 0x11111111; + uint32_t a2 = (a >> 2) & 0x11111111; + uint32_t a3 = (a >> 3) & 0x11111111; + uint32_t b0 = b & 0x11111111; + uint32_t b1 = (b >> 1) & 0x11111111; + uint32_t b2 = (b >> 2) & 0x11111111; + uint32_t b3 = (b >> 3) & 0x11111111; + + return _gf16v_mul_u32_u32(a0, a1, a2, a3, b0, b1, b2, b3); +} + +static inline uint8_t gf256v_reduce_u32(uint32_t a) { + // https://godbolt.org/z/7hirMb + uint16_t *aa = (uint16_t *) (&a); + uint16_t r = aa[0] ^ aa[1]; + uint8_t *rr = (uint8_t *) (&r); + return rr[0] ^ rr[1]; +} + +static inline uint8_t gf16v_reduce_u32(uint32_t a) { + uint8_t r256 = gf256v_reduce_u32(a); + return (uint8_t)((r256 & 0xf) ^ (r256 >> 4)); +} + +static inline uint32_t gf16v_squ_u32(uint32_t a) { + uint32_t a2 = gf4v_squ_u32(a); + + return a2 ^ gf4v_mul_2_u32((a2 >> 2) & 0x33333333); +} + +static inline uint32_t gf16v_mul_8_u32(uint32_t a) { + uint32_t a1 = a & 0xcccccccc; + uint32_t a0 = (a << 2) & 0xcccccccc; + return gf4v_mul_2_u32(a0 ^ a1) | gf4v_mul_3_u32(a1 >> 2); +} + +static inline uint8_t gf256_is_nonzero(uint8_t a) { + unsigned a8 = a; + unsigned r = ((unsigned) 0) - a8; + r >>= 8; + return r & 1; +} + +// gf256 := gf16[X]/X^2+X+xy +static inline uint8_t 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 = gf16_mul(a0, b0); + uint8_t a1b1 = gf16_mul(a1, b1); + uint8_t a0b1_a1b0 = 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_mul_gf16(uint8_t a, uint8_t gf16_b) { + uint8_t a0 = a & 15; + uint8_t a1 = (a >> 4); + uint8_t b0 = gf16_b & 15; + uint8_t a0b0 = gf16_mul(a0, b0); + uint8_t a1b0 = gf16_mul(a1, b0); + return (uint8_t) (a0b0 ^ (a1b0 << 4)); +} + +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)); +} + +static inline uint8_t 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 = gf256_mul(a4, a2); + uint8_t a8_4_2 = 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 = gf256_mul(a64_, a8_4_2); + uint8_t a128_ = gf256_squ(a64_2); + return gf256_mul(a2, a128_); +} + +static inline uint32_t gf256v_mul_u32(uint32_t a, uint8_t b) { + uint32_t axb0 = gf16v_mul_u32(a, b); + uint32_t axb1 = gf16v_mul_u32(a, b >> 4); + uint32_t a0b1 = (axb1 << 4) & 0xf0f0f0f0; + uint32_t a1b1 = axb1 & 0xf0f0f0f0; + uint32_t a1b1_4 = a1b1 >> 4; + + return axb0 ^ a0b1 ^ a1b1 ^ gf16v_mul_8_u32(a1b1_4); +} + +static inline uint32_t gf256v_squ_u32(uint32_t a) { + uint32_t a2 = gf16v_squ_u32(a); + uint32_t ar = (a2 >> 4) & 0x0f0f0f0f; + + return a2 ^ gf16v_mul_8_u32(ar); +} + +static inline uint32_t gf256v_mul_gf16_u32(uint32_t a, uint8_t gf16_b) { + return gf16v_mul_u32(a, gf16_b); +} + +#endif // _GF16_H_ + diff --git a/crypto_sign/rainbowIa-classic/clean/hash_len_config.h b/crypto_sign/rainbowIa-classic/clean/hash_len_config.h new file mode 100644 index 00000000..eb9da010 --- /dev/null +++ b/crypto_sign/rainbowIa-classic/clean/hash_len_config.h @@ -0,0 +1,14 @@ +/// @file hash_len_config.h +/// @brief defining the lenght of outputs of the internel hash functions. +/// + +#ifndef _HASH_LEN_CONFIG_H_ +#define _HASH_LEN_CONFIG_H_ + + +/// defining the lenght of outputs of the internel hash functions. +#ifndef _HASH_LEN +#define _HASH_LEN (32) +#endif + +#endif diff --git a/crypto_sign/rainbowIa-classic/clean/parallel_matrix_op.c b/crypto_sign/rainbowIa-classic/clean/parallel_matrix_op.c new file mode 100644 index 00000000..de26502f --- /dev/null +++ b/crypto_sign/rainbowIa-classic/clean/parallel_matrix_op.c @@ -0,0 +1,349 @@ +/// @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 "blas_comm.h" +#include "blas.h" + +#include "parallel_matrix_op.h" + + +//////////////// Section: triangle matrix <-> rectangle matrix /////////////////////////////////// + + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_UpperTrianglize( unsigned char *btriC, const unsigned char *bA, unsigned Awidth, unsigned size_batch ) { + unsigned char *runningC = btriC; + unsigned Aheight = Awidth; + for (unsigned i = 0; i < Aheight; i++) { + for (unsigned j = 0; j < i; j++) { + unsigned idx = idx_of_trimat(j, i, Aheight); + gf256v_add( btriC + idx * size_batch, bA + size_batch * (i * Awidth + j), size_batch ); + } + gf256v_add( runningC, bA + size_batch * (i * Awidth + i), size_batch * (Aheight - i) ); + runningC += size_batch * (Aheight - i); + } +} + + + + +///////////////// Section: matrix multiplications /////////////////////////////// + + + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_trimat_madd_gf16( unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned Bheight, unsigned size_Bcolvec, unsigned Bwidth, unsigned size_batch ) { + unsigned Awidth = Bheight; + unsigned Aheight = Awidth; + for (unsigned i = 0; i < Aheight; i++) { + for (unsigned j = 0; j < Bwidth; j++) { + for (unsigned k = 0; k < Bheight; k++) { + if (k < i) { + continue; + } + gf16v_madd( bC, & btriA[ (k - i)*size_batch ], gf16v_get_ele( &B[j * size_Bcolvec], k ), size_batch ); + } + bC += size_batch; + } + btriA += (Aheight - i) * size_batch; + } +} + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_trimat_madd_gf256( unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned Bheight, unsigned size_Bcolvec, unsigned Bwidth, unsigned size_batch ) { + unsigned Awidth = Bheight; + unsigned Aheight = Awidth; + for (unsigned i = 0; i < Aheight; i++) { + for (unsigned j = 0; j < Bwidth; j++) { + for (unsigned k = 0; k < Bheight; k++) { + if (k < i) { + continue; + } + gf256v_madd( bC, & btriA[ (k - i)*size_batch ], gf256v_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 Bheight, unsigned size_Bcolvec, unsigned Bwidth, unsigned size_batch ) { + unsigned Aheight = Bheight; + for (unsigned i = 0; i < Aheight; i++) { + for (unsigned j = 0; j < Bwidth; j++) { + for (unsigned k = 0; k < Bheight; k++) { + if (i < k) { + continue; + } + gf16v_madd( bC, & btriA[ size_batch * (idx_of_trimat(k, i, Aheight)) ], gf16v_get_ele( &B[j * size_Bcolvec], k ), size_batch ); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_trimatTr_madd_gf256( unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned Bheight, unsigned size_Bcolvec, unsigned Bwidth, unsigned size_batch ) { + unsigned Aheight = Bheight; + for (unsigned i = 0; i < Aheight; i++) { + for (unsigned j = 0; j < Bwidth; j++) { + for (unsigned k = 0; k < Bheight; k++) { + if (i < k) { + continue; + } + gf256v_madd( bC, & btriA[ size_batch * (idx_of_trimat(k, i, Aheight)) ], gf256v_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 Bheight, unsigned size_Bcolvec, unsigned Bwidth, unsigned size_batch ) { + unsigned Aheight = Bheight; + for (unsigned i = 0; i < Aheight; i++) { + for (unsigned j = 0; j < Bwidth; j++) { + for (unsigned k = 0; k < Bheight; k++) { + if (i == k) { + continue; + } + gf16v_madd( bC, & btriA[ size_batch * (idx_of_2trimat(i, k, Aheight)) ], gf16v_get_ele( &B[j * size_Bcolvec], k ), size_batch ); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_2trimat_madd_gf256( unsigned char *bC, const unsigned char *btriA, + const unsigned char *B, unsigned Bheight, unsigned size_Bcolvec, unsigned Bwidth, unsigned size_batch ) { + unsigned Aheight = Bheight; + for (unsigned i = 0; i < Aheight; i++) { + for (unsigned j = 0; j < Bwidth; j++) { + for (unsigned k = 0; k < Bheight; k++) { + if (i == k) { + continue; + } + gf256v_madd( bC, & btriA[ size_batch * (idx_of_2trimat(i, k, Aheight)) ], gf256v_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 Aheight, unsigned size_Acolvec, unsigned Awidth, + const unsigned char *bB, unsigned Bwidth, unsigned size_batch ) { + unsigned Atr_height = Awidth; + unsigned Atr_width = Aheight; + for (unsigned i = 0; i < Atr_height; i++) { + for (unsigned j = 0; j < Atr_width; j++) { + gf16v_madd( bC, & bB[ j * Bwidth * size_batch ], gf16v_get_ele( &A_to_tr[size_Acolvec * i], j ), size_batch * Bwidth ); + } + bC += size_batch * Bwidth; + } +} + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_matTr_madd_gf256( unsigned char *bC, const unsigned char *A_to_tr, unsigned Aheight, unsigned size_Acolvec, unsigned Awidth, + const unsigned char *bB, unsigned Bwidth, unsigned size_batch ) { + unsigned Atr_height = Awidth; + unsigned Atr_width = Aheight; + for (unsigned i = 0; i < Atr_height; i++) { + for (unsigned j = 0; j < Atr_width; j++) { + gf256v_madd( bC, & bB[ j * Bwidth * size_batch ], gf256v_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 Awidth_before_tr, + const unsigned char *B, unsigned Bheight, unsigned size_Bcolvec, unsigned Bwidth, unsigned size_batch ) { + const unsigned char *bA = bA_to_tr; + unsigned Aheight = Awidth_before_tr; + for (unsigned i = 0; i < Aheight; i++) { + for (unsigned j = 0; j < Bwidth; j++) { + for (unsigned k = 0; k < Bheight; k++) { + gf16v_madd( bC, & bA[ size_batch * (i + k * Aheight) ], gf16v_get_ele( &B[j * size_Bcolvec], k ), size_batch ); + } + bC += size_batch; + } + } +} + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_bmatTr_madd_gf256( unsigned char *bC, const unsigned char *bA_to_tr, unsigned Awidth_before_tr, + const unsigned char *B, unsigned Bheight, unsigned size_Bcolvec, unsigned Bwidth, unsigned size_batch ) { + const unsigned char *bA = bA_to_tr; + unsigned Aheight = Awidth_before_tr; + for (unsigned i = 0; i < Aheight; i++) { + for (unsigned j = 0; j < Bwidth; j++) { + for (unsigned k = 0; k < Bheight; k++) { + gf256v_madd( bC, & bA[ size_batch * (i + k * Aheight) ], gf256v_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 Aheight, + const unsigned char *B, unsigned Bheight, unsigned size_Bcolvec, unsigned Bwidth, unsigned size_batch ) { + unsigned Awidth = Bheight; + for (unsigned i = 0; i < Aheight; i++) { + for (unsigned j = 0; j < Bwidth; j++) { + for (unsigned k = 0; k < Bheight; k++) { + gf16v_madd( bC, & bA[ k * size_batch ], gf16v_get_ele( &B[j * size_Bcolvec], k ), size_batch ); + } + bC += size_batch; + } + bA += (Awidth) * size_batch; + } +} + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_mat_madd_gf256( unsigned char *bC, const unsigned char *bA, unsigned Aheight, + const unsigned char *B, unsigned Bheight, unsigned size_Bcolvec, unsigned Bwidth, unsigned size_batch ) { + unsigned Awidth = Bheight; + for (unsigned i = 0; i < Aheight; i++) { + for (unsigned j = 0; j < Bwidth; j++) { + for (unsigned k = 0; k < Bheight; k++) { + gf256v_madd( bC, & bA[ k * size_batch ], gf256v_get_ele( &B[j * size_Bcolvec], k ), size_batch ); + } + bC += size_batch; + } + bA += (Awidth) * size_batch; + } +} + + + + +//////////////////// Section: "quadratric" matrix evaluation /////////////////////////////// + + + + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_quad_trimat_eval_gf16( unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned dim, unsigned size_batch ) { +/// +/// assert( dim <= 128 ); +/// assert( size_batch <= 128 ); + unsigned char tmp[256]; + + unsigned char _x[256]; + for (unsigned i = 0; i < dim; i++) { + _x[i] = gf16v_get_ele( x, i ); + } + + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_set_zero( y, size_batch ); + for (unsigned i = 0; i < dim; i++) { + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_set_zero( tmp, size_batch ); + for (unsigned j = i; j < dim; j++) { + gf16v_madd( tmp, trimat, _x[j], size_batch ); + trimat += size_batch; + } + gf16v_madd( y, tmp, _x[i], size_batch ); + } +} + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_quad_trimat_eval_gf256( unsigned char *y, const unsigned char *trimat, const unsigned char *x, unsigned dim, unsigned size_batch ) { +/// +/// assert( dim <= 256 ); +/// assert( size_batch <= 256 ); + unsigned char tmp[256]; + + unsigned char _x[256]; + for (unsigned i = 0; i < dim; i++) { + _x[i] = gf256v_get_ele( x, i ); + } + + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_set_zero( y, size_batch ); + for (unsigned i = 0; i < dim; i++) { + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_set_zero( tmp, size_batch ); + for (unsigned j = i; j < dim; j++) { + gf256v_madd( tmp, trimat, _x[j], size_batch ); + trimat += size_batch; + } + gf256v_madd( y, tmp, _x[i], size_batch ); + } +} + + + + + + + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_quad_recmat_eval_gf16( unsigned char *z, const unsigned char *y, unsigned dim_y, const unsigned char *mat, + const unsigned char *x, unsigned dim_x, unsigned size_batch ) { +/// +/// assert( dim_x <= 128 ); +/// assert( dim_y <= 128 ); +/// assert( size_batch <= 128 ); + unsigned char tmp[128]; + + unsigned char _x[128]; + for (unsigned i = 0; i < dim_x; i++) { + _x[i] = gf16v_get_ele( x, i ); + } + unsigned char _y[128]; + for (unsigned i = 0; i < dim_y; i++) { + _y[i] = gf16v_get_ele( y, i ); + } + + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_set_zero( z, size_batch ); + for (unsigned i = 0; i < dim_y; i++) { + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_set_zero( tmp, size_batch ); + for (unsigned j = 0; j < dim_x; j++) { + gf16v_madd( tmp, mat, _x[j], size_batch ); + mat += size_batch; + } + gf16v_madd( z, tmp, _y[i], size_batch ); + } +} + + +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_batch_quad_recmat_eval_gf256( unsigned char *z, const unsigned char *y, unsigned dim_y, const unsigned char *mat, + const unsigned char *x, unsigned dim_x, unsigned size_batch ) { +/// +/// assert( dim_x <= 128 ); +/// assert( dim_y <= 128 ); +/// assert( size_batch <= 128 ); + unsigned char tmp[128]; + + unsigned char _x[128]; + for (unsigned i = 0; i < dim_x; i++) { + _x[i] = gf256v_get_ele( x, i ); + } + unsigned char _y[128]; + for (unsigned i = 0; i < dim_y; i++) { + _y[i] = gf256v_get_ele( y, i ); + } + + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_set_zero( z, size_batch ); + for (unsigned i = 0; i < dim_y; i++) { + PQCLEAN_RAINBOWIACLASSIC_CLEAN_gf256v_set_zero( tmp, size_batch ); + for (unsigned j = 0; j < dim_x; j++) { + gf256v_madd( tmp, mat, _x[j], size_batch ); + mat += size_batch; + } + gf256v_madd( z, tmp, _y[i], size_batch ); + } +} + + + diff --git a/crypto_sign/rainbowIa-classic/clean/parallel_matrix_op.h b/crypto_sign/rainbowIa-classic/clean/parallel_matrix_op.h new file mode 100644 index 00000000..4881bc53 --- /dev/null +++ b/crypto_sign/rainbowIa-classic/clean/parallel_matrix_op.h @@ -0,0 +1,316 @@ +/// @file parallel_matrix_op.h +/// @brief Librarys for operations of batched matrixes. +/// +/// + +#ifndef _P_MATRIX_OP_H_ +#define _P_MATRIX_OP_H_ + + + + + +//////////////////////////////////////////////////////////////////////// +/// Librarys for batched matrix operations. +/// A batched matrix is a matrix which each element of the matrix +/// contains size_batch GF elements. +//////////////////////////////////////////////////////////////////////// + + + + +//////////////// 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. +/// +static inline +unsigned idx_of_trimat( unsigned i_row, unsigned j_col, unsigned 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 idx_of_2trimat( unsigned i_row, unsigned j_col, unsigned n_var ) { + if ( i_row > j_col ) { + return idx_of_trimat(j_col, i_row, n_var); + } + return idx_of_trimat(i_row, j_col, n_var); +} + + +/// +/// @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 Awidth, unsigned 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 Bheight, unsigned size_Bcolvec, unsigned Bwidth, unsigned 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 Bheight, unsigned size_Bcolvec, unsigned Bwidth, unsigned 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 Bheight, unsigned size_Bcolvec, unsigned Bwidth, unsigned 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 Bheight, unsigned size_Bcolvec, unsigned Bwidth, unsigned 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 Bheight, unsigned size_Bcolvec, unsigned Bwidth, unsigned 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 Bheight, unsigned size_Bcolvec, unsigned Bwidth, unsigned 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 Aheight, unsigned size_Acolvec, unsigned Awidth, + const unsigned char *bB, unsigned Bwidth, unsigned 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 Aheight, unsigned size_Acolvec, unsigned Awidth, + const unsigned char *bB, unsigned Bwidth, unsigned 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 Awidth_before_tr, + const unsigned char *B, unsigned Bheight, unsigned size_Bcolvec, unsigned Bwidth, unsigned 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 Awidth_before_tr, + const unsigned char *B, unsigned Bheight, unsigned size_Bcolvec, unsigned Bwidth, unsigned 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 Aheight, + const unsigned char *B, unsigned Bheight, unsigned size_Bcolvec, unsigned Bwidth, unsigned 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 Aheight, + const unsigned char *B, unsigned Bheight, unsigned size_Bcolvec, unsigned Bwidth, unsigned 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 dim, unsigned 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 dim, unsigned 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 dim_y, + const unsigned char *mat, const unsigned char *x, unsigned dim_x, unsigned 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 dim_y, + const unsigned char *mat, const unsigned char *x, unsigned dim_x, unsigned size_batch ); + + + + + + +#endif // _P_MATRIX_OP_H_ + diff --git a/crypto_sign/rainbowIa-classic/clean/rainbow.c b/crypto_sign/rainbowIa-classic/clean/rainbow.c new file mode 100644 index 00000000..9ce5ff8b --- /dev/null +++ b/crypto_sign/rainbowIa-classic/clean/rainbow.c @@ -0,0 +1,195 @@ +/// @file rainbow.c +/// @brief The standard implementations for functions in rainbow.h +/// + +#include "blas.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 +#define _MAX_O ((_O1>_O2)?_O1:_O2) +#define _MAX_O_BYTE ((_O1_BYTE>_O2_BYTE)?_O1_BYTE:_O2_BYTE) + + + +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 i = 0; i < LEN_SKSEED + _HASH_LEN; i++) { + prng_preseed[i] ^= prng_preseed[i]; // clean + } + for (unsigned i = 0; i < _HASH_LEN; i++) { + prng_seed[i] ^= prng_seed[i]; // clean + } + + // roll vinegars. + uint8_t vinegar[_V1_BYTE]; + unsigned n_attempt = 0; + unsigned 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 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); + gf256v_add(y, temp_o, _O1_BYTE); + + // Central Map: + // layer 1: calculate x_o1 + memcpy( temp_o, r_l1_F1, _O1_BYTE ); + 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 + gf256v_add( temp_o, mat_l2, _O2_BYTE ); + gf256v_add( temp_o, r_l2_F1, _O2_BYTE ); // F1 + 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 + 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 ); + gf256v_add(w, y, _V1_BYTE ); + // Computing the t4 part. + gfmat_prod(y, sk->t4, _V1_BYTE, _O2, x_o2 ); + gf256v_add(w, y, _V1_BYTE ); + // Computing the t3 part. + gfmat_prod(y, sk->t3, _O1_BYTE, _O2, x_o2 ); + 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; + } + gf256v_add( signature, w, _PUB_N_BYTE ); + 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 i = 0; i < _PUB_M_BYTE; i++) { + cc |= (digest_ck[i] ^ correct[i]); + } + return (0 == cc) ? 0 : -1; +} + + + +/////////////// cyclic version /////////////////////////// + + +int PQCLEAN_RAINBOWIACLASSIC_CLEAN_rainbow_sign_cyclic( uint8_t *signature, const csk_t *csk, const uint8_t *digest ) { + unsigned char sk[sizeof(sk_t) + 32]; + PQCLEAN_RAINBOWIACLASSIC_CLEAN_generate_secretkey_cyclic((sk_t *)sk, csk->pk_seed, csk->sk_seed ); // generating classic secret key. + return PQCLEAN_RAINBOWIACLASSIC_CLEAN_rainbow_sign( signature, (sk_t *) sk, digest ); +} + +int PQCLEAN_RAINBOWIACLASSIC_CLEAN_rainbow_verify_cyclic( const uint8_t *digest, const uint8_t *signature, const cpk_t *_pk ) { + unsigned char pk[sizeof(pk_t) +32]; + PQCLEAN_RAINBOWIACLASSIC_CLEAN_cpk_to_pk( (pk_t *)pk, _pk ); // generating classic public key. + return PQCLEAN_RAINBOWIACLASSIC_CLEAN_rainbow_verify( digest, signature, (pk_t *)pk ); +} + + diff --git a/crypto_sign/rainbowIa-classic/clean/rainbow.h b/crypto_sign/rainbowIa-classic/clean/rainbow.h new file mode 100644 index 00000000..c1947f67 --- /dev/null +++ b/crypto_sign/rainbowIa-classic/clean/rainbow.h @@ -0,0 +1,64 @@ +/// @file rainbow.h +/// @brief APIs for rainbow. +/// + +#ifndef _RAINBOW_H_ +#define _RAINBOW_H_ + +#include "rainbow_config.h" +#include "rainbow_keypair.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/// +/// @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 ); + + +/// +/// @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_RAINBOWIACLASSIC_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_RAINBOWIACLASSIC_CLEAN_rainbow_verify_cyclic( const uint8_t *digest, const uint8_t *signature, const cpk_t *pk ); + + + +#ifdef __cplusplus +} +#endif + + +#endif // _RAINBOW_H_ diff --git a/crypto_sign/rainbowIa-classic/clean/rainbow_blas.h b/crypto_sign/rainbowIa-classic/clean/rainbow_blas.h new file mode 100644 index 00000000..8f42efd3 --- /dev/null +++ b/crypto_sign/rainbowIa-classic/clean/rainbow_blas.h @@ -0,0 +1,57 @@ +/// @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 + +#ifndef _RAINBOW_BLAS_H_ +#define _RAINBOW_BLAS_H_ + +#include "blas.h" + +#include "parallel_matrix_op.h" + +#include "rainbow_config.h" + +#ifdef _USE_GF16 + +#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 + +#else + +#define gfv_get_ele gf256v_get_ele +#define gfv_mul_scalar gf256v_mul_scalar +#define gfv_madd gf256v_madd + +#define gfmat_prod gf256mat_prod +#define gfmat_inv gf256mat_inv + +#define batch_trimat_madd batch_trimat_madd_gf256 +#define batch_trimatTr_madd batch_trimatTr_madd_gf256 +#define batch_2trimat_madd batch_2trimat_madd_gf256 +#define batch_matTr_madd batch_matTr_madd_gf256 +#define batch_bmatTr_madd batch_bmatTr_madd_gf256 +#define batch_mat_madd batch_mat_madd_gf256 + +#define batch_quad_trimat_eval batch_quad_trimat_eval_gf256 +#define batch_quad_recmat_eval batch_quad_recmat_eval_gf256 + +#endif + + +#endif // _RAINBOW_BLAS_H_ + diff --git a/crypto_sign/rainbowIa-classic/clean/rainbow_config.h b/crypto_sign/rainbowIa-classic/clean/rainbow_config.h new file mode 100644 index 00000000..da952ce4 --- /dev/null +++ b/crypto_sign/rainbowIa-classic/clean/rainbow_config.h @@ -0,0 +1,100 @@ +/// @file rainbow_config.h +/// @brief Defining the parameters of the Rainbow and the corresponding constants. +/// +/// Defining one of the 3 parameter _RAINBOW16_32_32_32 , _RAINBOW256_68_36_36 , or _RAINBOW256_92_48_48 +/// for (GF16,32,32,32) (GF256,68,36,36) (GF256,92,48,48) in this file. +/// +/// + +#ifndef _H_RAINBOW_CONFIG_H_ +#define _H_RAINBOW_CONFIG_H_ + + +// TODO: refactor this + +/// the defined parameter +#if (!defined(_RAINBOW16_32_32_32))&&(!defined(_RAINBOW256_68_36_36))&&(!defined(_RAINBOW256_92_48_48)) +#define _RAINBOW16_32_32_32 +//#define _RAINBOW256_68_36_36 +//#define _RAINBOW256_92_48_48 +#endif + + +#if defined _RAINBOW16_32_32_32 +#define _USE_GF16 +#define _GFSIZE 16 +#define _V1 32 +#define _O1 32 +#define _O2 32 +#define _HASH_LEN 32 + +#elif defined _RAINBOW256_68_36_36 +#define _GFSIZE 256 +#define _V1 68 +#define _O1 36 +#define _O2 36 +#define _HASH_LEN 48 + +#elif defined _RAINBOW256_92_48_48 +#define _GFSIZE 256 +#define _V1 92 +#define _O1 48 +#define _O2 48 +#define _HASH_LEN 64 + +#else +error here. +#endif + + +#define _V2 ((_V1)+(_O1)) + +#define STR1(x) #x +#define THE_NAME(gf,v1,o1,o2) "RAINBOW(" STR1(gf) "," STR1(v1) "," STR1(o1) "," STR1(o2) ")" +#define _S_NAME THE_NAME(_GFSIZE,_V1,_O1,_O2) + + +/// 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. + + +#ifdef _USE_GF16 +// GF16 +#define _V1_BYTE (_V1/2) +#define _V2_BYTE (_V2/2) +#define _O1_BYTE (_O1/2) +#define _O2_BYTE (_O2/2) +#define _PUB_N_BYTE (_PUB_N/2) +#define _PUB_M_BYTE (_PUB_M/2) + +#else +// GF256 +#define _V1_BYTE (_V1) +#define _V2_BYTE (_V2) +#define _O1_BYTE (_O1) +#define _O2_BYTE (_O2) +#define _PUB_N_BYTE (_PUB_N) +#define _PUB_M_BYTE (_PUB_M) + +#endif + + +/// 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/crypto_sign/rainbowIa-classic/clean/rainbow_keypair.c b/crypto_sign/rainbowIa-classic/clean/rainbow_keypair.c new file mode 100644 index 00000000..009006f4 --- /dev/null +++ b/crypto_sign/rainbowIa-classic/clean/rainbow_keypair.c @@ -0,0 +1,267 @@ +/// @file rainbow_keypair.c +/// @brief implementations of functions in rainbow_keypair.h +/// + +#include "blas.h" +#include "blas_comm.h" +#include "rainbow_blas.h" +#include "rainbow_keypair.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 generate_l1_F12( unsigned char *sk, prng_t *prng0 ) { + unsigned 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 generate_l2_F12356( unsigned char *sk, prng_t *prng0 ) { + unsigned 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 ); +} + + +////////////////////////////////////////////////////////// + + + +void PQCLEAN_RAINBOWIACLASSIC_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_RAINBOWIACLASSIC_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_RAINBOWIACLASSIC_CLEAN_extcpk_to_pk( rpk, &pk ); +} + + + +///////////////////////////////////////////////////////// + + + +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 i = 0; i < _O2; i++) { /// t3 width + gfmat_prod( temp, t1, _V1_BYTE, _O1, t3 ); + 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 n_terms, const unsigned char *s1 ) { + unsigned char temp[_O1_BYTE + 32]; + while ( n_terms-- ) { + gfmat_prod( temp, s1, _O1_BYTE, _O2, l2_polys ); + 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_secretkey( sk_t *sk, const unsigned char *sk_seed ) { + _generate_secretkey( sk, sk_seed ); + calculate_t4( sk->t4, sk->t1, sk->t3 ); +} + + + +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. +} + + + +///////////////////// Cyclic ////////////////////////////////// + + +void PQCLEAN_RAINBOWIACLASSIC_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_RAINBOWIACLASSIC_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_RAINBOWIACLASSIC_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_RAINBOWIACLASSIC_CLEAN_calculate_F_from_Q( sk, Qs, sk ); + + // clean prng for sk + memset( &prng0, 0, sizeof(prng_t) ); +} + + + + + +void PQCLEAN_RAINBOWIACLASSIC_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 ); + + // prng for sk + prng_t prng; + prng_t *prng0 = &prng; + PQCLEAN_RAINBOWIACLASSIC_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_RAINBOWIACLASSIC_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_RAINBOWIACLASSIC_CLEAN_calculate_F_from_Q( sk, Qs, sk ); // calcuate the rest parts of secret key from Qs and S,T + + memcpy( sk->t4, t2, _V1_BYTE * _O2 ); // restore t2 + PQCLEAN_RAINBOWIACLASSIC_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 + + 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_RAINBOWIACLASSIC_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_RAINBOWIACLASSIC_CLEAN_generate_keypair_cyclic( pk, &sk, pk_seed, sk_seed ); +} + + + + diff --git a/crypto_sign/rainbowIa-classic/clean/rainbow_keypair.h b/crypto_sign/rainbowIa-classic/clean/rainbow_keypair.h new file mode 100644 index 00000000..accee12c --- /dev/null +++ b/crypto_sign/rainbowIa-classic/clean/rainbow_keypair.h @@ -0,0 +1,148 @@ +/// @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. +/// + +#ifndef _RAINBOW_KEYPAIR_H_ +#define _RAINBOW_KEYPAIR_H_ + + +#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 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 ); + +/// +/// @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_RAINBOWIACLASSIC_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_RAINBOWIACLASSIC_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 classic rainbow. +/// +/// @param[out] sk - the secret key. +/// @param[in] sk_seed - seed for generating the secret key. +/// +void PQCLEAN_RAINBOWIACLASSIC_CLEAN_generate_secretkey( sk_t *sk, 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_RAINBOWIACLASSIC_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_RAINBOWIACLASSIC_CLEAN_cpk_to_pk( pk_t *pk, const cpk_t *cpk ); + +#endif // _RAINBOW_KEYPAIR_H_ diff --git a/crypto_sign/rainbowIa-classic/clean/rainbow_keypair_computation.c b/crypto_sign/rainbowIa-classic/clean/rainbow_keypair_computation.c new file mode 100644 index 00000000..70ebac1e --- /dev/null +++ b/crypto_sign/rainbowIa-classic/clean/rainbow_keypair_computation.c @@ -0,0 +1,367 @@ +/// @file rainbow_keypair_computation.c +/// @brief Implementations for functions in rainbow_keypair_computation.h +/// + + +#include "blas.h" +#include "blas_comm.h" +#include "rainbow_blas.h" +#include "rainbow_keypair.h" +#include "rainbow_keypair_computation.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 i = 0; i < _V1; i++) { + for (unsigned j = i; j < _V1; j++) { + unsigned pub_idx = 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 i = 0; i < _V1; i++) { + for (unsigned j = _V1; j < _V1 + _O1; j++) { + unsigned pub_idx = 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 i = 0; i < _V1; i++) { + for (unsigned j = _V1 + _O1; j < _PUB_N; j++) { + unsigned pub_idx = 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 i = _V1; i < _V1 + _O1; i++) { + for (unsigned j = i; j < _V1 + _O1; j++) { + unsigned pub_idx = 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 i = _V1; i < _V1 + _O1; i++) { + for (unsigned j = _V1 + _O1; j < _PUB_N; j++) { + unsigned pub_idx = 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 i = _V1 + _O1; i < _PUB_N; i++) { + for (unsigned j = i; j < _PUB_N; j++) { + unsigned pub_idx = 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 + +#define SIZE_TEMPQ (_O1_BYTE * _O1 * _O1) + #if (_O1_BYTE*_O2*_O2)> SIZE_TEMPQ +#define SIZE_TEMPQ (_O1_BYTE*_O2*_O2) + #endif + #if (_O2_BYTE*_O1*_O1) > SIZE_TEMPQ +#define SIZE_TEMPQ (_O2_BYTE*_O1*_O1) + #endif + #if (_O2_BYTE*_O2*_O2) > SIZE_TEMPQ +#define SIZE_TEMPQ (_O2_BYTE*_O2*_O2) + #endif + + unsigned char tempQ[SIZE_TEMPQ + 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 +} + + + + + +///////////////////////////////////////////////////// + +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_RAINBOWIACLASSIC_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, _O1_BYTE * _V1 * _O2 ); + 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_RAINBOWIACLASSIC_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_RAINBOWIACLASSIC_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_RAINBOWIACLASSIC_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_Q_from_F_impl calculate_Q_from_F_ref +#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_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 ); +} + +void PQCLEAN_RAINBOWIACLASSIC_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_RAINBOWIACLASSIC_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/crypto_sign/rainbowIa-classic/clean/rainbow_keypair_computation.h b/crypto_sign/rainbowIa-classic/clean/rainbow_keypair_computation.h new file mode 100644 index 00000000..5aec5ae4 --- /dev/null +++ b/crypto_sign/rainbowIa-classic/clean/rainbow_keypair_computation.h @@ -0,0 +1,79 @@ +/// @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. +/// + +#ifndef _RAINBOW_KEYPAIR_COMP_H_ +#define _RAINBOW_KEYPAIR_COMP_H_ + + +#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 ); + + +/// +/// @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_RAINBOWIACLASSIC_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_RAINBOWIACLASSIC_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/crypto_sign/rainbowIa-classic/clean/sign.c b/crypto_sign/rainbowIa-classic/clean/sign.c new file mode 100644 index 00000000..82d2122d --- /dev/null +++ b/crypto_sign/rainbowIa-classic/clean/sign.c @@ -0,0 +1,150 @@ +/// @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 ); + + #if defined _RAINBOW_CLASSIC + + PQCLEAN_RAINBOWIACLASSIC_CLEAN_generate_keypair( (pk_t *) pk, (sk_t *) sk, sk_seed ); + + #elif defined _RAINBOW_CYCLIC + + unsigned char pk_seed[LEN_PKSEED] = {0}; + randombytes( pk_seed, LEN_PKSEED ); + generate_keypair_cyclic( (cpk_t *) pk, (sk_t *) sk, pk_seed, sk_seed ); + + #elif defined _RAINBOW_CYCLIC_COMPRESSED + + unsigned char pk_seed[LEN_PKSEED] = {0}; + randombytes( pk_seed, LEN_PKSEED ); + generate_compact_keypair_cyclic( (cpk_t *) pk, (csk_t *) sk, pk_seed, sk_seed ); + + #else + error here + #endif + 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; + + #if defined _RAINBOW_CLASSIC + + return PQCLEAN_RAINBOWIACLASSIC_CLEAN_rainbow_sign( sm + mlen, (const sk_t *)sk, digest ); + + #elif defined _RAINBOW_CYCLIC + + return rainbow_sign( sm + mlen, (const sk_t *)sk, digest ); + + #elif defined _RAINBOW_CYCLIC_COMPRESSED + + return rainbow_sign_cyclic( sm + mlen, (const csk_t *)sk, digest ); + + #else + error here + #endif + + +} + + + + + + +int +PQCLEAN_RAINBOWIACLASSIC_CLEAN_crypto_sign_open(unsigned char *m, size_t *mlen, const unsigned char *sm, size_t smlen, const unsigned char *pk) { +//TODO: this should not copy out the message if verification fails + if ( _SIGNATURE_BYTE > smlen ) { + return -1; + } + memcpy( m, sm, smlen - _SIGNATURE_BYTE ); + mlen[0] = smlen - _SIGNATURE_BYTE; + + unsigned char digest[_HASH_LEN]; + PQCLEAN_RAINBOWIACLASSIC_CLEAN_hash_msg( digest, _HASH_LEN, m, *mlen ); + + #if defined _RAINBOW_CLASSIC + + return PQCLEAN_RAINBOWIACLASSIC_CLEAN_rainbow_verify( digest, sm + mlen[0], (const pk_t *)pk ); + + #elif defined _RAINBOW_CYCLIC + + return PQCLEAN_RAINBOWIACLASSIC_CLEAN_rainbow_verify_cyclic( digest, sm + mlen[0], (const cpk_t *)pk ); + + #elif defined _RAINBOW_CYCLIC_COMPRESSED + + return PQCLEAN_RAINBOWIACLASSIC_CLEAN_rainbow_verify_cyclic( digest, sm + mlen[0], (const cpk_t *)pk ); + + #else + error here + #endif + + +} + +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; + #if defined _RAINBOW_CLASSIC + return PQCLEAN_RAINBOWIACLASSIC_CLEAN_rainbow_sign( sig, (const sk_t *)sk, digest ); + #elif defined _RAINBOW_CYCLIC + return PQCLEAN_RAINBOWIACLASSIC_CLEAN_rainbow_sign( sig, (const sk_t *)sk, digest ); + #elif defined _RAINBOW_CYCLIC_COMPRESSED + return PQCLEAN_RAINBOWIACLASSIC_CLEAN_rainbow_sign_cyclic( sig, (const csk_t *)sk, digest ); + #else + error here + #endif + +} + +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 ); + #if defined _RAINBOW_CLASSIC + return PQCLEAN_RAINBOWIACLASSIC_CLEAN_rainbow_verify( digest, sig, (const pk_t *)pk ); + #elif defined _RAINBOW_CYCLIC + return PQCLEAN_RAINBOWIACLASSIC_CLEAN_rainbow_verify_cyclic( digest, sig, (const cpk_t *)pk ); + #elif defined _RAINBOW_CYCLIC_COMPRESSED + return PQCLEAN_RAINBOWIACLASSIC_CLEAN_rainbow_verify_cyclic( digest, sig, (const cpk_t *)pk ); + #else + error here + #endif + +} diff --git a/crypto_sign/rainbowIa-classic/clean/utils_hash.c b/crypto_sign/rainbowIa-classic/clean/utils_hash.c new file mode 100644 index 00000000..1b072a3c --- /dev/null +++ b/crypto_sign/rainbowIa-classic/clean/utils_hash.c @@ -0,0 +1,65 @@ +/// @file utils_hash.c +/// @brief the adapter for SHA2 families. +/// +/// + +#include "hash_len_config.h" +#include "sha2.h" +#include "utils_hash.h" + +#ifndef _HASH_LEN +#define _HASH_LEN (32) +#endif + +static inline +int _hash( unsigned char *digest, const unsigned char *m, unsigned long long mlen ) { + #if 32 == _HASH_LEN + sha256(digest, m, mlen); + #elif 48 == _HASH_LEN + sha384(digest, m, mlen); + #elif 64 == _HASH_LEN + sha512(digest, m, mlen); + #else +#error "unsupported _HASH_LEN" + #endif + return 0; +} + +static inline +int expand_hash( unsigned char *digest, unsigned n_digest, const unsigned char *hash ) { + if ( _HASH_LEN >= n_digest ) { + for (unsigned i = 0; i < n_digest; i++) { + digest[i] = hash[i]; + } + return 0; + } + for (unsigned 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 (unsigned i = 0; i < n_digest; i++) { + digest[_HASH_LEN + i] = temp[i]; + } + } + return 0; +} + +int PQCLEAN_RAINBOWIACLASSIC_CLEAN_hash_msg( unsigned char *digest, unsigned len_digest, const unsigned char *m, unsigned long long mlen ) { + unsigned char buf[_HASH_LEN]; + _hash( buf, m, mlen ); + + return expand_hash( digest, len_digest, buf ); +} + + diff --git a/crypto_sign/rainbowIa-classic/clean/utils_hash.h b/crypto_sign/rainbowIa-classic/clean/utils_hash.h new file mode 100644 index 00000000..2aeffde4 --- /dev/null +++ b/crypto_sign/rainbowIa-classic/clean/utils_hash.h @@ -0,0 +1,16 @@ +/// @file utils_hash.h +/// @brief the interface for adapting hash functions. +/// +/// +#ifndef _UTILS_HASH_H_ +#define _UTILS_HASH_H_ + +// for the definition of _HASH_LEN. +#include "hash_len_config.h" + +int PQCLEAN_RAINBOWIACLASSIC_CLEAN_hash_msg( unsigned char *digest, unsigned len_digest, const unsigned char *m, unsigned long long mlen ); + + + +#endif // _UTILS_HASH_H_ + diff --git a/crypto_sign/rainbowIa-classic/clean/utils_prng.c b/crypto_sign/rainbowIa-classic/clean/utils_prng.c new file mode 100644 index 00000000..7a9ad369 --- /dev/null +++ b/crypto_sign/rainbowIa-classic/clean/utils_prng.c @@ -0,0 +1,96 @@ +/// @file utils_prng.c +/// @brief The implementation of PRNG related functions. +/// + +#include "aes.h" +#include "randombytes.h" +#include "utils_hash.h" +#include "utils_prng.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]; + } + } + 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, + unsigned long long 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; + } + } + 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/crypto_sign/rainbowIa-classic/clean/utils_prng.h b/crypto_sign/rainbowIa-classic/clean/utils_prng.h new file mode 100644 index 00000000..6c1f93a9 --- /dev/null +++ b/crypto_sign/rainbowIa-classic/clean/utils_prng.h @@ -0,0 +1,22 @@ +/// @file utils_prng.h +/// @brief the interface for adapting PRNG functions. +/// +/// + +#ifndef _UTILS_PRNG_H_ +#define _UTILS_PRNG_H_ + +#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_ + +