From 39c00e8c47110a8b42bf6ba45fd99f58fe949939 Mon Sep 17 00:00:00 2001 From: "John M. Schanck" Date: Thu, 15 Oct 2020 20:00:04 -0400 Subject: [PATCH] Update Saber and add AVX2 implementation --- crypto_kem/firesaber/META.yml | 11 +- crypto_kem/firesaber/avx2/LICENSE | 1 + crypto_kem/firesaber/avx2/Makefile | 22 + crypto_kem/firesaber/avx2/SABER_indcpa.c | 416 +++++++ crypto_kem/firesaber/avx2/SABER_indcpa.h | 13 + crypto_kem/firesaber/avx2/SABER_params.h | 45 + crypto_kem/firesaber/avx2/api.h | 18 + crypto_kem/firesaber/avx2/cbd.c | 52 + crypto_kem/firesaber/avx2/cbd.h | 16 + crypto_kem/firesaber/avx2/kem.c | 79 ++ crypto_kem/firesaber/avx2/kem.h | 35 + crypto_kem/firesaber/avx2/pack_unpack.c | 502 ++++++++ crypto_kem/firesaber/avx2/pack_unpack.h | 56 + crypto_kem/firesaber/avx2/poly.h | 27 + crypto_kem/firesaber/avx2/polymul/consts.h | 20 + crypto_kem/firesaber/avx2/polymul/matrix.c | 303 +++++ crypto_kem/firesaber/avx2/polymul/scm_avx.c | 753 ++++++++++++ .../firesaber/avx2/polymul/toom-cook_4way.c | 1010 +++++++++++++++++ crypto_kem/firesaber/avx2/verify.c | 35 + crypto_kem/firesaber/avx2/verify.h | 22 + crypto_kem/firesaber/clean/LICENSE | 9 +- crypto_kem/firesaber/clean/Makefile | 4 +- crypto_kem/firesaber/clean/SABER_indcpa.c | 316 +----- crypto_kem/firesaber/clean/SABER_indcpa.h | 12 +- crypto_kem/firesaber/clean/SABER_params.h | 42 +- crypto_kem/firesaber/clean/api.h | 12 +- crypto_kem/firesaber/clean/cbd.c | 34 +- crypto_kem/firesaber/clean/cbd.h | 7 +- crypto_kem/firesaber/clean/kem.c | 78 +- crypto_kem/firesaber/clean/pack_unpack.c | 336 ++---- crypto_kem/firesaber/clean/pack_unpack.h | 29 +- crypto_kem/firesaber/clean/poly.c | 58 +- crypto_kem/firesaber/clean/poly.h | 23 +- crypto_kem/firesaber/clean/poly_mul.c | 18 +- crypto_kem/firesaber/clean/poly_mul.h | 8 +- crypto_kem/firesaber/clean/verify.c | 13 +- crypto_kem/firesaber/clean/verify.h | 7 +- crypto_kem/lightsaber/META.yml | 11 +- crypto_kem/lightsaber/avx2/LICENSE | 1 + crypto_kem/lightsaber/avx2/Makefile | 22 + crypto_kem/lightsaber/avx2/SABER_indcpa.c | 416 +++++++ crypto_kem/lightsaber/avx2/SABER_indcpa.h | 13 + crypto_kem/lightsaber/avx2/SABER_params.h | 46 + crypto_kem/lightsaber/avx2/api.h | 18 + crypto_kem/lightsaber/avx2/cbd.c | 51 + crypto_kem/lightsaber/avx2/cbd.h | 16 + crypto_kem/lightsaber/avx2/kem.c | 79 ++ crypto_kem/lightsaber/avx2/kem.h | 35 + crypto_kem/lightsaber/avx2/pack_unpack.c | 502 ++++++++ crypto_kem/lightsaber/avx2/pack_unpack.h | 56 + crypto_kem/lightsaber/avx2/poly.h | 27 + crypto_kem/lightsaber/avx2/polymul/consts.h | 20 + crypto_kem/lightsaber/avx2/polymul/matrix.c | 303 +++++ crypto_kem/lightsaber/avx2/polymul/scm_avx.c | 753 ++++++++++++ .../lightsaber/avx2/polymul/toom-cook_4way.c | 1010 +++++++++++++++++ crypto_kem/lightsaber/avx2/verify.c | 35 + crypto_kem/lightsaber/avx2/verify.h | 22 + crypto_kem/lightsaber/clean/LICENSE | 9 +- crypto_kem/lightsaber/clean/Makefile | 4 +- crypto_kem/lightsaber/clean/SABER_indcpa.c | 316 +----- crypto_kem/lightsaber/clean/SABER_indcpa.h | 12 +- crypto_kem/lightsaber/clean/SABER_params.h | 43 +- crypto_kem/lightsaber/clean/api.h | 12 +- crypto_kem/lightsaber/clean/cbd.c | 27 +- crypto_kem/lightsaber/clean/cbd.h | 7 +- crypto_kem/lightsaber/clean/kem.c | 78 +- crypto_kem/lightsaber/clean/pack_unpack.c | 338 ++---- crypto_kem/lightsaber/clean/pack_unpack.h | 29 +- crypto_kem/lightsaber/clean/poly.c | 58 +- crypto_kem/lightsaber/clean/poly.h | 23 +- crypto_kem/lightsaber/clean/poly_mul.c | 18 +- crypto_kem/lightsaber/clean/poly_mul.h | 8 +- crypto_kem/lightsaber/clean/verify.c | 13 +- crypto_kem/lightsaber/clean/verify.h | 7 +- crypto_kem/saber/META.yml | 11 +- crypto_kem/saber/avx2/LICENSE | 1 + crypto_kem/saber/avx2/Makefile | 22 + crypto_kem/saber/avx2/SABER_indcpa.c | 416 +++++++ crypto_kem/saber/avx2/SABER_indcpa.h | 13 + crypto_kem/saber/avx2/SABER_params.h | 46 + crypto_kem/saber/avx2/api.h | 18 + crypto_kem/saber/avx2/cbd.c | 51 + crypto_kem/saber/avx2/cbd.h | 16 + crypto_kem/saber/avx2/kem.c | 79 ++ crypto_kem/saber/avx2/kem.h | 35 + crypto_kem/saber/avx2/pack_unpack.c | 502 ++++++++ crypto_kem/saber/avx2/pack_unpack.h | 56 + crypto_kem/saber/avx2/poly.h | 27 + crypto_kem/saber/avx2/polymul/consts.h | 20 + crypto_kem/saber/avx2/polymul/matrix.c | 303 +++++ crypto_kem/saber/avx2/polymul/scm_avx.c | 753 ++++++++++++ .../saber/avx2/polymul/toom-cook_4way.c | 1010 +++++++++++++++++ crypto_kem/saber/avx2/verify.c | 35 + crypto_kem/saber/avx2/verify.h | 22 + crypto_kem/saber/clean/LICENSE | 9 +- crypto_kem/saber/clean/Makefile | 4 +- crypto_kem/saber/clean/SABER_indcpa.c | 316 +----- crypto_kem/saber/clean/SABER_indcpa.h | 12 +- crypto_kem/saber/clean/SABER_params.h | 43 +- crypto_kem/saber/clean/api.h | 12 +- crypto_kem/saber/clean/cbd.c | 31 +- crypto_kem/saber/clean/cbd.h | 7 +- crypto_kem/saber/clean/kem.c | 78 +- crypto_kem/saber/clean/pack_unpack.c | 340 ++---- crypto_kem/saber/clean/pack_unpack.h | 29 +- crypto_kem/saber/clean/poly.c | 58 +- crypto_kem/saber/clean/poly.h | 23 +- crypto_kem/saber/clean/poly_mul.c | 18 +- crypto_kem/saber/clean/poly_mul.h | 8 +- crypto_kem/saber/clean/verify.c | 13 +- crypto_kem/saber/clean/verify.h | 7 +- test/duplicate_consistency/firesaber_avx2.yml | 7 + .../duplicate_consistency/firesaber_clean.yml | 36 +- .../duplicate_consistency/lightsaber_avx2.yml | 45 + .../lightsaber_clean.yml | 78 +- test/duplicate_consistency/saber_avx2.yml | 26 + test/duplicate_consistency/saber_clean.yml | 57 +- 117 files changed, 11459 insertions(+), 2114 deletions(-) create mode 100644 crypto_kem/firesaber/avx2/LICENSE create mode 100644 crypto_kem/firesaber/avx2/Makefile create mode 100644 crypto_kem/firesaber/avx2/SABER_indcpa.c create mode 100644 crypto_kem/firesaber/avx2/SABER_indcpa.h create mode 100644 crypto_kem/firesaber/avx2/SABER_params.h create mode 100644 crypto_kem/firesaber/avx2/api.h create mode 100644 crypto_kem/firesaber/avx2/cbd.c create mode 100644 crypto_kem/firesaber/avx2/cbd.h create mode 100644 crypto_kem/firesaber/avx2/kem.c create mode 100644 crypto_kem/firesaber/avx2/kem.h create mode 100644 crypto_kem/firesaber/avx2/pack_unpack.c create mode 100644 crypto_kem/firesaber/avx2/pack_unpack.h create mode 100644 crypto_kem/firesaber/avx2/poly.h create mode 100644 crypto_kem/firesaber/avx2/polymul/consts.h create mode 100644 crypto_kem/firesaber/avx2/polymul/matrix.c create mode 100644 crypto_kem/firesaber/avx2/polymul/scm_avx.c create mode 100644 crypto_kem/firesaber/avx2/polymul/toom-cook_4way.c create mode 100644 crypto_kem/firesaber/avx2/verify.c create mode 100644 crypto_kem/firesaber/avx2/verify.h create mode 100644 crypto_kem/lightsaber/avx2/LICENSE create mode 100644 crypto_kem/lightsaber/avx2/Makefile create mode 100644 crypto_kem/lightsaber/avx2/SABER_indcpa.c create mode 100644 crypto_kem/lightsaber/avx2/SABER_indcpa.h create mode 100644 crypto_kem/lightsaber/avx2/SABER_params.h create mode 100644 crypto_kem/lightsaber/avx2/api.h create mode 100644 crypto_kem/lightsaber/avx2/cbd.c create mode 100644 crypto_kem/lightsaber/avx2/cbd.h create mode 100644 crypto_kem/lightsaber/avx2/kem.c create mode 100644 crypto_kem/lightsaber/avx2/kem.h create mode 100644 crypto_kem/lightsaber/avx2/pack_unpack.c create mode 100644 crypto_kem/lightsaber/avx2/pack_unpack.h create mode 100644 crypto_kem/lightsaber/avx2/poly.h create mode 100644 crypto_kem/lightsaber/avx2/polymul/consts.h create mode 100644 crypto_kem/lightsaber/avx2/polymul/matrix.c create mode 100644 crypto_kem/lightsaber/avx2/polymul/scm_avx.c create mode 100644 crypto_kem/lightsaber/avx2/polymul/toom-cook_4way.c create mode 100644 crypto_kem/lightsaber/avx2/verify.c create mode 100644 crypto_kem/lightsaber/avx2/verify.h create mode 100644 crypto_kem/saber/avx2/LICENSE create mode 100644 crypto_kem/saber/avx2/Makefile create mode 100644 crypto_kem/saber/avx2/SABER_indcpa.c create mode 100644 crypto_kem/saber/avx2/SABER_indcpa.h create mode 100644 crypto_kem/saber/avx2/SABER_params.h create mode 100644 crypto_kem/saber/avx2/api.h create mode 100644 crypto_kem/saber/avx2/cbd.c create mode 100644 crypto_kem/saber/avx2/cbd.h create mode 100644 crypto_kem/saber/avx2/kem.c create mode 100644 crypto_kem/saber/avx2/kem.h create mode 100644 crypto_kem/saber/avx2/pack_unpack.c create mode 100644 crypto_kem/saber/avx2/pack_unpack.h create mode 100644 crypto_kem/saber/avx2/poly.h create mode 100644 crypto_kem/saber/avx2/polymul/consts.h create mode 100644 crypto_kem/saber/avx2/polymul/matrix.c create mode 100644 crypto_kem/saber/avx2/polymul/scm_avx.c create mode 100644 crypto_kem/saber/avx2/polymul/toom-cook_4way.c create mode 100644 crypto_kem/saber/avx2/verify.c create mode 100644 crypto_kem/saber/avx2/verify.h create mode 100644 test/duplicate_consistency/firesaber_avx2.yml create mode 100644 test/duplicate_consistency/lightsaber_avx2.yml create mode 100644 test/duplicate_consistency/saber_avx2.yml diff --git a/crypto_kem/firesaber/META.yml b/crypto_kem/firesaber/META.yml index e58c7a7c..def16e46 100644 --- a/crypto_kem/firesaber/META.yml +++ b/crypto_kem/firesaber/META.yml @@ -14,4 +14,13 @@ principal-submitters: - Frederik Vercauteren implementations: - name: clean - version: https://github.com/KULeuven-COSIC/SABER/commit/14ede83f1ff3bcc41f0464543542366c68b55871 + version: https://github.com/KULeuven-COSIC/SABER/commit/509cc5ec3a7e12a751ccdd2ef5bd6e54e00bd350 + - name: avx2 + version: https://github.com/KULeuven-COSIC/SABER/commit/509cc5ec3a7e12a751ccdd2ef5bd6e54e00bd350 + supported_platforms: + - architecture: x86_64 + operating_systems: + - Linux + - Darwin + required_flags: + - avx2 diff --git a/crypto_kem/firesaber/avx2/LICENSE b/crypto_kem/firesaber/avx2/LICENSE new file mode 100644 index 00000000..d5d21fff --- /dev/null +++ b/crypto_kem/firesaber/avx2/LICENSE @@ -0,0 +1 @@ +Public Domain diff --git a/crypto_kem/firesaber/avx2/Makefile b/crypto_kem/firesaber/avx2/Makefile new file mode 100644 index 00000000..a44bbdb4 --- /dev/null +++ b/crypto_kem/firesaber/avx2/Makefile @@ -0,0 +1,22 @@ +# This Makefile can be used with GNU Make or BSD Make + +LIB=libfiresaber_avx2.a +HEADERS=api.h cbd.h kem.h pack_unpack.h poly.h SABER_indcpa.h SABER_params.h verify.h +OBJECTS=cbd.o kem.o pack_unpack.o SABER_indcpa.o verify.o + +CFLAGS=-O3 -mavx2 -Wall -Wextra -Wpedantic -Wvla -Werror -Wredundant-decls -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) + +all: $(LIB) + +%.o: %.s $(HEADERS) + $(AS) -o $@ $< + +%.o: %.c $(HEADERS) + $(CC) $(CFLAGS) -c -o $@ $< + +$(LIB): $(OBJECTS) + $(AR) -r $@ $(OBJECTS) + +clean: + $(RM) $(OBJECTS) + $(RM) $(LIB) diff --git a/crypto_kem/firesaber/avx2/SABER_indcpa.c b/crypto_kem/firesaber/avx2/SABER_indcpa.c new file mode 100644 index 00000000..ab017224 --- /dev/null +++ b/crypto_kem/firesaber/avx2/SABER_indcpa.c @@ -0,0 +1,416 @@ +#include "./polymul/toom-cook_4way.c" +#include "SABER_indcpa.h" +#include "SABER_params.h" +#include "api.h" +#include "cbd.h" +#include "fips202.h" +#include "pack_unpack.h" +#include "randombytes.h" +#include +#include +#include +//#include "randombytes.h" +//#include "./polymul/toom_cook_4/toom-cook_4way.c" + +#define h1 4 //2^(EQ-EP-1) + +#define h2 ( (1<<(SABER_EP-2)) - (1<<(SABER_EP-SABER_ET-1)) + (1<<(SABER_EQ-SABER_EP-1)) ) + + +static void POL2MSG(uint8_t *message_dec, const uint16_t *message_dec_unpacked) { + int32_t i, j; + + for (j = 0; j < SABER_KEYBYTES; j++) { + message_dec[j] = 0; + for (i = 0; i < 8; i++) { + message_dec[j] = message_dec[j] | (message_dec_unpacked[j * 8 + i] << i); + } + } +} + +/*----------------------------------------------------------------------------------- + This routine generates a=[Matrix K x K] of 256-coefficient polynomials +-------------------------------------------------------------------------------------*/ + +static void GenMatrix(polyvec *a, const uint8_t *seed) { + uint8_t buf[SABER_K * SABER_K * 13 * SABER_N / 8]; + + uint16_t temp_ar[SABER_N]; + + int i, j, k; + uint16_t mod = (SABER_Q - 1); + + shake128(buf, sizeof(buf), seed, SABER_SEEDBYTES); + + for (i = 0; i < SABER_K; i++) { + for (j = 0; j < SABER_K; j++) { + PQCLEAN_FIRESABER_AVX2_BS2POLq(temp_ar, buf + (i * SABER_K + j) * 13 * SABER_N / 8); + for (k = 0; k < SABER_N; k++) { + a[i].vec[j].coeffs[k] = (temp_ar[k])& mod ; + } + } + } +} + +static void GenSecret(uint16_t r[SABER_K][SABER_N], const uint8_t *seed) { + + uint32_t i; + + uint8_t buf[SABER_MU * SABER_N * SABER_K / 8]; + + shake128(buf, sizeof(buf), seed, SABER_NOISESEEDBYTES); + + for (i = 0; i < SABER_K; i++) { + PQCLEAN_FIRESABER_AVX2_cbd(r[i], buf + i * SABER_MU * SABER_N / 8); + } +} + +//********************************matrix-vector mul routines***************************************************** +static void matrix_vector_mul(__m256i a1_avx_combined[NUM_POLY][NUM_POLY][AVX_N1], __m256i b_bucket[NUM_POLY][SCHB_N * 4], __m256i res_avx[NUM_POLY][AVX_N1], int isTranspose) { + int64_t i, j; + + __m256i c_bucket[2 * SCM_SIZE * 4]; //Holds results for 9 Karatsuba at a time + + for (i = 0; i < NUM_POLY; i++) { + for (j = 0; j < NUM_POLY; j++) { + + if (isTranspose == 0) { + toom_cook_4way_avx_n1(a1_avx_combined[i][j], b_bucket[j], c_bucket, j); + } else { + toom_cook_4way_avx_n1(a1_avx_combined[j][i], b_bucket[j], c_bucket, j); + } + } + + TC_interpol(c_bucket, res_avx[i]); + } + +} + +static void vector_vector_mul(__m256i a_avx[NUM_POLY][AVX_N1], __m256i b_bucket[NUM_POLY][SCHB_N * 4], __m256i res_avx[AVX_N1]) { + + int64_t i; + + __m256i c_bucket[2 * SCM_SIZE * 4]; //Holds results for 9 Karatsuba at a time + + for (i = 0; i < NUM_POLY; i++) { + toom_cook_4way_avx_n1(a_avx[i], b_bucket[i], c_bucket, i); + } + TC_interpol(c_bucket, res_avx); +} + +//********************************matrix-vector mul routines***************************************************** + +void PQCLEAN_FIRESABER_AVX2_indcpa_kem_keypair(uint8_t *pk, uint8_t *sk) { + + polyvec a[SABER_K]; + + uint16_t skpv1[SABER_K][SABER_N]; + + + + uint8_t seed[SABER_SEEDBYTES]; + uint8_t noiseseed[SABER_COINBYTES]; + int32_t i, j, k; + + +//--------------AVX declaration------------------ + + __m256i sk_avx[SABER_K][SABER_N / 16]; + __m256i mod; + __m256i res_avx[SABER_K][SABER_N / 16]; + __m256i a_avx[SABER_K][SABER_K][SABER_N / 16]; + //__m256i acc[2*SABER_N/16]; + + mod = _mm256_set1_epi16(SABER_Q - 1); + + __m256i b_bucket[NUM_POLY][SCHB_N * 4]; + +//--------------AVX declaration ends------------------ + + randombytes(seed, SABER_SEEDBYTES); + + shake128(seed, SABER_SEEDBYTES, seed, SABER_SEEDBYTES); // for not revealing system RNG state + randombytes(noiseseed, SABER_COINBYTES); + + + GenMatrix(a, seed); //sample matrix A + + GenSecret(skpv1, noiseseed); + + +// Load sk into avx vectors + for (i = 0; i < SABER_K; i++) { + for (j = 0; j < SABER_N / 16; j++) { + sk_avx[i][j] = _mm256_loadu_si256 ((__m256i const *) (&skpv1[i][j * 16])); + } + + } + + // Load a into avx vectors + for (i = 0; i < SABER_K; i++) { + for (j = 0; j < SABER_K; j++) { + for (k = 0; k < SABER_N / 16; k++) { + a_avx[i][j][k] = _mm256_loadu_si256 ((__m256i const *) (&a[i].vec[j].coeffs[k * 16])); + } + } + } + + + + //------------------------do the matrix vector multiplication and rounding------------ + + for (j = 0; j < NUM_POLY; j++) { + TC_eval(sk_avx[j], b_bucket[j]); + } + matrix_vector_mul(a_avx, b_bucket, res_avx, 1);// Matrix-vector multiplication; Matrix in transposed order + + // Now truncation + + + for (i = 0; i < SABER_K; i++) { //shift right EQ-EP bits + for (j = 0; j < SABER_N / 16; j++) { + res_avx[i][j] = _mm256_add_epi16 (res_avx[i][j], _mm256_set1_epi16(h1)); + res_avx[i][j] = _mm256_srli_epi16 (res_avx[i][j], (SABER_EQ - SABER_EP) ); + res_avx[i][j] = _mm256_and_si256 (res_avx[i][j], mod); + } + } + + //------------------Pack sk into byte string------- + + PQCLEAN_FIRESABER_AVX2_POLVEC2BS(sk, (const uint16_t (*)[SABER_N])skpv1, SABER_Q); + + //------------------Pack pk into byte string------- + + for (i = 0; i < SABER_K; i++) { // reuses skpv1[] for unpacking avx of public-key + for (j = 0; j < SABER_N / 16; j++) { + _mm256_maskstore_epi32 ((int *) (skpv1[i] + j * 16), _mm256_set1_epi32(-1), res_avx[i][j]); + } + } + PQCLEAN_FIRESABER_AVX2_POLVEC2BS(pk, (const uint16_t (*)[SABER_N])skpv1, SABER_P); // load the public-key into pk byte string + + + for (i = 0; i < SABER_SEEDBYTES; i++) { // now load the seedbytes in PK. Easy since seed bytes are kept in byte format. + pk[SABER_POLYVECCOMPRESSEDBYTES + i] = seed[i]; + } + +} + + +void PQCLEAN_FIRESABER_AVX2_indcpa_kem_enc(uint8_t ciphertext[SABER_BYTES_CCA_DEC], const uint8_t m[SABER_KEYBYTES], const uint8_t noiseseed[SABER_NOISESEEDBYTES], const uint8_t pk[SABER_INDCPA_PUBLICKEYBYTES]) { + + + uint32_t i, j, k; + polyvec a[SABER_K]; // skpv; + uint8_t seed[SABER_SEEDBYTES]; + uint16_t pkcl[SABER_K][SABER_N]; //public key of received by the client + + + uint16_t skpv1[SABER_K][SABER_N]; + uint16_t temp[SABER_K][SABER_N]; + uint16_t message[SABER_KEYBYTES * 8]; + + uint8_t msk_c[SABER_SCALEBYTES_KEM]; + + //--------------AVX declaration------------------ + + __m256i sk_avx[SABER_K][SABER_N / 16]; + __m256i mod, mod_p; + __m256i res_avx[SABER_K][SABER_N / 16]; + __m256i vprime_avx[SABER_N / 16]; + __m256i a_avx[SABER_K][SABER_K][SABER_N / 16]; + //__m256i acc[2*SABER_N/16]; + + __m256i pkcl_avx[SABER_K][SABER_N / 16]; + + __m256i message_avx[SABER_N / 16]; + + mod = _mm256_set1_epi16(SABER_Q - 1); + mod_p = _mm256_set1_epi16(SABER_P - 1); + + + + __m256i b_bucket[NUM_POLY][SCHB_N * 4]; + + //--------------AVX declaration ends------------------ + for (i = 0; i < SABER_SEEDBYTES; i++) { // Load the seedbytes in the client seed from PK. + seed[i] = pk[ SABER_POLYVECCOMPRESSEDBYTES + i]; + } + + GenMatrix(a, seed); + GenSecret(skpv1, noiseseed); + + // ----------- Load skpv1 into avx vectors ---------- + for (i = 0; i < SABER_K; i++) { + for (j = 0; j < SABER_N / 16; j++) { + sk_avx[i][j] = _mm256_loadu_si256 ((__m256i const *) (&skpv1[i][j * 16])); + } + } + + // ----------- Load skpv1 into avx vectors ---------- + for (i = 0; i < SABER_K; i++) { + for (j = 0; j < SABER_K; j++) { + for (k = 0; k < SABER_N / 16; k++) { + a_avx[i][j][k] = _mm256_loadu_si256 ((__m256i const *) (&a[i].vec[j].coeffs[k * 16])); + } + } + } + //-----------------matrix-vector multiplication and rounding + + for (j = 0; j < NUM_POLY; j++) { + TC_eval(sk_avx[j], b_bucket[j]); + } + matrix_vector_mul(a_avx, b_bucket, res_avx, 0);// Matrix-vector multiplication; Matrix in normal order + + // Now truncation + + for (i = 0; i < SABER_K; i++) { //shift right EQ-EP bits + for (j = 0; j < SABER_N / 16; j++) { + res_avx[i][j] = _mm256_add_epi16 (res_avx[i][j], _mm256_set1_epi16(h1)); + res_avx[i][j] = _mm256_srli_epi16 (res_avx[i][j], (SABER_EQ - SABER_EP) ); + res_avx[i][j] = _mm256_and_si256 (res_avx[i][j], mod); + + } + } + + + //-----this result should be put in b_prime for later use in server. + for (i = 0; i < SABER_K; i++) { // first store in 16 bit arrays + for (j = 0; j < SABER_N / 16; j++) { + _mm256_maskstore_epi32 ((int *)(temp[i] + j * 16), _mm256_set1_epi32(-1), res_avx[i][j]); + } + } + + PQCLEAN_FIRESABER_AVX2_POLVEC2BS(ciphertext, (const uint16_t (*)[SABER_N])temp, SABER_P); // Pack b_prime into ciphertext byte string + +//**************client matrix-vector multiplication ends******************// + + //------now calculate the v' + + //-------unpack the public_key + PQCLEAN_FIRESABER_AVX2_BS2POLVEC(pkcl, pk, SABER_P); + + for (i = 0; i < SABER_K; i++) { + for (j = 0; j < SABER_N / 16; j++) { + pkcl_avx[i][j] = _mm256_loadu_si256 ((__m256i const *) (&pkcl[i][j * 16])); + } + } + + // InnerProduct + //for(k=0;k> i) & 0x01); + } + } + // message encoding + for (i = 0; i < SABER_N / 16; i++) { + message_avx[i] = _mm256_loadu_si256 ((__m256i const *) (&message[i * 16])); + message_avx[i] = _mm256_slli_epi16 (message_avx[i], (SABER_EP - 1) ); + } + + // SHIFTRIGHT(v'+h1-m mod p, EP-ET) + for (k = 0; k < SABER_N / 16; k++) { + vprime_avx[k] = _mm256_sub_epi16(vprime_avx[k], message_avx[k]); + vprime_avx[k] = _mm256_and_si256(vprime_avx[k], mod_p); + vprime_avx[k] = _mm256_srli_epi16 (vprime_avx[k], (SABER_EP - SABER_ET) ); + } + + // Unpack avx + for (j = 0; j < SABER_N / 16; j++) { + _mm256_maskstore_epi32 ((int *) (temp[0] + j * 16), _mm256_set1_epi32(-1), vprime_avx[j]); + } + + PQCLEAN_FIRESABER_AVX2_SABER_pack_6bit(msk_c, temp[0]); + + + for (j = 0; j < SABER_SCALEBYTES_KEM; j++) { + ciphertext[SABER_CIPHERTEXTBYTES + j] = msk_c[j]; + } + +} + + +void PQCLEAN_FIRESABER_AVX2_indcpa_kem_dec(uint8_t m[SABER_KEYBYTES], const uint8_t sk[SABER_INDCPA_SECRETKEYBYTES], const uint8_t ciphertext[SABER_BYTES_CCA_DEC]) { + + uint32_t i, j; + uint16_t sksv[SABER_K][SABER_N]; //secret key of the server + uint16_t pksv[SABER_K][SABER_N]; + uint16_t message_dec_unpacked[SABER_KEYBYTES * 8]; // one element containes on decrypted bit; + uint8_t scale_ar[SABER_SCALEBYTES_KEM]; + uint16_t op[SABER_N]; + + //--------------AVX declaration------------------ + + + //__m256i mod_p; + + __m256i v_avx[SABER_N / 16]; + + //__m256i acc[2*SABER_N/16]; + + __m256i sksv_avx[SABER_K][SABER_N / 16]; + __m256i pksv_avx[SABER_K][SABER_N / 16]; + + //mod_p=_mm256_set1_epi16(SABER_P-1); + + __m256i b_bucket[NUM_POLY][SCHB_N * 4]; + //--------------AVX declaration ends------------------ + + //-------unpack the public_key + + PQCLEAN_FIRESABER_AVX2_BS2POLVEC(sksv, sk, SABER_Q); //sksv is the secret-key + PQCLEAN_FIRESABER_AVX2_BS2POLVEC(pksv, ciphertext, SABER_P); //pksv is the ciphertext + + for (i = 0; i < SABER_K; i++) { + for (j = 0; j < SABER_N / 16; j++) { + sksv_avx[i][j] = _mm256_loadu_si256 ((__m256i const *) (&sksv[i][j * 16])); + pksv_avx[i][j] = _mm256_loadu_si256 ((__m256i const *) (&pksv[i][j * 16])); + } + } + + for (i = 0; i < SABER_N / 16; i++) { + v_avx[i] = _mm256_xor_si256(v_avx[i], v_avx[i]); + } + + + // InnerProduct(b', s, mod p) + + for (j = 0; j < NUM_POLY; j++) { + TC_eval(sksv_avx[j], b_bucket[j]); + } + + vector_vector_mul(pksv_avx, b_bucket, v_avx); + + for (i = 0; i < SABER_N / 16; i++) { + _mm256_maskstore_epi32 ((int *)(message_dec_unpacked + i * 16), _mm256_set1_epi32(-1), v_avx[i]); + } + + + for (i = 0; i < SABER_SCALEBYTES_KEM; i++) { + scale_ar[i] = ciphertext[SABER_CIPHERTEXTBYTES + i]; + } + + PQCLEAN_FIRESABER_AVX2_SABER_un_pack6bit(op, scale_ar); + + + //addition of h2 + for (i = 0; i < SABER_N; i++) { + message_dec_unpacked[i] = ( ( message_dec_unpacked[i] + h2 - (op[i] << (SABER_EP - SABER_ET)) ) & (SABER_P - 1) ) >> (SABER_EP - 1); + } + + + POL2MSG(m, message_dec_unpacked); +} diff --git a/crypto_kem/firesaber/avx2/SABER_indcpa.h b/crypto_kem/firesaber/avx2/SABER_indcpa.h new file mode 100644 index 00000000..1b6c8311 --- /dev/null +++ b/crypto_kem/firesaber/avx2/SABER_indcpa.h @@ -0,0 +1,13 @@ +#ifndef INDCPA_H +#define INDCPA_H +#include "SABER_params.h" +#include + +void PQCLEAN_FIRESABER_AVX2_indcpa_kem_keypair(uint8_t pk[SABER_INDCPA_PUBLICKEYBYTES], uint8_t sk[SABER_INDCPA_SECRETKEYBYTES]); + +void PQCLEAN_FIRESABER_AVX2_indcpa_kem_enc(uint8_t ciphertext[SABER_BYTES_CCA_DEC], const uint8_t m[SABER_KEYBYTES], const uint8_t noiseseed[SABER_NOISESEEDBYTES], const uint8_t pk[SABER_INDCPA_PUBLICKEYBYTES]); + +void PQCLEAN_FIRESABER_AVX2_indcpa_kem_dec(uint8_t m[SABER_KEYBYTES], const uint8_t sk[SABER_INDCPA_SECRETKEYBYTES], const uint8_t ciphertext[SABER_BYTES_CCA_DEC]); + + +#endif diff --git a/crypto_kem/firesaber/avx2/SABER_params.h b/crypto_kem/firesaber/avx2/SABER_params.h new file mode 100644 index 00000000..e1476b6a --- /dev/null +++ b/crypto_kem/firesaber/avx2/SABER_params.h @@ -0,0 +1,45 @@ +#ifndef PARAMS_H +#define PARAMS_H +#include "api.h" + + + + +#define SABER_K 4 +#define SABER_MU 6 +#define SABER_ET 6 + +#define SABER_EQ 13 +#define SABER_EP 10 + +#define SABER_N 256 +#define SABER_Q 8192 //2^13 +#define SABER_P 1024 + +#define SABER_SEEDBYTES 32 +#define SABER_NOISESEEDBYTES 32 +#define SABER_COINBYTES 32 +#define SABER_KEYBYTES 32 + +#define SABER_HASHBYTES 32 + +#define SABER_POLYBYTES 416 //13*256/8 + +#define SABER_POLYVECBYTES (SABER_K * SABER_POLYBYTES) + +#define SABER_POLYVECCOMPRESSEDBYTES (SABER_K * 320) //10*256/8 NOTE : changed till here due to parameter adaptation + +#define SABER_CIPHERTEXTBYTES (SABER_POLYVECCOMPRESSEDBYTES) + +#define SABER_SCALEBYTES_KEM ((SABER_ET)*SABER_N/8) + +#define SABER_INDCPA_PUBLICKEYBYTES (SABER_POLYVECCOMPRESSEDBYTES + SABER_SEEDBYTES) +#define SABER_INDCPA_SECRETKEYBYTES (SABER_POLYVECBYTES) + +#define SABER_PUBLICKEYBYTES (SABER_INDCPA_PUBLICKEYBYTES) + +#define SABER_SECRETKEYBYTES (SABER_INDCPA_SECRETKEYBYTES + SABER_INDCPA_PUBLICKEYBYTES + SABER_HASHBYTES + SABER_KEYBYTES) + +#define SABER_BYTES_CCA_DEC (SABER_POLYVECCOMPRESSEDBYTES + SABER_SCALEBYTES_KEM) /* Second part is for Targhi-Unruh */ + +#endif diff --git a/crypto_kem/firesaber/avx2/api.h b/crypto_kem/firesaber/avx2/api.h new file mode 100644 index 00000000..cb5240dd --- /dev/null +++ b/crypto_kem/firesaber/avx2/api.h @@ -0,0 +1,18 @@ +#ifndef PQCLEAN_FIRESABER_AVX2_API_H +#define PQCLEAN_FIRESABER_AVX2_API_H + + +#define PQCLEAN_FIRESABER_AVX2_CRYPTO_ALGNAME "FireSaber" +#define PQCLEAN_FIRESABER_AVX2_CRYPTO_BYTES 32 +#define PQCLEAN_FIRESABER_AVX2_CRYPTO_CIPHERTEXTBYTES 1472 +#define PQCLEAN_FIRESABER_AVX2_CRYPTO_PUBLICKEYBYTES 1312 +#define PQCLEAN_FIRESABER_AVX2_CRYPTO_SECRETKEYBYTES 3040 + +int PQCLEAN_FIRESABER_AVX2_crypto_kem_keypair(unsigned char *pk, unsigned char *sk); + +int PQCLEAN_FIRESABER_AVX2_crypto_kem_enc(unsigned char *ct, unsigned char *k, const unsigned char *pk); + +int PQCLEAN_FIRESABER_AVX2_crypto_kem_dec(unsigned char *k, const unsigned char *ct, const unsigned char *sk); + + +#endif /* PQCLEAN_FIRESABER_AVX2_API_H */ diff --git a/crypto_kem/firesaber/avx2/cbd.c b/crypto_kem/firesaber/avx2/cbd.c new file mode 100644 index 00000000..37970a81 --- /dev/null +++ b/crypto_kem/firesaber/avx2/cbd.c @@ -0,0 +1,52 @@ +#include "SABER_params.h" +#include "api.h" +#include "cbd.h" +#include +/*--------------------------------------------------------------------- +This file has been adapted from the implementation +(available at, Public Domain https://github.com/pq-crystals/kyber) +of "CRYSTALS – Kyber: a CCA-secure module-lattice-based KEM" +by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint, +Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle +----------------------------------------------------------------------*/ + + +static uint64_t load_littleendian(const unsigned char *x, int bytes) { + int i; + uint64_t r = x[0]; + for (i = 1; i < bytes; i++) { + r |= (uint64_t)x[i] << (8 * i); + } + return r; +} + + +void PQCLEAN_FIRESABER_AVX2_cbd(uint16_t *r, const unsigned char *buf) { + uint16_t Qmod_minus1 = SABER_Q - 1; + + uint32_t t, d, a[4], b[4]; + int i, j; + + for (i = 0; i < SABER_N / 4; i++) { + t = load_littleendian(buf + 3 * i, 3); + d = 0; + for (j = 0; j < 3; j++) { + d += (t >> j) & 0x249249; + } + + a[0] = d & 0x7; + b[0] = (d >> 3) & 0x7; + a[1] = (d >> 6) & 0x7; + b[1] = (d >> 9) & 0x7; + a[2] = (d >> 12) & 0x7; + b[2] = (d >> 15) & 0x7; + a[3] = (d >> 18) & 0x7; + b[3] = (d >> 21); + + r[4 * i + 0] = (uint16_t)(a[0] - b[0]) & Qmod_minus1; + r[4 * i + 1] = (uint16_t)(a[1] - b[1]) & Qmod_minus1; + r[4 * i + 2] = (uint16_t)(a[2] - b[2]) & Qmod_minus1; + r[4 * i + 3] = (uint16_t)(a[3] - b[3]) & Qmod_minus1; + + } +} diff --git a/crypto_kem/firesaber/avx2/cbd.h b/crypto_kem/firesaber/avx2/cbd.h new file mode 100644 index 00000000..210bcc50 --- /dev/null +++ b/crypto_kem/firesaber/avx2/cbd.h @@ -0,0 +1,16 @@ +#ifndef CBD_H +#define CBD_H +/*--------------------------------------------------------------------- +This file has been adapted from the implementation +(available at, Public Domain https://github.com/pq-crystals/kyber) +of "CRYSTALS – Kyber: a CCA-secure module-lattice-based KEM" +by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint, +Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle +----------------------------------------------------------------------*/ +#include "poly.h" +#include + +void PQCLEAN_FIRESABER_AVX2_cbd(uint16_t *r, const unsigned char *buf); + + +#endif diff --git a/crypto_kem/firesaber/avx2/kem.c b/crypto_kem/firesaber/avx2/kem.c new file mode 100644 index 00000000..2e72e6aa --- /dev/null +++ b/crypto_kem/firesaber/avx2/kem.c @@ -0,0 +1,79 @@ +#include "SABER_indcpa.h" +#include "SABER_params.h" +#include "api.h" +#include "fips202.h" +#include "randombytes.h" +#include "verify.h" +#include +#include +#include +#include + + +int PQCLEAN_FIRESABER_AVX2_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) { + int i; + + PQCLEAN_FIRESABER_AVX2_indcpa_kem_keypair(pk, sk); // sk[0:SABER_INDCPA_SECRETKEYBYTES-1] <-- sk + for (i = 0; i < SABER_INDCPA_PUBLICKEYBYTES; i++) { + sk[i + SABER_INDCPA_SECRETKEYBYTES] = pk[i]; // sk[SABER_INDCPA_SECRETKEYBYTES:SABER_INDCPA_SECRETKEYBYTES+SABER_INDCPA_SECRETKEYBYTES-1] <-- pk + } + + sha3_256(sk + SABER_SECRETKEYBYTES - 64, pk, SABER_INDCPA_PUBLICKEYBYTES); // Then hash(pk) is appended. + + randombytes(sk + SABER_SECRETKEYBYTES - SABER_KEYBYTES, SABER_KEYBYTES); // Remaining part of sk contains a pseudo-random number. + // This is output when check in PQCLEAN_FIRESABER_AVX2_crypto_kem_dec() fails. + return (0); +} + +int PQCLEAN_FIRESABER_AVX2_crypto_kem_enc(uint8_t *c, uint8_t *k, const uint8_t *pk) { + + uint8_t kr[64]; // Will contain key, coins + uint8_t buf[64]; + + randombytes(buf, 32); + + sha3_256(buf, buf, 32); // BUF[0:31] <-- random message (will be used as the key for client) Note: hash doesnot release system RNG output + + sha3_256(buf + 32, pk, SABER_INDCPA_PUBLICKEYBYTES); // BUF[32:63] <-- Hash(public key); Multitarget countermeasure for coins + contributory KEM + + sha3_512(kr, buf, 64); // kr[0:63] <-- Hash(buf[0:63]); + // K^ <-- kr[0:31] + // noiseseed (r) <-- kr[32:63]; + PQCLEAN_FIRESABER_AVX2_indcpa_kem_enc(c, buf, (const uint8_t *) (kr + 32), pk); // buf[0:31] contains message; kr[32:63] contains randomness r; + + sha3_256(kr + 32, c, SABER_BYTES_CCA_DEC); + + sha3_256(k, kr, 64); // hash concatenation of pre-k and h(c) to k + + return (0); +} + +int PQCLEAN_FIRESABER_AVX2_crypto_kem_dec(uint8_t *k, const uint8_t *c, const uint8_t *sk) { + int i; + uint8_t fail; + uint8_t cmp[SABER_BYTES_CCA_DEC]; + uint8_t buf[64]; + uint8_t kr[64]; // Will contain key, coins + const uint8_t *pk = sk + SABER_INDCPA_SECRETKEYBYTES; + + PQCLEAN_FIRESABER_AVX2_indcpa_kem_dec(buf, sk, c); // buf[0:31] <-- message + + // Multitarget countermeasure for coins + contributory KEM + for (i = 0; i < 32; i++) { // Save hash by storing h(pk) in sk + buf[32 + i] = sk[SABER_SECRETKEYBYTES - 64 + i]; + } + + sha3_512(kr, buf, 64); + + PQCLEAN_FIRESABER_AVX2_indcpa_kem_enc(cmp, buf, (const uint8_t *) (kr + 32), pk); + + fail = PQCLEAN_FIRESABER_AVX2_verify(c, cmp, SABER_BYTES_CCA_DEC); + + sha3_256(kr + 32, c, SABER_BYTES_CCA_DEC); // overwrite coins in kr with h(c) + + PQCLEAN_FIRESABER_AVX2_cmov(kr, sk + SABER_SECRETKEYBYTES - SABER_KEYBYTES, SABER_KEYBYTES, fail); + + sha3_256(k, kr, 64); // hash concatenation of pre-k and h(c) to k + + return (0); +} diff --git a/crypto_kem/firesaber/avx2/kem.h b/crypto_kem/firesaber/avx2/kem.h new file mode 100644 index 00000000..a55514d9 --- /dev/null +++ b/crypto_kem/firesaber/avx2/kem.h @@ -0,0 +1,35 @@ +#ifndef INDCPA_H +#define INDCPA_H + +#include + +void PQCLEAN_FIRESABER_AVX2_indcpa_keypair(uint8_t *pk, uint8_t *sk); + + +void PQCLEAN_FIRESABER_AVX2_indcpa_client(uint8_t *pk, uint8_t *b_prime, uint8_t *c, uint8_t *key); + + +void PQCLEAN_FIRESABER_AVX2_indcpa_server(uint8_t *pk, uint8_t *b_prime, uint8_t *c, uint8_t *key); + + +void PQCLEAN_FIRESABER_AVX2_indcpa_kem_keypair(uint8_t *pk, uint8_t *sk); + +void PQCLEAN_FIRESABER_AVX2_indcpa_kem_enc(uint8_t *message, uint8_t *noiseseed, uint8_t *pk, uint8_t *ciphertext); + +void PQCLEAN_FIRESABER_AVX2_indcpa_kem_dec(uint8_t *sk, uint8_t *ciphertext, uint8_t message_dec[]); + + +int PQCLEAN_FIRESABER_AVX2_crypto_kem_keypair(unsigned char *pk, unsigned char *sk); + +int PQCLEAN_FIRESABER_AVX2_crypto_kem_enc(unsigned char *c, unsigned char *k, const unsigned char *pk); + +int PQCLEAN_FIRESABER_AVX2_crypto_kem_dec(unsigned char *k, const unsigned char *c, const unsigned char *sk); + + + +//uint64_t clock1,clock2; + +//uint64_t clock_kp_kex, clock_enc_kex, clock_dec_kex; + + +#endif diff --git a/crypto_kem/firesaber/avx2/pack_unpack.c b/crypto_kem/firesaber/avx2/pack_unpack.c new file mode 100644 index 00000000..33c481b3 --- /dev/null +++ b/crypto_kem/firesaber/avx2/pack_unpack.c @@ -0,0 +1,502 @@ +#include "pack_unpack.h" + + +void PQCLEAN_FIRESABER_AVX2_SABER_pack_3bit(uint8_t *bytes, const uint16_t *data) { + + uint32_t j; + uint32_t offset_data = 0, offset_byte = 0; + + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = 3 * j; + offset_data = 8 * j; + bytes[offset_byte + 0] = (data[offset_data + 0] & 0x7) | ( (data[offset_data + 1] & 0x7) << 3 ) | ((data[offset_data + 2] & 0x3) << 6); + bytes[offset_byte + 1] = ((data[offset_data + 2] >> 2 ) & 0x01) | ( (data[offset_data + 3] & 0x7) << 1 ) | ( (data[offset_data + 4] & 0x7) << 4 ) | (((data[offset_data + 5]) & 0x01) << 7); + bytes[offset_byte + 2] = ((data[offset_data + 5] >> 1 ) & 0x03) | ( (data[offset_data + 6] & 0x7) << 2 ) | ( (data[offset_data + 7] & 0x7) << 5 ); + } +} + +void PQCLEAN_FIRESABER_AVX2_SABER_un_pack3bit(uint16_t *data, const uint8_t *bytes) { + + uint32_t j; + uint32_t offset_data = 0, offset_byte = 0; + + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = 3 * j; + offset_data = 8 * j; + data[offset_data + 0] = (bytes[offset_byte + 0]) & 0x07; + data[offset_data + 1] = ( (bytes[offset_byte + 0]) >> 3 ) & 0x07; + data[offset_data + 2] = ( ( (bytes[offset_byte + 0]) >> 6 ) & 0x03) | ( ( (bytes[offset_byte + 1]) & 0x01) << 2 ); + data[offset_data + 3] = ( (bytes[offset_byte + 1]) >> 1 ) & 0x07; + data[offset_data + 4] = ( (bytes[offset_byte + 1]) >> 4 ) & 0x07; + data[offset_data + 5] = ( ( (bytes[offset_byte + 1]) >> 7 ) & 0x01) | ( ( (bytes[offset_byte + 2]) & 0x03) << 1 ); + data[offset_data + 6] = ( (bytes[offset_byte + 2] >> 2) & 0x07 ); + data[offset_data + 7] = ( (bytes[offset_byte + 2] >> 5) & 0x07 ); + } + +} + +void PQCLEAN_FIRESABER_AVX2_SABER_pack_4bit(uint8_t *bytes, const uint16_t *data) { + + uint32_t j; + uint32_t offset_data = 0; + + for (j = 0; j < SABER_N / 2; j++) { + offset_data = 2 * j; + bytes[j] = (data[offset_data] & 0x0f) | ( (data[offset_data + 1] & 0x0f) << 4 ); + } +} + +void PQCLEAN_FIRESABER_AVX2_SABER_un_pack4bit(uint16_t *data, const uint8_t *bytes) { + + uint32_t j; + uint32_t offset_data = 0; + + for (j = 0; j < SABER_N / 2; j++) { + offset_data = 2 * j; + data[offset_data] = bytes[j] & 0x0f; + data[offset_data + 1] = (bytes[j] >> 4) & 0x0f; + } +} + +void PQCLEAN_FIRESABER_AVX2_SABER_pack_6bit(uint8_t *bytes, const uint16_t *data) { + + uint32_t j; + uint32_t offset_data = 0, offset_byte = 0; + + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = 3 * j; + offset_data = 4 * j; + bytes[offset_byte + 0] = (data[offset_data + 0] & 0x3f) | ((data[offset_data + 1] & 0x03) << 6); + bytes[offset_byte + 1] = ((data[offset_data + 1] >> 2) & 0x0f) | ((data[offset_data + 2] & 0x0f) << 4); + bytes[offset_byte + 2] = ((data[offset_data + 2] >> 4) & 0x03) | ((data[offset_data + 3] & 0x3f) << 2); + } +} + + +void PQCLEAN_FIRESABER_AVX2_SABER_un_pack6bit(uint16_t *data, const uint8_t *bytes) { + + uint32_t j; + uint32_t offset_data = 0, offset_byte = 0; + + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = 3 * j; + offset_data = 4 * j; + data[offset_data + 0] = bytes[offset_byte + 0] & 0x3f; + data[offset_data + 1] = ((bytes[offset_byte + 0] >> 6) & 0x03) | ((bytes[offset_byte + 1] & 0x0f) << 2) ; + data[offset_data + 2] = ((bytes[offset_byte + 1] & 0xff) >> 4) | ((bytes[offset_byte + 2] & 0x03) << 4) ; + data[offset_data + 3] = ((bytes[offset_byte + 2] & 0xff) >> 2); + } + +} + +void PQCLEAN_FIRESABER_AVX2_SABER_pack10bit(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 10) / 8; + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = offset_byte1 + 5 * j; + offset_data = 4 * j; + bytes[offset_byte + 0] = ( data[i][ offset_data + 0 ] & (0xff)); + + bytes[offset_byte + 1] = ( (data[i][ offset_data + 0 ] >> 8) & 0x03 ) | ((data[i][ offset_data + 1 ] & 0x3f) << 2); + + bytes[offset_byte + 2] = ( (data[i][ offset_data + 1 ] >> 6) & 0x0f ) | ( (data[i][ offset_data + 2 ] & 0x0f) << 4); + + bytes[offset_byte + 3] = ( (data[i][ offset_data + 2 ] >> 4) & 0x3f ) | ((data[i][ offset_data + 3 ] & 0x03) << 6); + + bytes[offset_byte + 4] = ( (data[i][ offset_data + 3 ] >> 2) & 0xff ); + } + } +} + +void PQCLEAN_FIRESABER_AVX2_POLVECp2BS(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 10) / 8; + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = offset_byte1 + 5 * j; + offset_data = 4 * j; + bytes[offset_byte + 0] = ( data[i][ offset_data + 0 ] & (0xff)); + + bytes[offset_byte + 1] = ( (data[i][ offset_data + 0 ] >> 8) & 0x03 ) | ((data[i][ offset_data + 1 ] & 0x3f) << 2); + + bytes[offset_byte + 2] = ( (data[i][ offset_data + 1 ] >> 6) & 0x0f ) | ( (data[i][ offset_data + 2 ] & 0x0f) << 4); + + bytes[offset_byte + 3] = ( (data[i][ offset_data + 2 ] >> 4) & 0x3f ) | ((data[i][ offset_data + 3 ] & 0x03) << 6); + + bytes[offset_byte + 4] = ( (data[i][ offset_data + 3 ] >> 2) & 0xff ); + } + } +} + +void PQCLEAN_FIRESABER_AVX2_POLVECq2BS(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 13) / 8; + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = offset_byte1 + 13 * j; + offset_data = 8 * j; + bytes[offset_byte + 0] = ( data[i][ offset_data + 0 ] & (0xff)); + + bytes[offset_byte + 1] = ( (data[i][ offset_data + 0 ] >> 8) & 0x1f ) | ((data[i][ offset_data + 1 ] & 0x07) << 5); + + bytes[offset_byte + 2] = ( (data[i][ offset_data + 1 ] >> 3) & 0xff ); + + bytes[offset_byte + 3] = ( (data[i][ offset_data + 1 ] >> 11) & 0x03 ) | ((data[i][ offset_data + 2 ] & 0x3f) << 2); + + bytes[offset_byte + 4] = ( (data[i][ offset_data + 2 ] >> 6) & 0x7f ) | ( (data[i][ offset_data + 3 ] & 0x01) << 7 ); + + bytes[offset_byte + 5] = ( (data[i][ offset_data + 3 ] >> 1) & 0xff ); + + bytes[offset_byte + 6] = ( (data[i][ offset_data + 3 ] >> 9) & 0x0f ) | ( (data[i][ offset_data + 4 ] & 0x0f) << 4 ); + + bytes[offset_byte + 7] = ( (data[i][ offset_data + 4] >> 4) & 0xff ); + + bytes[offset_byte + 8] = ( (data[i][ offset_data + 4 ] >> 12) & 0x01 ) | ( (data[i][ offset_data + 5 ] & 0x7f) << 1 ); + + bytes[offset_byte + 9] = ( (data[i][ offset_data + 5 ] >> 7) & 0x3f ) | ( (data[i][ offset_data + 6 ] & 0x03) << 6 ); + + bytes[offset_byte + 10] = ( (data[i][ offset_data + 6 ] >> 2) & 0xff ); + + bytes[offset_byte + 11] = ( (data[i][ offset_data + 6 ] >> 10) & 0x07 ) | ( (data[i][ offset_data + 7 ] & 0x1f) << 3 ); + + bytes[offset_byte + 12] = ( (data[i][ offset_data + 7 ] >> 5) & 0xff ); + + } + } + + +} + +void PQCLEAN_FIRESABER_AVX2_BS2POLq(uint16_t data[SABER_N], const uint8_t *bytes) { + + uint32_t j; + uint32_t offset_data = 0, offset_byte = 0; + + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = 13 * j; + offset_data = 8 * j; + data[offset_data + 0] = ( bytes[ offset_byte + 0 ] & (0xff)) | ((bytes[offset_byte + 1] & 0x1f) << 8); + data[offset_data + 1] = ( bytes[ offset_byte + 1 ] >> 5 & (0x07)) | ((bytes[offset_byte + 2] & 0xff) << 3) | ((bytes[offset_byte + 3] & 0x03) << 11); + data[offset_data + 2] = ( bytes[ offset_byte + 3 ] >> 2 & (0x3f)) | ((bytes[offset_byte + 4] & 0x7f) << 6); + data[offset_data + 3] = ( bytes[ offset_byte + 4 ] >> 7 & (0x01)) | ((bytes[offset_byte + 5] & 0xff) << 1) | ((bytes[offset_byte + 6] & 0x0f) << 9); + data[offset_data + 4] = ( bytes[ offset_byte + 6 ] >> 4 & (0x0f)) | ((bytes[offset_byte + 7] & 0xff) << 4) | ((bytes[offset_byte + 8] & 0x01) << 12); + data[offset_data + 5] = ( bytes[ offset_byte + 8] >> 1 & (0x7f)) | ((bytes[offset_byte + 9] & 0x3f) << 7); + data[offset_data + 6] = ( bytes[ offset_byte + 9] >> 6 & (0x03)) | ((bytes[offset_byte + 10] & 0xff) << 2) | ((bytes[offset_byte + 11] & 0x07) << 10); + data[offset_data + 7] = ( bytes[ offset_byte + 11] >> 3 & (0x1f)) | ((bytes[offset_byte + 12] & 0xff) << 5); + } +} + + + +void PQCLEAN_FIRESABER_AVX2_BS2POLVECp(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 10) / 8; + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = offset_byte1 + 5 * j; + offset_data = 4 * j; + data[i][offset_data + 0] = ( bytes[ offset_byte + 0 ] & (0xff)) | ((bytes[ offset_byte + 1 ] & 0x03) << 8); + data[i][offset_data + 1] = ( (bytes[ offset_byte + 1 ] >> 2) & (0x3f)) | ((bytes[ offset_byte + 2 ] & 0x0f) << 6); + data[i][offset_data + 2] = ( (bytes[ offset_byte + 2 ] >> 4) & (0x0f)) | ((bytes[ offset_byte + 3 ] & 0x3f) << 4); + data[i][offset_data + 3] = ( (bytes[ offset_byte + 3 ] >> 6) & (0x03)) | ((bytes[ offset_byte + 4 ] & 0xff) << 2); + + } + } +} + +void PQCLEAN_FIRESABER_AVX2_BS2POLVECq(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 13) / 8; + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = offset_byte1 + 13 * j; + offset_data = 8 * j; + data[i][offset_data + 0] = ( bytes[ offset_byte + 0 ] & (0xff)) | ((bytes[offset_byte + 1] & 0x1f) << 8); + data[i][offset_data + 1] = ( bytes[ offset_byte + 1 ] >> 5 & (0x07)) | ((bytes[offset_byte + 2] & 0xff) << 3) | ((bytes[offset_byte + 3] & 0x03) << 11); + data[i][offset_data + 2] = ( bytes[ offset_byte + 3 ] >> 2 & (0x3f)) | ((bytes[offset_byte + 4] & 0x7f) << 6); + data[i][offset_data + 3] = ( bytes[ offset_byte + 4 ] >> 7 & (0x01)) | ((bytes[offset_byte + 5] & 0xff) << 1) | ((bytes[offset_byte + 6] & 0x0f) << 9); + data[i][offset_data + 4] = ( bytes[ offset_byte + 6 ] >> 4 & (0x0f)) | ((bytes[offset_byte + 7] & 0xff) << 4) | ((bytes[offset_byte + 8] & 0x01) << 12); + data[i][offset_data + 5] = ( bytes[ offset_byte + 8] >> 1 & (0x7f)) | ((bytes[offset_byte + 9] & 0x3f) << 7); + data[i][offset_data + 6] = ( bytes[ offset_byte + 9] >> 6 & (0x03)) | ((bytes[offset_byte + 10] & 0xff) << 2) | ((bytes[offset_byte + 11] & 0x07) << 10); + data[i][offset_data + 7] = ( bytes[ offset_byte + 11] >> 3 & (0x1f)) | ((bytes[offset_byte + 12] & 0xff) << 5); + } + } + + +} + + + +void PQCLEAN_FIRESABER_AVX2_SABER_un_pack10bit(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 10) / 8; + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = offset_byte1 + 5 * j; + offset_data = 4 * j; + data[i][offset_data + 0] = ( bytes[ offset_byte + 0 ] & (0xff)) | ((bytes[ offset_byte + 1 ] & 0x03) << 8); + data[i][offset_data + 1] = ( (bytes[ offset_byte + 1 ] >> 2) & (0x3f)) | ((bytes[ offset_byte + 2 ] & 0x0f) << 6); + data[i][offset_data + 2] = ( (bytes[ offset_byte + 2 ] >> 4) & (0x0f)) | ((bytes[ offset_byte + 3 ] & 0x3f) << 4); + data[i][offset_data + 3] = ( (bytes[ offset_byte + 3 ] >> 6) & (0x03)) | ((bytes[ offset_byte + 4 ] & 0xff) << 2); + + } + } + + +} + + +void PQCLEAN_FIRESABER_AVX2_SABER_pack13bit(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 13) / 8; + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = offset_byte1 + 13 * j; + offset_data = 8 * j; + bytes[offset_byte + 0] = ( data[i][ offset_data + 0 ] & (0xff)); + + bytes[offset_byte + 1] = ( (data[i][ offset_data + 0 ] >> 8) & 0x1f ) | ((data[i][ offset_data + 1 ] & 0x07) << 5); + + bytes[offset_byte + 2] = ( (data[i][ offset_data + 1 ] >> 3) & 0xff ); + + bytes[offset_byte + 3] = ( (data[i][ offset_data + 1 ] >> 11) & 0x03 ) | ((data[i][ offset_data + 2 ] & 0x3f) << 2); + + bytes[offset_byte + 4] = ( (data[i][ offset_data + 2 ] >> 6) & 0x7f ) | ( (data[i][ offset_data + 3 ] & 0x01) << 7 ); + + bytes[offset_byte + 5] = ( (data[i][ offset_data + 3 ] >> 1) & 0xff ); + + bytes[offset_byte + 6] = ( (data[i][ offset_data + 3 ] >> 9) & 0x0f ) | ( (data[i][ offset_data + 4 ] & 0x0f) << 4 ); + + bytes[offset_byte + 7] = ( (data[i][ offset_data + 4] >> 4) & 0xff ); + + bytes[offset_byte + 8] = ( (data[i][ offset_data + 4 ] >> 12) & 0x01 ) | ( (data[i][ offset_data + 5 ] & 0x7f) << 1 ); + + bytes[offset_byte + 9] = ( (data[i][ offset_data + 5 ] >> 7) & 0x3f ) | ( (data[i][ offset_data + 6 ] & 0x03) << 6 ); + + bytes[offset_byte + 10] = ( (data[i][ offset_data + 6 ] >> 2) & 0xff ); + + bytes[offset_byte + 11] = ( (data[i][ offset_data + 6 ] >> 10) & 0x07 ) | ( (data[i][ offset_data + 7 ] & 0x1f) << 3 ); + + bytes[offset_byte + 12] = ( (data[i][ offset_data + 7 ] >> 5) & 0xff ); + + } + } + + +} + +void PQCLEAN_FIRESABER_AVX2_SABER_un_pack13bit(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 13) / 8; + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = offset_byte1 + 13 * j; + offset_data = 8 * j; + data[i][offset_data + 0] = ( bytes[ offset_byte + 0 ] & (0xff)) | ((bytes[offset_byte + 1] & 0x1f) << 8); + data[i][offset_data + 1] = ( bytes[ offset_byte + 1 ] >> 5 & (0x07)) | ((bytes[offset_byte + 2] & 0xff) << 3) | ((bytes[offset_byte + 3] & 0x03) << 11); + data[i][offset_data + 2] = ( bytes[ offset_byte + 3 ] >> 2 & (0x3f)) | ((bytes[offset_byte + 4] & 0x7f) << 6); + data[i][offset_data + 3] = ( bytes[ offset_byte + 4 ] >> 7 & (0x01)) | ((bytes[offset_byte + 5] & 0xff) << 1) | ((bytes[offset_byte + 6] & 0x0f) << 9); + data[i][offset_data + 4] = ( bytes[ offset_byte + 6 ] >> 4 & (0x0f)) | ((bytes[offset_byte + 7] & 0xff) << 4) | ((bytes[offset_byte + 8] & 0x01) << 12); + data[i][offset_data + 5] = ( bytes[ offset_byte + 8] >> 1 & (0x7f)) | ((bytes[offset_byte + 9] & 0x3f) << 7); + data[i][offset_data + 6] = ( bytes[ offset_byte + 9] >> 6 & (0x03)) | ((bytes[offset_byte + 10] & 0xff) << 2) | ((bytes[offset_byte + 11] & 0x07) << 10); + data[i][offset_data + 7] = ( bytes[ offset_byte + 11] >> 3 & (0x1f)) | ((bytes[offset_byte + 12] & 0xff) << 5); + } + } + + +} + +void PQCLEAN_FIRESABER_AVX2_SABER_poly_un_pack13bit(uint16_t data[SABER_N], const uint8_t *bytes) { + + uint32_t j; + uint32_t offset_data = 0, offset_byte = 0; + + //for(i=0;i> 5 & (0x07)) | ((bytes[offset_byte + 2] & 0xff) << 3) | ((bytes[offset_byte + 3] & 0x03) << 11); + data[offset_data + 2] = ( bytes[ offset_byte + 3 ] >> 2 & (0x3f)) | ((bytes[offset_byte + 4] & 0x7f) << 6); + data[offset_data + 3] = ( bytes[ offset_byte + 4 ] >> 7 & (0x01)) | ((bytes[offset_byte + 5] & 0xff) << 1) | ((bytes[offset_byte + 6] & 0x0f) << 9); + data[offset_data + 4] = ( bytes[ offset_byte + 6 ] >> 4 & (0x0f)) | ((bytes[offset_byte + 7] & 0xff) << 4) | ((bytes[offset_byte + 8] & 0x01) << 12); + data[offset_data + 5] = ( bytes[ offset_byte + 8] >> 1 & (0x7f)) | ((bytes[offset_byte + 9] & 0x3f) << 7); + data[offset_data + 6] = ( bytes[ offset_byte + 9] >> 6 & (0x03)) | ((bytes[offset_byte + 10] & 0xff) << 2) | ((bytes[offset_byte + 11] & 0x07) << 10); + data[offset_data + 7] = ( bytes[ offset_byte + 11] >> 3 & (0x1f)) | ((bytes[offset_byte + 12] & 0xff) << 5); + } + //} + + +} + + +void PQCLEAN_FIRESABER_AVX2_SABER_pack11bit(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]) { + /*This function packs 11 bit data stream into 8 bits of data. + */ + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 11) / 8; + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = offset_byte1 + 11 * j; + offset_data = 8 * j; + bytes[offset_byte + 0] = ( data[i][ offset_data + 0 ] & (0xff)); + + bytes[offset_byte + 1] = ( (data[i][ offset_data + 0 ] >> 8) & 0x07 ) | ((data[i][ offset_data + 1 ] & 0x1f) << 3); + + bytes[offset_byte + 2] = ( (data[i][ offset_data + 1 ] >> 5) & 0x3f ) | ((data[i][ offset_data + 2 ] & 0x03) << 6); + + bytes[offset_byte + 3] = ( (data[i][ offset_data + 2 ] >> 2) & 0xff ); + + bytes[offset_byte + 4] = ( (data[i][ offset_data + 2 ] >> 10) & 0x01 ) | ((data[i][ offset_data + 3 ] & 0x7f) << 1); + + bytes[offset_byte + 5] = ( (data[i][ offset_data + 3 ] >> 7) & 0x0f ) | ((data[i][ offset_data + 4 ] & 0x0f) << 4); + + bytes[offset_byte + 6] = ( (data[i][ offset_data + 4 ] >> 4) & 0x7f ) | ((data[i][ offset_data + 5 ] & 0x01) << 7); + + bytes[offset_byte + 7] = ( (data[i][ offset_data + 5 ] >> 1) & 0xff ); + + bytes[offset_byte + 8] = ( (data[i][ offset_data + 5 ] >> 9) & 0x03 ) | ((data[i][ offset_data + 6 ] & 0x3f) << 2); + + bytes[offset_byte + 9] = ( (data[i][ offset_data + 6 ] >> 6) & 0x1f ) | ((data[i][ offset_data + 7 ] & 0x07) << 5); + + bytes[offset_byte + 10] = ( (data[i][ offset_data + 7 ] >> 3) & 0xff ); + + } + } + +} + +void PQCLEAN_FIRESABER_AVX2_SABER_un_pack11bit(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 11) / 8; + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = offset_byte1 + 11 * j; + offset_data = 8 * j; + + data[i][offset_data + 0] = (bytes[offset_byte + 0]) | ( (bytes[offset_byte + 1] & 0x07) << 8 ); + + data[i][offset_data + 1] = ( (bytes[offset_byte + 1] >> 3) & 0x1f) | ( (bytes[offset_byte + 2] & 0x3f) << 5 ); + + data[i][offset_data + 2] = ( (bytes[offset_byte + 2] >> 6) & 0x03) | ( (bytes[offset_byte + 3] & 0xff) << 2 ) | ( (bytes[offset_byte + 4] & 0x01) << 10 ); + + data[i][offset_data + 3] = ( (bytes[offset_byte + 4] >> 1) & 0x7f) | ( (bytes[offset_byte + 5] & 0x0f) << 7 ); + + data[i][offset_data + 4] = ( (bytes[offset_byte + 5] >> 4) & 0x0f) | ( (bytes[offset_byte + 6] & 0x7f) << 4 ); + + data[i][offset_data + 5] = ( (bytes[offset_byte + 6] >> 7) & 0x01) | ( (bytes[offset_byte + 7] & 0xff) << 1 ) | ( (bytes[offset_byte + 8] & 0x03) << 9 ); + + data[i][offset_data + 6] = ( (bytes[offset_byte + 8] >> 2) & 0x3f) | ( (bytes[offset_byte + 9] & 0x1f) << 6 ); + + data[i][offset_data + 7] = ( (bytes[offset_byte + 9] >> 5) & 0x07) | ( (bytes[offset_byte + 10] & 0xff) << 3 ); + } + } + + +} + +void PQCLEAN_FIRESABER_AVX2_SABER_pack14bit(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 14) / 8; + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = offset_byte1 + 7 * j; + offset_data = 4 * j; + bytes[offset_byte + 0] = ( data[i][ offset_data + 0 ] & (0xff)); + + bytes[offset_byte + 1] = ( (data[i][ offset_data + 0 ] >> 8) & 0x3f ) | ((data[i][ offset_data + 1 ] & 0x03) << 6); + + bytes[offset_byte + 2] = ( (data[i][ offset_data + 1 ] >> 2) & 0xff ); + + bytes[offset_byte + 3] = ( (data[i][ offset_data + 1 ] >> 10) & 0x0f ) | ((data[i][ offset_data + 2 ] & 0x0f) << 4); + + bytes[offset_byte + 4] = ( (data[i][ offset_data + 2 ] >> 4) & 0xff ); + + bytes[offset_byte + 5] = ( (data[i][ offset_data + 2 ] >> 12) & 0x03 ) | ((data[i][ offset_data + 3 ] & 0x3f) << 2); + + bytes[offset_byte + 6] = ( (data[i][ offset_data + 3 ] >> 6) & 0xff ); + } + } + + +} + + +void PQCLEAN_FIRESABER_AVX2_SABER_un_pack14bit(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 14) / 8; + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = offset_byte1 + 7 * j; + offset_data = 4 * j; + data[i][offset_data + 0] = (bytes[offset_byte + 0] & 0xff) | ( (bytes[offset_byte + 1] & 0x3f) << 8 ); + + data[i][offset_data + 1] = ( (bytes[offset_byte + 1] >> 6) & 0x03) | ((bytes[offset_byte + 2] & 0xff) << 2 ) | ( (bytes[offset_byte + 3] & 0x0f) << 10 ); + + data[i][offset_data + 2] = ( (bytes[offset_byte + 3] >> 4) & 0x0f) | ( (bytes[offset_byte + 4] ) << 4 ) | ( (bytes[offset_byte + 5] & 0x03) << 12 ); + + data[i][offset_data + 3] = ( (bytes[offset_byte + 5] >> 2) & 0x3f) | ( (bytes[offset_byte + 6] ) << 6 ); + } + } + + +} + +void PQCLEAN_FIRESABER_AVX2_POLVEC2BS(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N], uint16_t modulus) { + + if (modulus == 1024) { + PQCLEAN_FIRESABER_AVX2_POLVECp2BS(bytes, data); + } else if (modulus == 8192) { + PQCLEAN_FIRESABER_AVX2_POLVECq2BS(bytes, data); + } +} + +void PQCLEAN_FIRESABER_AVX2_BS2POLVEC(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes, uint16_t modulus) { + + if (modulus == 1024) { + PQCLEAN_FIRESABER_AVX2_BS2POLVECp(data, bytes); + } else if (modulus == 8192) { + PQCLEAN_FIRESABER_AVX2_BS2POLVECq(data, bytes); + } + +} diff --git a/crypto_kem/firesaber/avx2/pack_unpack.h b/crypto_kem/firesaber/avx2/pack_unpack.h new file mode 100644 index 00000000..ba8a568f --- /dev/null +++ b/crypto_kem/firesaber/avx2/pack_unpack.h @@ -0,0 +1,56 @@ +#ifndef PACK_UNPACK_H +#define PACK_UNPACK_H +#include "SABER_params.h" +#include +#include + +void PQCLEAN_FIRESABER_AVX2_BS2POLq(uint16_t data[SABER_N], const uint8_t *bytes); + +void PQCLEAN_FIRESABER_AVX2_BS2POLVEC(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes, uint16_t modulus); + +void PQCLEAN_FIRESABER_AVX2_BS2POLVECq(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes); + +void PQCLEAN_FIRESABER_AVX2_BS2POLVECp(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes); + + +void PQCLEAN_FIRESABER_AVX2_POLVEC2BS(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N], uint16_t modulus); + +void PQCLEAN_FIRESABER_AVX2_POLVECq2BS(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]); + +void PQCLEAN_FIRESABER_AVX2_POLVECp2BS(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]); + + +void PQCLEAN_FIRESABER_AVX2_SABER_pack_3bit(uint8_t *bytes, const uint16_t *data); + +void PQCLEAN_FIRESABER_AVX2_SABER_pack_4bit(uint8_t *bytes, const uint16_t *data); + +void PQCLEAN_FIRESABER_AVX2_SABER_pack_6bit(uint8_t *bytes, const uint16_t *data); + +void PQCLEAN_FIRESABER_AVX2_SABER_pack10bit(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]); + +void PQCLEAN_FIRESABER_AVX2_SABER_pack11bit(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]); + +void PQCLEAN_FIRESABER_AVX2_SABER_pack13bit(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]); + +void PQCLEAN_FIRESABER_AVX2_SABER_pack14bit(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]); + + +void PQCLEAN_FIRESABER_AVX2_SABER_poly_un_pack13bit(uint16_t data[SABER_N], const uint8_t *bytes); + + +void PQCLEAN_FIRESABER_AVX2_SABER_un_pack3bit(uint16_t *data, const uint8_t *bytes); + +void PQCLEAN_FIRESABER_AVX2_SABER_un_pack4bit(uint16_t *data, const uint8_t *bytes); + +void PQCLEAN_FIRESABER_AVX2_SABER_un_pack6bit(uint16_t *data, const uint8_t *bytes); + +void PQCLEAN_FIRESABER_AVX2_SABER_un_pack10bit(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes); + +void PQCLEAN_FIRESABER_AVX2_SABER_un_pack11bit(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes); + +void PQCLEAN_FIRESABER_AVX2_SABER_un_pack13bit(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes); + +void PQCLEAN_FIRESABER_AVX2_SABER_un_pack14bit(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes); + + +#endif diff --git a/crypto_kem/firesaber/avx2/poly.h b/crypto_kem/firesaber/avx2/poly.h new file mode 100644 index 00000000..8443de34 --- /dev/null +++ b/crypto_kem/firesaber/avx2/poly.h @@ -0,0 +1,27 @@ +#ifndef POLY_H +#define POLY_H +/*--------------------------------------------------------------------- +This file has been adapted from the implementation +(available at, Public Domain https://github.com/pq-crystals/kyber) +of "CRYSTALS – Kyber: a CCA-secure module-lattice-based KEM" +by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint, +Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle +----------------------------------------------------------------------*/ +#include "SABER_params.h" +#include + +typedef struct { + uint16_t coeffs[SABER_N]; +} poly; + +typedef struct { + poly vec[SABER_K]; +} polyvec; + +void PQCLEAN_FIRESABER_AVX2_poly_getnoise(uint16_t *r, const unsigned char *seed, unsigned char nonce); + + +void PQCLEAN_FIRESABER_AVX2_poly_getnoise4x(uint16_t *r0, uint16_t *r1, uint16_t *r2, const unsigned char *seed, unsigned char nonce0, unsigned char nonce1, unsigned char nonce2, unsigned char nonce3); + + +#endif diff --git a/crypto_kem/firesaber/avx2/polymul/consts.h b/crypto_kem/firesaber/avx2/polymul/consts.h new file mode 100644 index 00000000..40826398 --- /dev/null +++ b/crypto_kem/firesaber/avx2/polymul/consts.h @@ -0,0 +1,20 @@ +#include "../SABER_params.h" + +#define AVX_N (SABER_N >> 4) +#define small_len_avx (AVX_N >> 2) + +#define SCHB_N 16 + +#define N_SB (SABER_N >> 2) +#define N_SB_RES (2*N_SB-1) + +#define N_SB_16 (N_SB >> 2) +#define N_SB_16_RES (2*N_SB_16-1) + +#define AVX_N1 16 /*N/16*/ + +#define SCM_SIZE 16 + +// The dimension of a vector. i.e vector has NUM_POLY elements and Matrix has NUM_POLY X NUM_POLY elements +#define NUM_POLY SABER_K +//int NUM_POLY=2; diff --git a/crypto_kem/firesaber/avx2/polymul/matrix.c b/crypto_kem/firesaber/avx2/polymul/matrix.c new file mode 100644 index 00000000..5fa35783 --- /dev/null +++ b/crypto_kem/firesaber/avx2/polymul/matrix.c @@ -0,0 +1,303 @@ +#include + +static void transpose_n1(__m256i *M) +{ + //int i; + register __m256i r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11; + register __m256i temp, temp0, temp1, temp2; + + //for(i=0; i<8; i=i+1) + //{ + r0 = _mm256_unpacklo_epi16(M[0], M[1]); + r1 = _mm256_unpacklo_epi16(M[2], M[3]); + r2 = _mm256_unpacklo_epi16(M[4], M[5]); + r3 = _mm256_unpacklo_epi16(M[6], M[7]); + r4 = _mm256_unpacklo_epi16(M[8], M[9]); + r5 = _mm256_unpacklo_epi16(M[10], M[11]); + r6 = _mm256_unpacklo_epi16(M[12], M[13]); + r7 = _mm256_unpacklo_epi16(M[14], M[15]); + + + temp = _mm256_unpacklo_epi32(r0, r1); + temp0 = _mm256_unpacklo_epi32(r2, r3); + temp1 = _mm256_unpacklo_epi32(r4, r5); + temp2 = _mm256_unpacklo_epi32(r6, r7); + + r8 = _mm256_unpackhi_epi32(r0, r1); + r9 = _mm256_unpackhi_epi32(r2, r3); + r10 = _mm256_unpackhi_epi32(r4, r5); + r11 = _mm256_unpackhi_epi32(r6, r7); + + r0 = _mm256_unpacklo_epi64(temp, temp0); + r2 = _mm256_unpackhi_epi64(temp, temp0); + + r1 = _mm256_unpacklo_epi64(temp1, temp2); + r3 = _mm256_unpackhi_epi64(temp1, temp2); + + temp = _mm256_unpackhi_epi16(M[0], M[1]); + temp0 = _mm256_unpackhi_epi16(M[2], M[3]); + temp1 = _mm256_unpackhi_epi16(M[4], M[5]); + temp2 = _mm256_unpackhi_epi16(M[6], M[7]); + r4 = _mm256_unpackhi_epi16(M[8], M[9]); + + M[0] = _mm256_permute2f128_si256(r0, r1, 0x20); + M[8] = _mm256_permute2f128_si256(r0, r1, 0x31); + M[1] = _mm256_permute2f128_si256(r2, r3, 0x20); + M[9] = _mm256_permute2f128_si256(r2, r3, 0x31); + + + r5 = _mm256_unpackhi_epi16(M[10], M[11]); + r6 = _mm256_unpackhi_epi16(M[12], M[13]); + r7 = _mm256_unpackhi_epi16(M[14], M[15]); + + + + r0 = _mm256_unpacklo_epi64(r8, r9); + r1 = _mm256_unpacklo_epi64(r10, r11); + + r2 = _mm256_unpackhi_epi64(r8, r9); + r3 = _mm256_unpackhi_epi64(r10, r11); + + + + M[3] = _mm256_permute2f128_si256(r2, r3, 0x20); + M[11] = _mm256_permute2f128_si256(r2, r3, 0x31); + M[2] = _mm256_permute2f128_si256(r0, r1, 0x20); + M[10] = _mm256_permute2f128_si256(r0, r1, 0x31); + + + //for(i=0; i<4; i=i+1) + //{ + r0 = _mm256_unpacklo_epi32(temp, temp0); + r1 = _mm256_unpacklo_epi32(temp1, temp2); + r2 = _mm256_unpacklo_epi32(r4, r5); + r3 = _mm256_unpacklo_epi32(r6, r7); + + //} + + + //for(i=0; i<2; i=i+1) + //{ + r8 = _mm256_unpacklo_epi64(r0, r1); + r10 = _mm256_unpackhi_epi64(r0, r1); + + r9 = _mm256_unpacklo_epi64(r2, r3); + r11 = _mm256_unpackhi_epi64(r2, r3); + + M[4] = _mm256_permute2f128_si256(r8, r9, 0x20); + M[12] = _mm256_permute2f128_si256(r8, r9, 0x31); + M[5] = _mm256_permute2f128_si256(r10, r11, 0x20); + M[13] = _mm256_permute2f128_si256(r10, r11, 0x31); + + r0 = _mm256_unpackhi_epi32(temp, temp0); + r1 = _mm256_unpackhi_epi32(temp1, temp2); + r2 = _mm256_unpackhi_epi32(r4, r5); + r3 = _mm256_unpackhi_epi32(r6, r7); + + //} +// for(i=0; i<2; i=i+1) +// { + r4 = _mm256_unpacklo_epi64(r0, r1); + r6 = _mm256_unpackhi_epi64(r0, r1); + + r5 = _mm256_unpacklo_epi64(r2, r3); + r7 = _mm256_unpackhi_epi64(r2, r3); + +// } + + //------------------------------------------------------- + + M[6] = _mm256_permute2f128_si256(r4, r5, 0x20); + M[14] = _mm256_permute2f128_si256(r4, r5, 0x31); + M[7] = _mm256_permute2f128_si256(r6, r7, 0x20); + M[15] = _mm256_permute2f128_si256(r6, r7, 0x31); +} + +/* +void transpose_unrolled(__m256i *M) +{ + int i; + __m256i tL[8], tH[8]; + __m256i bL[4], bH[4], cL[4], cH[4]; + __m256i dL[2], dH[2], eL[2], eH[2], fL[2], fH[2], gL[2], gH[2]; + + __m256i r0, r1, r2, r3, r4, r5, r6, r7; + + //for(i=0; i<8; i=i+1) + //{ + tL[0] = _mm256_unpacklo_epi16(M[0], M[1]); + tH[0] = _mm256_unpackhi_epi16(M[0], M[1]); + + tL[1] = _mm256_unpacklo_epi16(M[2], M[3]); + tH[1] = _mm256_unpackhi_epi16(M[2], M[3]); + + tL[2] = _mm256_unpacklo_epi16(M[4], M[5]); + tH[2] = _mm256_unpackhi_epi16(M[4], M[5]); + + tL[3] = _mm256_unpacklo_epi16(M[6], M[7]); + tH[3] = _mm256_unpackhi_epi16(M[6], M[7]); + + tL[4] = _mm256_unpacklo_epi16(M[8], M[9]); + tH[4] = _mm256_unpackhi_epi16(M[8], M[9]); + + tL[5] = _mm256_unpacklo_epi16(M[10], M[11]); + tH[5] = _mm256_unpackhi_epi16(M[10], M[11]); + + tL[6] = _mm256_unpacklo_epi16(M[12], M[13]); + tH[6] = _mm256_unpackhi_epi16(M[12], M[13]); + + tL[7] = _mm256_unpacklo_epi16(M[14], M[15]); + tH[7] = _mm256_unpackhi_epi16(M[14], M[15]); + + //} + + //------------------------------------------------------- + //for(i=0; i<4; i=i+1) + //{ + bL[0] = _mm256_unpacklo_epi32(tL[0], tL[1]); + bH[0] = _mm256_unpackhi_epi32(tL[0], tL[1]); + + bL[1] = _mm256_unpacklo_epi32(tL[2], tL[3]); + bH[1] = _mm256_unpackhi_epi32(tL[2], tL[3]); + + bL[2] = _mm256_unpacklo_epi32(tL[4], tL[5]); + bH[2] = _mm256_unpackhi_epi32(tL[4], tL[5]); + + bL[3] = _mm256_unpacklo_epi32(tL[6], tL[7]); + bH[3] = _mm256_unpackhi_epi32(tL[6], tL[7]); + + //} + + //for(i=0; i<2; i=i+1) + //{ + dL[0] = _mm256_unpacklo_epi64(bL[0], bL[1]); + dH[0] = _mm256_unpackhi_epi64(bL[0], bL[1]); + + dL[1] = _mm256_unpacklo_epi64(bL[2], bL[3]); + dH[1] = _mm256_unpackhi_epi64(bL[2], bL[3]); + + M[0] = _mm256_permute2f128_si256(dL[0], dL[1], 0x20); + M[8] = _mm256_permute2f128_si256(dL[0], dL[1], 0x31); + M[1] = _mm256_permute2f128_si256(dH[0], dH[1], 0x20); + M[9] = _mm256_permute2f128_si256(dH[0], dH[1], 0x31); + + //} + //for(i=0; i<2; i=i+1) + //{ + eL[0] = _mm256_unpacklo_epi64(bH[0], bH[1]); + eH[0] = _mm256_unpackhi_epi64(bH[0], bH[1]); + + eL[1] = _mm256_unpacklo_epi64(bH[2], bH[3]); + eH[1] = _mm256_unpackhi_epi64(bH[2], bH[3]); + + //} + + //------------------------------------------------------- + + //------------------------------------------------------- + for(i=0; i<4; i=i+1) + { + cL[i] = _mm256_unpacklo_epi32(tH[2*i], tH[2*i+1]); + cH[i] = _mm256_unpackhi_epi32(tH[2*i], tH[2*i+1]); + } + + + for(i=0; i<2; i=i+1) + { + fL[i] = _mm256_unpacklo_epi64(cL[2*i], cL[2*i+1]); + fH[i] = _mm256_unpackhi_epi64(cL[2*i], cL[2*i+1]); + } + for(i=0; i<2; i=i+1) + { + gL[i] = _mm256_unpacklo_epi64(cH[2*i], cH[2*i+1]); + gH[i] = _mm256_unpackhi_epi64(cH[2*i], cH[2*i+1]); + } + + //------------------------------------------------------- + + + + M[2] = _mm256_permute2f128_si256(eL[0], eL[1], 0x20); + M[10] = _mm256_permute2f128_si256(eL[0], eL[1], 0x31); + M[3] = _mm256_permute2f128_si256(eH[0], eH[1], 0x20); + M[11] = _mm256_permute2f128_si256(eH[0], eH[1], 0x31); + + M[4] = _mm256_permute2f128_si256(fL[0], fL[1], 0x20); + M[12] = _mm256_permute2f128_si256(fL[0], fL[1], 0x31); + M[5] = _mm256_permute2f128_si256(fH[0], fH[1], 0x20); + M[13] = _mm256_permute2f128_si256(fH[0], fH[1], 0x31); + + M[6] = _mm256_permute2f128_si256(gL[0], gL[1], 0x20); + M[14] = _mm256_permute2f128_si256(gL[0], gL[1], 0x31); + M[7] = _mm256_permute2f128_si256(gH[0], gH[1], 0x20); + M[15] = _mm256_permute2f128_si256(gH[0], gH[1], 0x31); +} + + +void transpose1(__m256i *M) +{ + int i; + __m256i tL[8], tH[8]; + __m256i bL[4], bH[4], cL[4], cH[4]; + __m256i dL[2], dH[2], eL[2], eH[2], fL[2], fH[2], gL[2], gH[2]; + + for(i=0; i<8; i=i+1) + { + tL[i] = _mm256_unpacklo_epi16(M[2*i], M[2*i+1]); + tH[i] = _mm256_unpackhi_epi16(M[2*i], M[2*i+1]); + } + + for(i=0; i<4; i=i+1) + { + bL[i] = _mm256_unpacklo_epi32(tL[2*i], tL[2*i+1]); + bH[i] = _mm256_unpackhi_epi32(tL[2*i], tL[2*i+1]); + } + for(i=0; i<4; i=i+1) + { + cL[i] = _mm256_unpacklo_epi32(tH[2*i], tH[2*i+1]); + cH[i] = _mm256_unpackhi_epi32(tH[2*i], tH[2*i+1]); + } + + for(i=0; i<2; i=i+1) + { + dL[i] = _mm256_unpacklo_epi64(bL[2*i], bL[2*i+1]); + dH[i] = _mm256_unpackhi_epi64(bL[2*i], bL[2*i+1]); + } + for(i=0; i<2; i=i+1) + { + eL[i] = _mm256_unpacklo_epi64(bH[2*i], bH[2*i+1]); + eH[i] = _mm256_unpackhi_epi64(bH[2*i], bH[2*i+1]); + } + + for(i=0; i<2; i=i+1) + { + fL[i] = _mm256_unpacklo_epi64(cL[2*i], cL[2*i+1]); + fH[i] = _mm256_unpackhi_epi64(cL[2*i], cL[2*i+1]); + } + for(i=0; i<2; i=i+1) + { + gL[i] = _mm256_unpacklo_epi64(cH[2*i], cH[2*i+1]); + gH[i] = _mm256_unpackhi_epi64(cH[2*i], cH[2*i+1]); + } + + M[0] = _mm256_permute2f128_si256(dL[0], dL[1], 0x20); + M[8] = _mm256_permute2f128_si256(dL[0], dL[1], 0x31); + M[1] = _mm256_permute2f128_si256(dH[0], dH[1], 0x20); + M[9] = _mm256_permute2f128_si256(dH[0], dH[1], 0x31); + + M[2] = _mm256_permute2f128_si256(eL[0], eL[1], 0x20); + M[10] = _mm256_permute2f128_si256(eL[0], eL[1], 0x31); + M[3] = _mm256_permute2f128_si256(eH[0], eH[1], 0x20); + M[11] = _mm256_permute2f128_si256(eH[0], eH[1], 0x31); + + M[4] = _mm256_permute2f128_si256(fL[0], fL[1], 0x20); + M[12] = _mm256_permute2f128_si256(fL[0], fL[1], 0x31); + M[5] = _mm256_permute2f128_si256(fH[0], fH[1], 0x20); + M[13] = _mm256_permute2f128_si256(fH[0], fH[1], 0x31); + + M[6] = _mm256_permute2f128_si256(gL[0], gL[1], 0x20); + M[14] = _mm256_permute2f128_si256(gL[0], gL[1], 0x31); + M[7] = _mm256_permute2f128_si256(gH[0], gH[1], 0x20); + M[15] = _mm256_permute2f128_si256(gH[0], gH[1], 0x31); +} +*/ diff --git a/crypto_kem/firesaber/avx2/polymul/scm_avx.c b/crypto_kem/firesaber/avx2/polymul/scm_avx.c new file mode 100644 index 00000000..4e4f11f8 --- /dev/null +++ b/crypto_kem/firesaber/avx2/polymul/scm_avx.c @@ -0,0 +1,753 @@ +//#define SCM_SIZE 16 + +//#pragma STDC FP_CONTRACT ON + +#include + +inline __m256i mul_add(__m256i a, __m256i b, __m256i c) { + return _mm256_add_epi16(_mm256_mullo_epi16(a, b), c); +} + + +static void schoolbook_avx_new3_acc(__m256i* a, __m256i* b, __m256i* c_avx) ////8 coefficients of a and b has been prefetched + //the c_avx are added cummulatively +{ + + register __m256i a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7; + register __m256i temp; + + + a0=a[0]; + a1=a[1]; + a2=a[2]; + a3=a[3]; + a4=a[4]; + a5=a[5]; + a6=a[6]; + a7=a[7]; + + b0=b[0]; + b1=b[1]; + b2=b[2]; + b3=b[3]; + b4=b[4]; + b5=b[5]; + b6=b[6]; + b7=b[7]; + + // New Unrolled first triangle + + //otherwise accumulate + c_avx[0] = mul_add(a0, b0, c_avx[0]); + + + temp = _mm256_mullo_epi16 (a0, b1); + temp=mul_add(a1, b0, temp); + c_avx[1] = _mm256_add_epi16(temp, c_avx[1]); + + + temp = _mm256_mullo_epi16 (a0, b2); + temp = mul_add(a1, b1, temp); + temp=mul_add(a2, b0, temp); + c_avx[2] = _mm256_add_epi16(temp, c_avx[2]); + + + temp = _mm256_mullo_epi16 (a0, b3); + temp = mul_add(a1, b2, temp); + temp = mul_add(a2, b1, temp); + temp=mul_add(a3, b0, temp); + c_avx[3] = _mm256_add_epi16(temp, c_avx[3]); + + temp = _mm256_mullo_epi16 (a0, b4); + temp = mul_add(a1, b3, temp); + temp = mul_add(a3, b1, temp); + temp = mul_add(a4, b0, temp); + temp=mul_add(a2, b2, temp); + c_avx[4] = _mm256_add_epi16(temp, c_avx[4]); + + + temp = _mm256_mullo_epi16 (a0, b5); + temp = mul_add(a1, b4 , temp); + temp = mul_add(a2, b3, temp); + temp = mul_add(a3, b2, temp); + temp = mul_add( a4, b1, temp); + temp=mul_add(a5, b0, temp); + c_avx[5] = _mm256_add_epi16(temp, c_avx[5]); + + temp = _mm256_mullo_epi16 (a0, b6); + temp = mul_add(a1, b5, temp); + temp = mul_add(a5, b1, temp); + temp = mul_add(a6, b0, temp); + temp = mul_add(a2, b4, temp); + temp = mul_add(a3, b3, temp); + temp=mul_add(a4, b2, temp); + c_avx[6] = _mm256_add_epi16(temp, c_avx[6]); + + + temp = _mm256_mullo_epi16 (a0, b7); + temp = mul_add(a1, b6, temp); + temp = mul_add (a6, b1, temp); + temp = mul_add (a7, b0, temp); + temp = mul_add(a2, b5, temp); + temp = mul_add (a3, b4, temp); + temp = mul_add (a4, b3, temp); + temp=mul_add(a5, b2, temp); + c_avx[7] = _mm256_add_epi16(temp, c_avx[7]); + + temp = _mm256_mullo_epi16 (a0, b[8]); + temp = mul_add (a1, b7, temp); + temp = mul_add (a7, b1, temp); + temp = mul_add (a[8], b0, temp); + temp = mul_add (a2, b6,temp); + temp = mul_add(a3, b5, temp); + temp = mul_add (a4, b4,temp); + temp = mul_add (a5, b3, temp); + + temp=mul_add(a6, b2, temp); + c_avx[8] = _mm256_add_epi16(temp, c_avx[8]); + + + temp = _mm256_mullo_epi16 (a0, b[9]); + temp = mul_add (a1, b[8], temp); + temp = mul_add (a[8], b1, temp); + temp = mul_add (a[9], b0, temp); + temp = mul_add (a2, b7, temp); + temp = mul_add (a3, b6, temp); + temp = mul_add (a4, b5, temp); + temp = mul_add (a5, b4, temp); + temp = mul_add (a6, b3, temp); + temp=mul_add(a7, b2, temp); + c_avx[9] = _mm256_add_epi16(temp, c_avx[9]); + + + temp= _mm256_mullo_epi16 (a0, b[10]); + temp = mul_add (a1, b[9], temp); + temp = mul_add (a[9], b1, temp); + temp = mul_add (a[10], b0, temp); + temp = mul_add (a2, b[8], temp); + temp = mul_add (a3, b7, temp); + temp = mul_add (a4, b6, temp); + temp = mul_add (a5, b5, temp); + temp = mul_add (a6, b4, temp); + temp = mul_add (a7, b3, temp); + temp=mul_add(a[8], b2, temp); + c_avx[10] = _mm256_add_epi16(temp, c_avx[10]); + + + temp = _mm256_mullo_epi16 (a0, b[11]); + temp = mul_add (a1, b[10], temp ); + temp = mul_add (a[10], b1, temp ); + temp = mul_add (a[11], b0, temp ); + temp = mul_add (a2, b[9], temp ); + temp = mul_add (a3, b[8], temp ); + temp = mul_add (a4, b7, temp ); + temp = mul_add (a5, b6, temp ); + temp = mul_add (a6, b5, temp ); + temp = mul_add (a7, b4, temp ); + temp = mul_add (a[8], b3, temp ); + temp=mul_add(a[9], b2, temp); + c_avx[11] = _mm256_add_epi16(temp, c_avx[11]); + + + temp = _mm256_mullo_epi16 (a0, b[12]); + temp = mul_add (a1, b[11], temp); + temp = mul_add (a[11], b1, temp); + temp = mul_add (a[12], b0, temp); + temp = mul_add (a2, b[10], temp); + temp = mul_add (a3, b[9], temp); + temp = mul_add (a4, b[8], temp); + temp = mul_add (a5, b7, temp); + temp = mul_add (a6, b6, temp); + temp = mul_add (a7, b5, temp); + temp = mul_add (a[8], b4, temp); + temp = mul_add (a[9], b3, temp); + temp=mul_add(a[10], b2, temp); + c_avx[12] = _mm256_add_epi16(temp, c_avx[12]); + + + temp = _mm256_mullo_epi16 (a0, b[13]); + temp = mul_add (a1, b[12], temp ); + temp = mul_add (a[12], b1, temp ); + temp = mul_add (a[13], b0, temp ); + temp = mul_add (a2, b[11], temp ); + temp = mul_add (a3, b[10], temp ); + temp = mul_add (a4, b[9], temp ); + temp = mul_add (a5, b[8], temp ); + temp = mul_add (a6, b7, temp ); + temp = mul_add (a7, b6, temp ); + temp = mul_add (a[8], b5, temp ); + temp = mul_add (a[9], b4, temp ); + temp = mul_add (a[10], b3, temp ); + temp=mul_add(a[11], b2, temp); + c_avx[13] = _mm256_add_epi16(temp, c_avx[13]); + + + + temp = _mm256_mullo_epi16 (a0, b[14]); + temp = mul_add (a1, b[13], temp ); + temp = mul_add (a[13], b1, temp ); + temp = mul_add (a[14], b0, temp ); + temp = mul_add (a2, b[12], temp ); + temp = mul_add (a3, b[11], temp ); + temp = mul_add (a4, b[10], temp ); + temp = mul_add (a5, b[9], temp ); + temp = mul_add (a6, b[8], temp ); + temp = mul_add (a7, b7, temp ); + temp = mul_add (a[8], b6, temp ); + temp = mul_add (a[9], b5, temp ); + temp = mul_add (a[10], b4, temp ); + temp = mul_add (a[11], b3, temp ); + temp=mul_add(a[12], b2, temp); + c_avx[14] = _mm256_add_epi16(temp, c_avx[14]); + + + temp = _mm256_mullo_epi16 (a0, b[15]); + temp = mul_add (a1, b[14], temp ); + temp = mul_add (a[14], b1, temp ); + temp = mul_add (a[15], b0, temp ); + temp = mul_add (a2, b[13], temp ); + temp = mul_add (a3, b[12], temp ); + temp = mul_add (a4, b[11], temp ); + temp = mul_add (a5, b[10], temp ); + temp = mul_add (a6, b[9], temp ); + temp = mul_add (a7, b[8], temp ); + temp = mul_add (a[8], b7, temp ); + temp = mul_add (a[9], b6, temp ); + temp = mul_add (a[10], b5, temp ); + temp = mul_add (a[11], b4, temp ); + temp = mul_add (a[12], b3, temp ); + temp=mul_add(a[13], b2, temp); + c_avx[15] = _mm256_add_epi16(temp, c_avx[15]); + + + // unrolled second triangle + a0=a[14]; + a1=a[15]; + a2=a[13]; + a3=a[12]; + a4=a[11]; + a5=a[10]; + a6=a[9]; + a7=a[8]; + + b0=b[14]; + b1=b[15]; + b2=b[13]; + b3=b[12]; + b4=b[11]; + b5=b[10]; + b6=b[9]; + b7=b[8]; + + temp = _mm256_mullo_epi16 (a[1], b1); + temp = mul_add (a[2], b0, temp ); + temp = mul_add (a[3], b2, temp ); + temp = mul_add (a[4], b3, temp ); + temp = mul_add (a[5], b4, temp ); + temp = mul_add (a[6], b5, temp ); + temp = mul_add (a[7], b6, temp ); + temp = mul_add (a7, b7, temp ); + temp = mul_add (a6, b[7], temp ); + temp = mul_add (a5, b[6], temp ); + temp = mul_add (a4, b[5], temp ); + temp = mul_add (a3, b[4], temp ); + temp = mul_add (a2, b[3], temp ); + temp = mul_add (a0, b[2], temp ); + temp=mul_add(a1, b[1], temp); + c_avx[16] = _mm256_add_epi16(temp, c_avx[16]); + + + temp = _mm256_mullo_epi16 (a[2], b1); + temp = mul_add (a[3], b0, temp ); + temp = mul_add (a[4], b2, temp ); + temp = mul_add (a[5], b3, temp ); + temp = mul_add (a[6], b4, temp ); + temp = mul_add (a[7], b5, temp ); + temp = mul_add (a7, b6, temp ); + temp = mul_add (a6, b7, temp ); + temp = mul_add (a5, b[7], temp ); + temp = mul_add (a4, b[6], temp ); + temp = mul_add (a3, b[5], temp ); + temp = mul_add (a2, b[4], temp ); + temp = mul_add (a0, b[3], temp ); + temp=mul_add(a1, b[2], temp); + c_avx[17] = _mm256_add_epi16(temp, c_avx[17]); + + + temp = _mm256_mullo_epi16 (a[3], b1); + temp = mul_add (a[4], b0, temp ); + temp = mul_add (a[5], b2, temp ); + temp = mul_add (a[6], b3, temp ); + temp = mul_add (a[7], b4, temp ); + temp = mul_add (a7, b5, temp ); + temp = mul_add (a6, b6, temp ); + temp = mul_add (a5, b7, temp ); + temp = mul_add (a4, b[7], temp ); + temp = mul_add (a3, b[6], temp ); + temp = mul_add (a2, b[5], temp ); + temp = mul_add (a0, b[4], temp ); + temp=mul_add(a1, b[3], temp); + c_avx[18] = _mm256_add_epi16(temp, c_avx[18]); + + + temp = _mm256_mullo_epi16 (a[4], b1); + temp = mul_add (a[5], b0, temp ); + temp = mul_add (a[6], b2, temp ); + temp = mul_add (a[7], b3, temp ); + temp = mul_add (a7, b4, temp ); + temp = mul_add (a6, b5, temp ); + temp = mul_add (a5, b6, temp ); + temp = mul_add (a4, b7, temp ); + temp = mul_add (a3, b[7], temp ); + temp = mul_add (a2, b[6], temp ); + temp = mul_add (a0, b[5], temp ); + temp=mul_add(a1, b[4], temp); + c_avx[19] = _mm256_add_epi16(temp, c_avx[19]); + + + temp = _mm256_mullo_epi16 (a[5], b1); + temp = mul_add (a[6], b0, temp ); + temp = mul_add (a[7], b2, temp ); + temp = mul_add (a7, b3, temp ); + temp = mul_add (a6, b4, temp ); + temp = mul_add (a5, b5, temp ); + temp = mul_add (a4, b6, temp ); + temp = mul_add (a3, b7, temp ); + temp = mul_add (a2, b[7], temp ); + temp = mul_add (a0, b[6], temp ); + temp=mul_add(a1, b[5], temp); + c_avx[20] = _mm256_add_epi16(temp, c_avx[20]); + + + temp = _mm256_mullo_epi16 (a[6], b1); + temp = mul_add (a[7], b0, temp ); + temp = mul_add (a7, b2, temp ); + temp = mul_add (a6, b3, temp ); + temp = mul_add (a5, b4, temp ); + temp = mul_add (a4, b5, temp ); + temp = mul_add (a3, b6, temp ); + temp = mul_add (a2, b7, temp ); + temp = mul_add (a0, b[7], temp ); + temp=mul_add(a1, b[6], temp); + c_avx[21] = _mm256_add_epi16(temp, c_avx[21]); + + + temp = _mm256_mullo_epi16 (a[7], b1); + temp = mul_add (a7, b0, temp ); + temp = mul_add (a6, b2, temp ); + temp = mul_add (a5, b3, temp ); + temp = mul_add (a4, b4, temp ); + temp = mul_add (a3, b5, temp ); + temp = mul_add (a2, b6, temp ); + temp = mul_add (a0, b7, temp ); + temp=mul_add(a1, b[7], temp); + c_avx[22] = _mm256_add_epi16(temp, c_avx[22]); + + + temp = _mm256_mullo_epi16 (a7, b1); + temp = mul_add (a6, b0, temp ); + temp = mul_add (a5, b2, temp ); + temp = mul_add (a4, b3, temp ); + temp = mul_add (a3, b4, temp ); + temp = mul_add (a2, b5, temp ); + temp = mul_add (a0, b6, temp ); + temp=mul_add(a1, b7, temp); + c_avx[23] = _mm256_add_epi16(temp, c_avx[23]); + + + temp = _mm256_mullo_epi16 (a6, b1); + temp = mul_add (a5, b0, temp ); + temp = mul_add (a4, b2, temp ); + temp = mul_add (a3, b3, temp ); + temp = mul_add (a2, b4, temp ); + temp = mul_add (a0, b5, temp ); + temp=mul_add(a1, b6, temp); + c_avx[24] = _mm256_add_epi16(temp, c_avx[24]); + + + temp = _mm256_mullo_epi16 (a5, b1); + temp = mul_add (a4, b0, temp ); + temp = mul_add (a3, b2, temp ); + temp = mul_add (a2, b3, temp ); + temp = mul_add (a0, b4, temp ); + temp=mul_add(a1, b5, temp); + c_avx[25] = _mm256_add_epi16(temp, c_avx[25]); + + + temp = _mm256_mullo_epi16 (a4, b1); + temp = mul_add (a3, b0, temp ); + temp = mul_add (a2, b2, temp ); + temp = mul_add (a0, b3, temp ); + temp=mul_add(a1, b4, temp); + c_avx[26] = _mm256_add_epi16(temp, c_avx[26]); + + + temp = _mm256_mullo_epi16 (a3, b1); + temp = mul_add (a2, b0, temp ); + temp = mul_add (a0, b2, temp ); + temp=mul_add(a1, b3, temp); + c_avx[27] = _mm256_add_epi16(temp, c_avx[27]); + + + temp = _mm256_mullo_epi16 (a2, b1); + temp = mul_add (a0, b0, temp ); + temp=mul_add(a1, b2, temp); + c_avx[28] = _mm256_add_epi16(temp, c_avx[28]); + + + temp = _mm256_mullo_epi16 (a0, b1); + temp=mul_add(a1, b0, temp); + c_avx[29] = _mm256_add_epi16(temp, c_avx[29]); + + + c_avx[30] = mul_add(a1, b1, c_avx[30]); + + + + c_avx[2*SCM_SIZE-1] = _mm256_set_epi64x(0, 0, 0, 0); + + +} + + + +static void schoolbook_avx_new2(__m256i* a, __m256i* b, __m256i* c_avx) ////8 coefficients of a and b has been prefetched + //the c_avx are not added cummulatively +{ + + __m256i a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7; + __m256i temp; + + + a0=a[0]; + a1=a[1]; + a2=a[2]; + a3=a[3]; + a4=a[4]; + a5=a[5]; + a6=a[6]; + a7=a[7]; + + b0=b[0]; + b1=b[1]; + b2=b[2]; + b3=b[3]; + b4=b[4]; + b5=b[5]; + b6=b[6]; + b7=b[7]; + + // New Unrolled first triangle + c_avx[0] = _mm256_mullo_epi16 (a0, b0); + + temp = _mm256_mullo_epi16 (a0, b1); + c_avx[1]=mul_add(a1, b0, temp); + + temp = _mm256_mullo_epi16 (a0, b2); + + temp = mul_add(a1, b1, temp); + c_avx[2]= mul_add(a2, b0, temp); + + temp = _mm256_mullo_epi16 (a0, b3); + temp = mul_add(a1, b2, temp); + temp = mul_add(a2, b1, temp); + c_avx[3]= mul_add(a3, b0, temp); + + temp = _mm256_mullo_epi16 (a0, b4); + temp = mul_add(a1, b3, temp); + temp = mul_add(a3, b1, temp); + temp = mul_add(a4, b0, temp); + c_avx[4]= mul_add(a2, b2, temp); + + temp = _mm256_mullo_epi16 (a0, b5); + temp = mul_add(a1, b4 , temp); + temp = mul_add(a2, b3, temp); + temp = mul_add(a3, b2, temp); + temp = mul_add( a4, b1, temp); + c_avx[5] = mul_add(a5, b0, temp); + + temp = _mm256_mullo_epi16 (a0, b6); + temp = mul_add(a1, b5, temp); + temp = mul_add(a5, b1, temp); + temp = mul_add(a6, b0, temp); + temp = mul_add(a2, b4, temp); + temp = mul_add(a3, b3, temp); + c_avx[6] = mul_add(a4, b2, temp); + + temp = _mm256_mullo_epi16 (a0, b7); + temp = mul_add(a1, b6, temp); + temp = mul_add (a6, b1, temp); + temp = mul_add (a7, b0, temp); + temp = mul_add(a2, b5, temp); + temp = mul_add (a3, b4, temp); + temp = mul_add (a4, b3, temp); + c_avx[7] = mul_add (a5, b2, temp); + + temp = _mm256_mullo_epi16 (a0, b[8]); + temp = mul_add (a1, b7, temp); + temp = mul_add (a7, b1, temp); + temp = mul_add (a[8], b0, temp); + temp = mul_add (a2, b6,temp); + temp = mul_add(a3, b5, temp); + temp = mul_add (a4, b4,temp); + temp = mul_add (a5, b3, temp); + c_avx[8] = mul_add (a6, b2, temp); + + temp = _mm256_mullo_epi16 (a0, b[9]); + temp = mul_add (a1, b[8], temp); + temp = mul_add (a[8], b1, temp); + temp = mul_add (a[9], b0, temp); + temp = mul_add (a2, b7, temp); + temp = mul_add (a3, b6, temp); + temp = mul_add (a4, b5, temp); + temp = mul_add (a5, b4, temp); + temp = mul_add (a6, b3, temp); + c_avx[9] = mul_add (a7, b2, temp); + + temp= _mm256_mullo_epi16 (a0, b[10]); + temp = mul_add (a1, b[9], temp); + temp = mul_add (a[9], b1, temp); + temp = mul_add (a[10], b0, temp); + temp = mul_add (a2, b[8], temp); + temp = mul_add (a3, b7, temp); + temp = mul_add (a4, b6, temp); + temp = mul_add (a5, b5, temp); + temp = mul_add (a6, b4, temp); + temp = mul_add (a7, b3, temp); + c_avx[10] = mul_add (a[8], b2, temp); + + temp = _mm256_mullo_epi16 (a0, b[11]); + temp = mul_add (a1, b[10], temp ); + temp = mul_add (a[10], b1, temp ); + temp = mul_add (a[11], b0, temp ); + temp = mul_add (a2, b[9], temp ); + temp = mul_add (a3, b[8], temp ); + temp = mul_add (a4, b7, temp ); + temp = mul_add (a5, b6, temp ); + temp = mul_add (a6, b5, temp ); + temp = mul_add (a7, b4, temp ); + temp = mul_add (a[8], b3, temp ); + c_avx[11] = mul_add (a[9], b2, temp ); + + temp = _mm256_mullo_epi16 (a0, b[12]); + temp = mul_add (a1, b[11], temp); + temp = mul_add (a[11], b1, temp); + temp = mul_add (a[12], b0, temp); + temp = mul_add (a2, b[10], temp); + temp = mul_add (a3, b[9], temp); + temp = mul_add (a4, b[8], temp); + temp = mul_add (a5, b7, temp); + temp = mul_add (a6, b6, temp); + temp = mul_add (a7, b5, temp); + temp = mul_add (a[8], b4, temp); + temp = mul_add (a[9], b3, temp); + c_avx[12] = mul_add (a[10], b2, temp); + + temp = _mm256_mullo_epi16 (a0, b[13]); + temp = mul_add (a1, b[12], temp ); + temp = mul_add (a[12], b1, temp ); + temp = mul_add (a[13], b0, temp ); + temp = mul_add (a2, b[11], temp ); + temp = mul_add (a3, b[10], temp ); + temp = mul_add (a4, b[9], temp ); + temp = mul_add (a5, b[8], temp ); + temp = mul_add (a6, b7, temp ); + temp = mul_add (a7, b6, temp ); + temp = mul_add (a[8], b5, temp ); + temp = mul_add (a[9], b4, temp ); + temp = mul_add (a[10], b3, temp ); + c_avx[13] = mul_add (a[11], b2, temp ); + + temp = _mm256_mullo_epi16 (a0, b[14]); + temp = mul_add (a1, b[13], temp ); + temp = mul_add (a[13], b1, temp ); + temp = mul_add (a[14], b0, temp ); + temp = mul_add (a2, b[12], temp ); + temp = mul_add (a3, b[11], temp ); + temp = mul_add (a4, b[10], temp ); + temp = mul_add (a5, b[9], temp ); + temp = mul_add (a6, b[8], temp ); + temp = mul_add (a7, b7, temp ); + temp = mul_add (a[8], b6, temp ); + temp = mul_add (a[9], b5, temp ); + temp = mul_add (a[10], b4, temp ); + temp = mul_add (a[11], b3, temp ); + c_avx[14] = mul_add (a[12], b2, temp ); + + temp = _mm256_mullo_epi16 (a0, b[15]); + temp = mul_add (a1, b[14], temp ); + temp = mul_add (a[14], b1, temp ); + temp = mul_add (a[15], b0, temp ); + temp = mul_add (a2, b[13], temp ); + temp = mul_add (a3, b[12], temp ); + temp = mul_add (a4, b[11], temp ); + temp = mul_add (a5, b[10], temp ); + temp = mul_add (a6, b[9], temp ); + temp = mul_add (a7, b[8], temp ); + temp = mul_add (a[8], b7, temp ); + temp = mul_add (a[9], b6, temp ); + temp = mul_add (a[10], b5, temp ); + temp = mul_add (a[11], b4, temp ); + temp = mul_add (a[12], b3, temp ); + c_avx[15] = mul_add (a[13], b2, temp ); + + + // unrolled second triangle + a0=a[14]; + a1=a[15]; + a2=a[13]; + a3=a[12]; + a4=a[11]; + a5=a[10]; + a6=a[9]; + a7=a[8]; + + b0=b[14]; + b1=b[15]; + b2=b[13]; + b3=b[12]; + b4=b[11]; + b5=b[10]; + b6=b[9]; + b7=b[8]; + + + temp = _mm256_mullo_epi16 (a[1], b1); + temp = mul_add (a[2], b0, temp ); + temp = mul_add (a[3], b2, temp ); + temp = mul_add (a[4], b3, temp ); + temp = mul_add (a[5], b4, temp ); + temp = mul_add (a[6], b5, temp ); + temp = mul_add (a[7], b6, temp ); + temp = mul_add (a7, b7, temp ); + temp = mul_add (a6, b[7], temp ); + temp = mul_add (a5, b[6], temp ); + temp = mul_add (a4, b[5], temp ); + temp = mul_add (a3, b[4], temp ); + temp = mul_add (a2, b[3], temp ); + temp = mul_add (a0, b[2], temp ); + c_avx[16] = mul_add (a1, b[1], temp ); + + temp = _mm256_mullo_epi16 (a[2], b1); + temp = mul_add (a[3], b0, temp ); + temp = mul_add (a[4], b2, temp ); + temp = mul_add (a[5], b3, temp ); + temp = mul_add (a[6], b4, temp ); + temp = mul_add (a[7], b5, temp ); + temp = mul_add (a7, b6, temp ); + temp = mul_add (a6, b7, temp ); + temp = mul_add (a5, b[7], temp ); + temp = mul_add (a4, b[6], temp ); + temp = mul_add (a3, b[5], temp ); + temp = mul_add (a2, b[4], temp ); + temp = mul_add (a0, b[3], temp ); + c_avx[17] = mul_add (a1, b[2], temp ); + + temp = _mm256_mullo_epi16 (a[3], b1); + temp = mul_add (a[4], b0, temp ); + temp = mul_add (a[5], b2, temp ); + temp = mul_add (a[6], b3, temp ); + temp = mul_add (a[7], b4, temp ); + temp = mul_add (a7, b5, temp ); + temp = mul_add (a6, b6, temp ); + temp = mul_add (a5, b7, temp ); + temp = mul_add (a4, b[7], temp ); + temp = mul_add (a3, b[6], temp ); + temp = mul_add (a2, b[5], temp ); + temp = mul_add (a0, b[4], temp ); + c_avx[18] = mul_add (a1, b[3], temp ); + + temp = _mm256_mullo_epi16 (a[4], b1); + temp = mul_add (a[5], b0, temp ); + temp = mul_add (a[6], b2, temp ); + temp = mul_add (a[7], b3, temp ); + temp = mul_add (a7, b4, temp ); + temp = mul_add (a6, b5, temp ); + temp = mul_add (a5, b6, temp ); + temp = mul_add (a4, b7, temp ); + temp = mul_add (a3, b[7], temp ); + temp = mul_add (a2, b[6], temp ); + temp = mul_add (a0, b[5], temp ); + c_avx[19] = mul_add (a1, b[4], temp ); + + temp = _mm256_mullo_epi16 (a[5], b1); + temp = mul_add (a[6], b0, temp ); + temp = mul_add (a[7], b2, temp ); + temp = mul_add (a7, b3, temp ); + temp = mul_add (a6, b4, temp ); + temp = mul_add (a5, b5, temp ); + temp = mul_add (a4, b6, temp ); + temp = mul_add (a3, b7, temp ); + temp = mul_add (a2, b[7], temp ); + temp = mul_add (a0, b[6], temp ); + c_avx[20] = mul_add (a1, b[5], temp ); + + temp = _mm256_mullo_epi16 (a[6], b1); + temp = mul_add (a[7], b0, temp ); + temp = mul_add (a7, b2, temp ); + temp = mul_add (a6, b3, temp ); + temp = mul_add (a5, b4, temp ); + temp = mul_add (a4, b5, temp ); + temp = mul_add (a3, b6, temp ); + temp = mul_add (a2, b7, temp ); + temp = mul_add (a0, b[7], temp ); + c_avx[21] = mul_add (a1, b[6], temp ); + + temp = _mm256_mullo_epi16 (a[7], b1); + temp = mul_add (a7, b0, temp ); + temp = mul_add (a6, b2, temp ); + temp = mul_add (a5, b3, temp ); + temp = mul_add (a4, b4, temp ); + temp = mul_add (a3, b5, temp ); + temp = mul_add (a2, b6, temp ); + temp = mul_add (a0, b7, temp ); + c_avx[22] = mul_add (a1, b[7], temp ); + + temp = _mm256_mullo_epi16 (a7, b1); + temp = mul_add (a6, b0, temp ); + temp = mul_add (a5, b2, temp ); + temp = mul_add (a4, b3, temp ); + temp = mul_add (a3, b4, temp ); + temp = mul_add (a2, b5, temp ); + temp = mul_add (a0, b6, temp ); + c_avx[23] = mul_add (a1, b7, temp ); + + temp = _mm256_mullo_epi16 (a6, b1); + temp = mul_add (a5, b0, temp ); + temp = mul_add (a4, b2, temp ); + temp = mul_add (a3, b3, temp ); + temp = mul_add (a2, b4, temp ); + temp = mul_add (a0, b5, temp ); + c_avx[24] = mul_add (a1, b6, temp ); + + temp = _mm256_mullo_epi16 (a5, b1); + temp = mul_add (a4, b0, temp ); + temp = mul_add (a3, b2, temp ); + temp = mul_add (a2, b3, temp ); + temp = mul_add (a0, b4, temp ); + c_avx[25] = mul_add (a1, b5, temp ); + + temp = _mm256_mullo_epi16 (a4, b1); + temp = mul_add (a3, b0, temp ); + temp = mul_add (a2, b2, temp ); + temp = mul_add (a0, b3, temp ); + c_avx[26] = mul_add (a1, b4, temp ); + + temp = _mm256_mullo_epi16 (a3, b1); + temp = mul_add (a2, b0, temp ); + temp = mul_add (a0, b2, temp ); + c_avx[27] = mul_add (a1, b3, temp ); + + temp = _mm256_mullo_epi16 (a2, b1); + temp = mul_add (a0, b0, temp ); + c_avx[28] = mul_add (a1, b2, temp ); + + temp = _mm256_mullo_epi16 (a0, b1); + c_avx[29] = mul_add (a1, b0, temp); + + c_avx[30] = _mm256_mullo_epi16 (a1, b1); + + + c_avx[2*SCM_SIZE-1] = _mm256_set_epi64x(0, 0, 0, 0); + +} diff --git a/crypto_kem/firesaber/avx2/polymul/toom-cook_4way.c b/crypto_kem/firesaber/avx2/polymul/toom-cook_4way.c new file mode 100644 index 00000000..78fb86c2 --- /dev/null +++ b/crypto_kem/firesaber/avx2/polymul/toom-cook_4way.c @@ -0,0 +1,1010 @@ +/* +Cleaned version for step by step approach look into the _debug file +*/ +//#include "timing.c" +#include "consts.h" +#include "matrix.c" +#include "scm_avx.c" + +static void batch_64coefficient_multiplications_new(__m256i* a, __m256i* b_bucket, __m256i* c_bucket, int f)//all 7 Karatsuba evaluation and interpolation are done in AVX. +{ + __m256i a_bucket[SCM_SIZE*4]; //SCM_SIZE = 16; Holds evaluation (a & b) for 7 Karatsuba at a time + + //uint16_t i; + + register __m256i r0_avx, r1_avx, r2_avx, r3_avx; + + + + //CLOCK1=cpucycles(); + + //------------------AVX evaluation for 1st poly----------------------- + + r0_avx=a[0]; + r1_avx=a[1]; + r2_avx=a[2]; + r3_avx=a[3]; + a_bucket[0]=r0_avx; + a_bucket[1]=r1_avx; + a_bucket[2]=r2_avx; + a_bucket[3]=r3_avx; + a_bucket[4]= _mm256_add_epi16(r0_avx, r1_avx); + a_bucket[5]= _mm256_add_epi16(r2_avx, r3_avx); + a_bucket[6]= _mm256_add_epi16(r0_avx, r2_avx); + a_bucket[7]= _mm256_add_epi16(r1_avx, r3_avx); + a_bucket[8]= _mm256_add_epi16(a_bucket[6],a_bucket[7]); + + + //------------------AVX evaluation for 1st poly ends------------------ + + + //------------------AVX evaluation for 2nd poly----------------------- + r0_avx=a[small_len_avx]; + r1_avx=a[small_len_avx+1]; + r2_avx=a[small_len_avx+2]; + r3_avx=a[small_len_avx+3]; + a_bucket[0+9]=r0_avx; + a_bucket[1+9]=r1_avx; + a_bucket[2+9]=r2_avx; + a_bucket[3+9]=r3_avx; + a_bucket[4+9]= _mm256_add_epi16(r0_avx, r1_avx); + a_bucket[5+9]= _mm256_add_epi16(r2_avx, r3_avx); + a_bucket[6+9]= _mm256_add_epi16(r0_avx, r2_avx); + a_bucket[7+9]= _mm256_add_epi16(r1_avx, r3_avx); + a_bucket[8+9]= _mm256_add_epi16(a_bucket[6+9],a_bucket[7+9]); + + + //------------------AVX evaluation for 2nd poly ends------------------ + + + //------------------AVX evaluation for 3rd poly----------------------- + r0_avx=a[2*small_len_avx]; + r1_avx=a[2*small_len_avx+1]; + r2_avx=a[2*small_len_avx+2]; + r3_avx=a[2*small_len_avx+3]; + a_bucket[0+18]=r0_avx; + a_bucket[1+18]=r1_avx; + a_bucket[2+18]=r2_avx; + a_bucket[3+18]=r3_avx; + a_bucket[4+18]= _mm256_add_epi16(r0_avx, r1_avx); + a_bucket[5+18]= _mm256_add_epi16(r2_avx, r3_avx); + a_bucket[6+18]= _mm256_add_epi16(r0_avx, r2_avx); + a_bucket[7+18]= _mm256_add_epi16(r1_avx, r3_avx); + a_bucket[8+18]= _mm256_add_epi16(a_bucket[6+18],a_bucket[7+18]); + + //------------------AVX evaluation for 3rd poly ends------------------ + + + //------------------AVX evaluation for 4th poly----------------------- + + r0_avx=a[3*small_len_avx]; + r1_avx=a[3*small_len_avx+1]; + r2_avx=a[3*small_len_avx+2]; + r3_avx=a[3*small_len_avx+3]; + a_bucket[0+27]=r0_avx; + a_bucket[1+27]=r1_avx; + a_bucket[2+27]=r2_avx; + a_bucket[3+27]=r3_avx; + a_bucket[4+27]= _mm256_add_epi16(r0_avx, r1_avx); + a_bucket[5+27]= _mm256_add_epi16(r2_avx, r3_avx); + a_bucket[6+27]= _mm256_add_epi16(r0_avx, r2_avx); + a_bucket[7+27]= _mm256_add_epi16(r1_avx, r3_avx); + a_bucket[8+27]= _mm256_add_epi16(a_bucket[6+27],a_bucket[7+27]); + + //------------------AVX evaluation for 4th poly ends------------------ + + //------------------AVX evaluation for 5th poly----------------------- + + r0_avx=a[4*small_len_avx+0]; + r1_avx=a[4*small_len_avx+1]; + r2_avx=a[4*small_len_avx+2]; + r3_avx=a[4*small_len_avx+3]; + a_bucket[0+36]=r0_avx; + a_bucket[1+36]=r1_avx; + a_bucket[2+36]=r2_avx; + a_bucket[3+36]=r3_avx; + a_bucket[4+36]= _mm256_add_epi16(r0_avx, r1_avx); + a_bucket[5+36]= _mm256_add_epi16(r2_avx, r3_avx); + a_bucket[6+36]= _mm256_add_epi16(r0_avx, r2_avx); + a_bucket[7+36]= _mm256_add_epi16(r1_avx, r3_avx); + a_bucket[8+36]= _mm256_add_epi16(a_bucket[6+36],a_bucket[7+36]); + + //------------------AVX evaluation for 5th poly ends------------------ + + + //------------------AVX evaluation for 6th poly----------------------- + r0_avx=a[5*small_len_avx]; + r1_avx=a[5*small_len_avx+1]; + r2_avx=a[5*small_len_avx+2]; + r3_avx=a[5*small_len_avx+3]; + a_bucket[0+45]=r0_avx; + a_bucket[1+45]=r1_avx; + a_bucket[2+45]=r2_avx; + a_bucket[3+45]=r3_avx; + a_bucket[4+45]= _mm256_add_epi16(r0_avx, r1_avx); + a_bucket[5+45]= _mm256_add_epi16(r2_avx, r3_avx); + a_bucket[6+45]= _mm256_add_epi16(r0_avx, r2_avx); + a_bucket[7+45]= _mm256_add_epi16(r1_avx, r3_avx); + a_bucket[8+45]= _mm256_add_epi16(a_bucket[6+45],a_bucket[7+45]); + + //------------------AVX evaluation for 6th poly ends------------------ + + //------------------AVX evaluation for 7th poly----------------------- + + r0_avx=a[6*small_len_avx]; + r1_avx=a[6*small_len_avx+1]; + r2_avx=a[6*small_len_avx+2]; + r3_avx=a[6*small_len_avx+3]; + a_bucket[0+54]=r0_avx; + a_bucket[1+54]=r1_avx; + a_bucket[2+54]=r2_avx; + a_bucket[3+54]=r3_avx; + a_bucket[4+54]= _mm256_add_epi16(r0_avx, r1_avx); + a_bucket[5+54]= _mm256_add_epi16(r2_avx, r3_avx); + a_bucket[6+54]= _mm256_add_epi16(r0_avx, r2_avx); + a_bucket[7+54]= _mm256_add_epi16(r1_avx, r3_avx); + a_bucket[8+54]= _mm256_add_epi16(a_bucket[6+54],a_bucket[7+54]); + + //------------------AVX evaluation for 7th poly ends------------------ + + + + //CLOCK2=cpucycles(); + //CLOCK_EVAL=CLOCK_EVAL+(CLOCK2-CLOCK1); + //printf("\nTime for multiplication : %llu\n", CLOCK2-CLOCK1); + + + //CLOCK1=cpucycles(); + //-----------------Forward transposes-------------------------------------- + transpose_n1(a_bucket); + transpose_n1(a_bucket+16); + transpose_n1(a_bucket+32); + transpose_n1(a_bucket+48); + + //-----------------Forwatrd transposes ends--------------------------------- + + //----------------------all multiplications--------------------------------- + if(f==0){ + schoolbook_avx_new2(a_bucket, b_bucket, c_bucket); + schoolbook_avx_new2(a_bucket+16, b_bucket+16, c_bucket+2*SCM_SIZE); + schoolbook_avx_new2(a_bucket+32, b_bucket+32, c_bucket+4*SCM_SIZE); + schoolbook_avx_new2(a_bucket+48, b_bucket+48, c_bucket+6*SCM_SIZE); + } + else{ + schoolbook_avx_new3_acc(a_bucket, b_bucket, c_bucket); + schoolbook_avx_new3_acc(a_bucket+16, b_bucket+16, c_bucket+2*SCM_SIZE); + //schoolbook_avx_new3_acc_fused(a_bucket, b_bucket, c_bucket); + schoolbook_avx_new3_acc(a_bucket+32, b_bucket+32, c_bucket+4*SCM_SIZE); + schoolbook_avx_new3_acc(a_bucket+48, b_bucket+48, c_bucket+6*SCM_SIZE); + } + /* + schoolbook_avx_new2_acc(a_bucket, b_bucket, c_bucket, f); + schoolbook_avx_new2_acc(a_bucket+16, b_bucket+16, c_bucket+2*SCM_SIZE, f); + schoolbook_avx_new2_acc(a_bucket+32, b_bucket+32, c_bucket+4*SCM_SIZE, f); + schoolbook_avx_new2_acc(a_bucket+48, b_bucket+48, c_bucket+6*SCM_SIZE, f); + */ + + + //----------------------all multiplications ends----------------------------- + + + //-----------------Reverse transposes-------------------------------------- + + /* + transpose(c_bucket); + transpose(c_bucket+16); + + transpose(c_bucket+2*SCM_SIZE); + transpose(c_bucket+16+2*SCM_SIZE); + + transpose(c_bucket+4*SCM_SIZE); + transpose(c_bucket+16+4*SCM_SIZE); + + transpose(c_bucket+6*SCM_SIZE); + transpose(c_bucket+16+6*SCM_SIZE); + */ + //-----------------Reverse transposes ends--------------------------------- + + //CLOCK2=cpucycles(); + //CLOCK_MULT=CLOCK_MULT+(CLOCK2-CLOCK1); + + //KARA_interpol(c_bucket, result_final0, result_final1, result_final2, result_final3, result_final4, result_final5, result_final6); + +} + +static void KARA_eval(__m256i* b, __m256i *b_bucket){ + + __m256i r0_avx, r1_avx, r2_avx, r3_avx; + + + //-------1st poly---------------------------------------------------- + r0_avx=b[0]; + r1_avx=b[1]; + r2_avx=b[2]; + r3_avx=b[3]; + b_bucket[0]=r0_avx; + b_bucket[1]=r1_avx; + b_bucket[2]=r2_avx; + b_bucket[3]=r3_avx; + b_bucket[4]= _mm256_add_epi16(r0_avx, r1_avx); + b_bucket[5]= _mm256_add_epi16(r2_avx, r3_avx); + b_bucket[6]= _mm256_add_epi16(r0_avx, r2_avx); + b_bucket[7]= _mm256_add_epi16(r1_avx, r3_avx); + b_bucket[8]= _mm256_add_epi16(b_bucket[6],b_bucket[7]); + //-------2nd poly---------------------------------------------------- + + r0_avx=b[small_len_avx]; + r1_avx=b[small_len_avx+1]; + r2_avx=b[small_len_avx+2]; + r3_avx=b[small_len_avx+3]; + b_bucket[0+9]=r0_avx; + b_bucket[1+9]=r1_avx; + b_bucket[2+9]=r2_avx; + b_bucket[3+9]=r3_avx; + b_bucket[4+9]= _mm256_add_epi16(r0_avx, r1_avx); + b_bucket[5+9]= _mm256_add_epi16(r2_avx, r3_avx); + b_bucket[6+9]= _mm256_add_epi16(r0_avx, r2_avx); + b_bucket[7+9]= _mm256_add_epi16(r1_avx, r3_avx); + b_bucket[8+9]= _mm256_add_epi16(b_bucket[6+9],b_bucket[7+9]); + + //-------3rd poly---------------------------------------------------- + + r0_avx=b[2*small_len_avx+0]; + r1_avx=b[2*small_len_avx+1]; + r2_avx=b[2*small_len_avx+2]; + r3_avx=b[2*small_len_avx+3]; + b_bucket[0+18]=r0_avx; + b_bucket[1+18]=r1_avx; + b_bucket[2+18]=r2_avx; + b_bucket[3+18]=r3_avx; + b_bucket[4+18]= _mm256_add_epi16(r0_avx, r1_avx); + b_bucket[5+18]= _mm256_add_epi16(r2_avx, r3_avx); + b_bucket[6+18]= _mm256_add_epi16(r0_avx, r2_avx); + b_bucket[7+18]= _mm256_add_epi16(r1_avx, r3_avx); + b_bucket[8+18]= _mm256_add_epi16(b_bucket[6+18],b_bucket[7+18]); + + //-------4th poly---------------------------------------------------- + r0_avx=b[3*small_len_avx]; + r1_avx=b[3*small_len_avx+1]; + r2_avx=b[3*small_len_avx+2]; + r3_avx=b[3*small_len_avx+3]; + b_bucket[0+27]=r0_avx; + b_bucket[1+27]=r1_avx; + b_bucket[2+27]=r2_avx; + b_bucket[3+27]=r3_avx; + b_bucket[4+27]= _mm256_add_epi16(r0_avx, r1_avx); + b_bucket[5+27]= _mm256_add_epi16(r2_avx, r3_avx); + b_bucket[6+27]= _mm256_add_epi16(r0_avx, r2_avx); + b_bucket[7+27]= _mm256_add_epi16(r1_avx, r3_avx); + b_bucket[8+27]= _mm256_add_epi16(b_bucket[6+27],b_bucket[7+27]); + + //-------5th poly---------------------------------------------------- + + r0_avx=b[4*small_len_avx]; + r1_avx=b[4*small_len_avx+1]; + r2_avx=b[4*small_len_avx+2]; + r3_avx=b[4*small_len_avx+3]; + b_bucket[0+36]=r0_avx; + b_bucket[1+36]=r1_avx; + b_bucket[2+36]=r2_avx; + b_bucket[3+36]=r3_avx; + b_bucket[4+36]= _mm256_add_epi16(r0_avx, r1_avx); + b_bucket[5+36]= _mm256_add_epi16(r2_avx, r3_avx); + b_bucket[6+36]= _mm256_add_epi16(r0_avx, r2_avx); + b_bucket[7+36]= _mm256_add_epi16(r1_avx, r3_avx); + b_bucket[8+36]= _mm256_add_epi16(b_bucket[6+36],b_bucket[7+36]); + + //-------6th poly---------------------------------------------------- + + r0_avx=b[5*small_len_avx]; + r1_avx=b[5*small_len_avx+1]; + r2_avx=b[5*small_len_avx+2]; + r3_avx=b[5*small_len_avx+3]; + b_bucket[0+45]=r0_avx; + b_bucket[1+45]=r1_avx; + b_bucket[2+45]=r2_avx; + b_bucket[3+45]=r3_avx; + b_bucket[4+45]= _mm256_add_epi16(r0_avx, r1_avx); + b_bucket[5+45]= _mm256_add_epi16(r2_avx, r3_avx); + b_bucket[6+45]= _mm256_add_epi16(r0_avx, r2_avx); + b_bucket[7+45]= _mm256_add_epi16(r1_avx, r3_avx); + b_bucket[8+45]= _mm256_add_epi16(b_bucket[6+45],b_bucket[7+45]); + + //-------7th poly---------------------------------------------------- + + r0_avx=b[6*small_len_avx]; + r1_avx=b[6*small_len_avx+1]; + r2_avx=b[6*small_len_avx+2]; + r3_avx=b[6*small_len_avx+3]; + b_bucket[0+54]=r0_avx; + b_bucket[1+54]=r1_avx; + b_bucket[2+54]=r2_avx; + b_bucket[3+54]=r3_avx; + b_bucket[4+54]= _mm256_add_epi16(r0_avx, r1_avx); + b_bucket[5+54]= _mm256_add_epi16(r2_avx, r3_avx); + b_bucket[6+54]= _mm256_add_epi16(r0_avx, r2_avx); + b_bucket[7+54]= _mm256_add_epi16(r1_avx, r3_avx); + b_bucket[8+54]= _mm256_add_epi16(b_bucket[6+54],b_bucket[7+54]); + + //--------------Evaluating B poly ends------------------------------- + + transpose_n1(b_bucket); + transpose_n1(b_bucket+16); + transpose_n1(b_bucket+32); + transpose_n1(b_bucket+48); +} + +static void KARA_interpol(__m256i *c_bucket, __m256i* result_final0, __m256i* result_final1, __m256i* result_final2, __m256i* result_final3, __m256i* result_final4, __m256i* result_final5, __m256i* result_final6){ + + //int64_t i; + register __m256i res_avx0, res_avx1, res_avx2, res_avx3, res_avx4, res_avx5, res_avx6, res_avx7; // to hold each 64X64 poly mul results + + __m256i temp, c6_avx, c7_avx, c8_avx, c20_avx, c21_avx, c22_avx, c23_avx, c24_avx; + + //CLOCK1=cpucycles(); + + //------------------------AVX interpolation for 1st poly external------------------- + + //loop1 + res_avx0 = c_bucket[0]; + res_avx2 = c_bucket[1]; + res_avx4 = c_bucket[2]; + res_avx6 = c_bucket[3]; + + c6_avx=c_bucket[6]; + c7_avx=c_bucket[7]; + + c8_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[8], c6_avx), c7_avx); + + res_avx1 = c_bucket[16]; + res_avx3 = c_bucket[17]; + res_avx5 = c_bucket[18]; + res_avx7 = c_bucket[19]; + + c22_avx=c_bucket[22]; + c23_avx=c_bucket[23]; + + c21_avx=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[21], res_avx5),res_avx7); + + c24_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[24], c22_avx), c23_avx); + + c20_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[20], res_avx1), res_avx3); + + temp=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[5], res_avx4),res_avx6); + res_avx5 = _mm256_add_epi16(res_avx5, temp); + + temp = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[4], res_avx0), res_avx2); + res_avx1 = _mm256_add_epi16(res_avx1, temp); + + c22_avx=_mm256_add_epi16(c22_avx, c8_avx); + + res_avx6 = _mm256_add_epi16(res_avx6, c21_avx); + + res_avx2 = _mm256_add_epi16(res_avx2, c20_avx); + + c7_avx=_mm256_add_epi16(c7_avx, c24_avx); + + + //loop4 + + c6_avx=_mm256_sub_epi16(_mm256_sub_epi16(c6_avx, res_avx0), res_avx4); + c22_avx=_mm256_sub_epi16(_mm256_sub_epi16(c22_avx, res_avx1), res_avx5); + + c7_avx=_mm256_sub_epi16(_mm256_sub_epi16(c7_avx, res_avx2), res_avx6); + c23_avx=_mm256_sub_epi16(_mm256_sub_epi16(c23_avx, res_avx3), res_avx7); + + //loop5 + result_final0[0]=res_avx0; + result_final0[1]=res_avx1; + + result_final0[2]=_mm256_add_epi16(res_avx2, c6_avx); + result_final0[3]=_mm256_add_epi16(res_avx3, c22_avx); + + + result_final0[4]=_mm256_add_epi16(res_avx4, c7_avx); + result_final0[5]=_mm256_add_epi16(res_avx5, c23_avx); + + result_final0[6]=res_avx6; + result_final0[7]=res_avx7; + + + //------------------------AVX interpolation for 1st poly ends-------------- + + + //------------------------AVX interpolation for 2nd poly external------------------- + + //loop1 + res_avx0 = c_bucket[9]; //c_bucket0 + res_avx2 = c_bucket[10]; //c_bucket1 + res_avx4 = c_bucket[11]; //c_bucket2 + res_avx6 = c_bucket[12]; //c_bucket3 + + c6_avx=c_bucket[15]; //c_bucket6 + c7_avx=c_bucket[32]; //c_bucket7 + + c8_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[33], c6_avx), c7_avx); + + res_avx1 = c_bucket[25]; //c_bucket0 + res_avx3 = c_bucket[26]; //c_bucket1 + res_avx5 = c_bucket[27]; //c_bucket2 + res_avx7 = c_bucket[28]; //c_bucket3 + + c22_avx=c_bucket[31]; + c23_avx=c_bucket[48]; + + c21_avx=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[30], res_avx5),res_avx7); + + c24_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[49], c22_avx), c23_avx); + + c20_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[29], res_avx1), res_avx3); + + temp=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[14], res_avx4),res_avx6); + res_avx5 = _mm256_add_epi16(res_avx5, temp); + + temp = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[13], res_avx0), res_avx2); + res_avx1 = _mm256_add_epi16(res_avx1, temp); + + c22_avx=_mm256_add_epi16(c22_avx, c8_avx); + + res_avx6 = _mm256_add_epi16(res_avx6, c21_avx); + + res_avx2 = _mm256_add_epi16(res_avx2, c20_avx); + + c7_avx=_mm256_add_epi16(c7_avx, c24_avx); + + + //loop4 + + c6_avx=_mm256_sub_epi16(_mm256_sub_epi16(c6_avx, res_avx0), res_avx4); + c22_avx=_mm256_sub_epi16(_mm256_sub_epi16(c22_avx, res_avx1), res_avx5); + + c7_avx=_mm256_sub_epi16(_mm256_sub_epi16(c7_avx, res_avx2), res_avx6); + c23_avx=_mm256_sub_epi16(_mm256_sub_epi16(c23_avx, res_avx3), res_avx7); + + //loop5 + result_final1[0]=res_avx0; + result_final1[1]=res_avx1; + + result_final1[2]=_mm256_add_epi16(res_avx2, c6_avx); + result_final1[3]=_mm256_add_epi16(res_avx3, c22_avx); + + + result_final1[4]=_mm256_add_epi16(res_avx4, c7_avx); + result_final1[5]=_mm256_add_epi16(res_avx5, c23_avx); + + result_final1[6]=res_avx6; + result_final1[7]=res_avx7; + + + //------------------------AVX interpolation for 2nd poly ends-------------- + + //------------------------AVX interpolation for 3rd poly external------------------- + + //loop1 + res_avx0 = c_bucket[34]; //c_bucket0 + res_avx2 = c_bucket[35]; //c_bucket1 + res_avx4 = c_bucket[36]; + res_avx6 = c_bucket[37]; + + c6_avx=c_bucket[40]; + c7_avx=c_bucket[41]; + + c8_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[42], c6_avx), c7_avx); + + res_avx1 = c_bucket[50]; //c_bucket0 + res_avx3 = c_bucket[51]; //c_bucket1 + res_avx5 = c_bucket[52]; + res_avx7 = c_bucket[53]; + + c22_avx=c_bucket[56]; + c23_avx=c_bucket[57]; + + c21_avx=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[55], res_avx5),res_avx7); + + c24_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[58], c22_avx), c23_avx); + + c20_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[54], res_avx1), res_avx3); + + temp=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[39], res_avx4),res_avx6); + res_avx5 = _mm256_add_epi16(res_avx5, temp); + + temp = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[38], res_avx0), res_avx2); + res_avx1 = _mm256_add_epi16(res_avx1, temp); + + c22_avx=_mm256_add_epi16(c22_avx, c8_avx); + + res_avx6 = _mm256_add_epi16(res_avx6, c21_avx); + + res_avx2 = _mm256_add_epi16(res_avx2, c20_avx); + + c7_avx=_mm256_add_epi16(c7_avx, c24_avx); + + //loop4 + c6_avx=_mm256_sub_epi16(_mm256_sub_epi16(c6_avx, res_avx0), res_avx4); + c22_avx=_mm256_sub_epi16(_mm256_sub_epi16(c22_avx, res_avx1), res_avx5); + + c7_avx=_mm256_sub_epi16(_mm256_sub_epi16(c7_avx, res_avx2), res_avx6); + c23_avx=_mm256_sub_epi16(_mm256_sub_epi16(c23_avx, res_avx3), res_avx7); + //loop5 + result_final2[0]=res_avx0; + result_final2[1]=res_avx1; + + result_final2[2]=_mm256_add_epi16(res_avx2, c6_avx); + result_final2[3]=_mm256_add_epi16(res_avx3, c22_avx); + + + result_final2[4]=_mm256_add_epi16(res_avx4, c7_avx); + result_final2[5]=_mm256_add_epi16(res_avx5, c23_avx); + + result_final2[6]=res_avx6; + result_final2[7]=res_avx7; + + //------------------------AVX interpolation for 3rd poly ends-------------- + + //------------------------AVX interpolation for 4th poly external------------------- + + //loop1 + res_avx0 = c_bucket[43]; + res_avx2 = c_bucket[44]; + res_avx4 = c_bucket[45]; + res_avx6 = c_bucket[46]; + + c6_avx=c_bucket[65]; + c7_avx=c_bucket[66]; + + c8_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[67], c6_avx), c7_avx); + + res_avx1 = c_bucket[59]; + res_avx3 = c_bucket[60]; + res_avx5 = c_bucket[61]; + res_avx7 = c_bucket[62]; + + c22_avx=c_bucket[81]; + c23_avx=c_bucket[82]; + + c21_avx=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[80], res_avx5),res_avx7); + + c24_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[83], c22_avx), c23_avx); + + c20_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[63], res_avx1), res_avx3); + + temp=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[64], res_avx4),res_avx6); + res_avx5 = _mm256_add_epi16(res_avx5, temp); + + temp = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[47], res_avx0), res_avx2); + res_avx1 = _mm256_add_epi16(res_avx1, temp); + + c22_avx=_mm256_add_epi16(c22_avx, c8_avx); + + res_avx6 = _mm256_add_epi16(res_avx6, c21_avx); + + res_avx2 = _mm256_add_epi16(res_avx2, c20_avx); + + c7_avx=_mm256_add_epi16(c7_avx, c24_avx); + + + //loop4 + + c6_avx=_mm256_sub_epi16(_mm256_sub_epi16(c6_avx, res_avx0), res_avx4); + c22_avx=_mm256_sub_epi16(_mm256_sub_epi16(c22_avx, res_avx1), res_avx5); + + c7_avx=_mm256_sub_epi16(_mm256_sub_epi16(c7_avx, res_avx2), res_avx6); + c23_avx=_mm256_sub_epi16(_mm256_sub_epi16(c23_avx, res_avx3), res_avx7); + + //loop5 + result_final3[0]=res_avx0; + result_final3[1]=res_avx1; + + result_final3[2]=_mm256_add_epi16(res_avx2, c6_avx); + result_final3[3]=_mm256_add_epi16(res_avx3, c22_avx); + + + result_final3[4]=_mm256_add_epi16(res_avx4, c7_avx); + result_final3[5]=_mm256_add_epi16(res_avx5, c23_avx); + + result_final3[6]=res_avx6; + result_final3[7]=res_avx7; + + + //------------------------AVX interpolation for 4th poly ends-------------- + + //------------------------AVX interpolation for 5th poly external------------------- + + //loop1 + res_avx0 = c_bucket[68]; + res_avx2 = c_bucket[69]; + res_avx4 = c_bucket[70]; + res_avx6 = c_bucket[71]; + + c6_avx=c_bucket[74]; + c7_avx=c_bucket[75]; + + c8_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[76], c6_avx), c7_avx); + + res_avx1 = c_bucket[84]; + res_avx3 = c_bucket[85]; + res_avx5 = c_bucket[86]; + res_avx7 = c_bucket[87]; + + c22_avx=c_bucket[90]; + c23_avx=c_bucket[91]; + + c21_avx=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[89], res_avx5),res_avx7); + + c24_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[92], c22_avx), c23_avx); + + c20_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[88], res_avx1), res_avx3); + + temp=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[73], res_avx4),res_avx6); + res_avx5 = _mm256_add_epi16(res_avx5, temp); + + temp = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[72], res_avx0), res_avx2); + res_avx1 = _mm256_add_epi16(res_avx1, temp); + + c22_avx=_mm256_add_epi16(c22_avx, c8_avx); + + res_avx6 = _mm256_add_epi16(res_avx6, c21_avx); + + res_avx2 = _mm256_add_epi16(res_avx2, c20_avx); + + c7_avx=_mm256_add_epi16(c7_avx, c24_avx); + + + //loop4 + + c6_avx=_mm256_sub_epi16(_mm256_sub_epi16(c6_avx, res_avx0), res_avx4); + c22_avx=_mm256_sub_epi16(_mm256_sub_epi16(c22_avx, res_avx1), res_avx5); + + c7_avx=_mm256_sub_epi16(_mm256_sub_epi16(c7_avx, res_avx2), res_avx6); + c23_avx=_mm256_sub_epi16(_mm256_sub_epi16(c23_avx, res_avx3), res_avx7); + + //loop5 + result_final4[0]=res_avx0; + result_final4[1]=res_avx1; + + result_final4[2]=_mm256_add_epi16(res_avx2, c6_avx); + result_final4[3]=_mm256_add_epi16(res_avx3, c22_avx); + + + result_final4[4]=_mm256_add_epi16(res_avx4, c7_avx); + result_final4[5]=_mm256_add_epi16(res_avx5, c23_avx); + + result_final4[6]=res_avx6; + result_final4[7]=res_avx7; + + + //------------------------AVX interpolation for 5th poly ends-------------- + + //------------------------AVX interpolation for 6th poly external------------------- + + //loop1 + res_avx0 = c_bucket[77]; + res_avx2 = c_bucket[78]; + res_avx4 = c_bucket[79]; + res_avx6 = c_bucket[96]; + + c6_avx=c_bucket[99]; + c7_avx=c_bucket[100]; + + c8_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[101], c6_avx), c7_avx); + + res_avx1 = c_bucket[93]; + res_avx3 = c_bucket[94]; + res_avx5 = c_bucket[95]; + res_avx7 = c_bucket[112]; + + c22_avx=c_bucket[115]; + c23_avx=c_bucket[116]; + + c21_avx=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[114], res_avx5),res_avx7); + + c24_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[117], c22_avx), c23_avx); + + c20_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[113], res_avx1), res_avx3); + + temp=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[98], res_avx4),res_avx6); + res_avx5 = _mm256_add_epi16(res_avx5, temp); + + temp = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[97], res_avx0), res_avx2); + res_avx1 = _mm256_add_epi16(res_avx1, temp); + + c22_avx=_mm256_add_epi16(c22_avx, c8_avx); + + res_avx6 = _mm256_add_epi16(res_avx6, c21_avx); + + res_avx2 = _mm256_add_epi16(res_avx2, c20_avx); + + c7_avx=_mm256_add_epi16(c7_avx, c24_avx); + + + //loop4 + + c6_avx=_mm256_sub_epi16(_mm256_sub_epi16(c6_avx, res_avx0), res_avx4); + c22_avx=_mm256_sub_epi16(_mm256_sub_epi16(c22_avx, res_avx1), res_avx5); + + c7_avx=_mm256_sub_epi16(_mm256_sub_epi16(c7_avx, res_avx2), res_avx6); + c23_avx=_mm256_sub_epi16(_mm256_sub_epi16(c23_avx, res_avx3), res_avx7); + + //loop5 + result_final5[0]=res_avx0; + result_final5[1]=res_avx1; + + result_final5[2]=_mm256_add_epi16(res_avx2, c6_avx); + result_final5[3]=_mm256_add_epi16(res_avx3, c22_avx); + + + result_final5[4]=_mm256_add_epi16(res_avx4, c7_avx); + result_final5[5]=_mm256_add_epi16(res_avx5, c23_avx); + + result_final5[6]=res_avx6; + result_final5[7]=res_avx7; + + + //------------------------AVX interpolation for 6th poly ends-------------- + + //------------------------AVX interpolation for 7th poly external------------------- + + //loop1 + res_avx0 = c_bucket[102]; + res_avx2 = c_bucket[103]; + res_avx4 = c_bucket[104]; + res_avx6 = c_bucket[105]; + + c6_avx=c_bucket[108]; + c7_avx=c_bucket[109]; + + c8_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[110], c6_avx), c7_avx); + + res_avx1 = c_bucket[118]; + res_avx3 = c_bucket[119]; + res_avx5 = c_bucket[120]; + res_avx7 = c_bucket[121]; + + c22_avx=c_bucket[124]; + c23_avx=c_bucket[125]; + + c21_avx=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[123], res_avx5),res_avx7); + + c24_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[126], c22_avx), c23_avx); + + c20_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[122], res_avx1), res_avx3); + + temp=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[107], res_avx4),res_avx6); + res_avx5 = _mm256_add_epi16(res_avx5, temp); + + temp = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[106], res_avx0), res_avx2); + res_avx1 = _mm256_add_epi16(res_avx1, temp); + + c22_avx=_mm256_add_epi16(c22_avx, c8_avx); + + res_avx6 = _mm256_add_epi16(res_avx6, c21_avx); + + res_avx2 = _mm256_add_epi16(res_avx2, c20_avx); + + c7_avx=_mm256_add_epi16(c7_avx, c24_avx); + + + //loop4 + + c6_avx=_mm256_sub_epi16(_mm256_sub_epi16(c6_avx, res_avx0), res_avx4); + c22_avx=_mm256_sub_epi16(_mm256_sub_epi16(c22_avx, res_avx1), res_avx5); + + c7_avx=_mm256_sub_epi16(_mm256_sub_epi16(c7_avx, res_avx2), res_avx6); + c23_avx=_mm256_sub_epi16(_mm256_sub_epi16(c23_avx, res_avx3), res_avx7); + + //loop5 + result_final6[0]=res_avx0; + result_final6[1]=res_avx1; + + result_final6[2]=_mm256_add_epi16(res_avx2, c6_avx); + result_final6[3]=_mm256_add_epi16(res_avx3, c22_avx); + + + result_final6[4]=_mm256_add_epi16(res_avx4, c7_avx); + result_final6[5]=_mm256_add_epi16(res_avx5, c23_avx); + + result_final6[6]=res_avx6; + result_final6[7]=res_avx7; + + + //------------------------AVX interpolation for 7th poly ends-------------- + + //CLOCK2=cpucycles(); + //CLOCK_INTER=CLOCK_INTER+(CLOCK2-CLOCK1); + //printf("\nTime for interpolation : %llu\n", CLOCK2-CLOCK1); + + + +} + +static void toom_cook_4way_avx_n1(__m256i* a_avx,__m256i* b_bucket, __m256i *c_bucket, int f){ + + int i; + +//---------------AVX data----------------------------- + + __m256i r0_avx, r1_avx, r2_avx, r3_avx, r4_avx, r5_avx, r6_avx; + __m256i aw_avx[7*small_len_avx]; + +//----------------AVX data---------------------------- + + +// EVALUATION + + //CLOCK1=cpucycles(); + + for (i=0; i>= 63; + return (uint8_t) r; +} + +/* b = 1 means mov, b = 0 means don't mov*/ +void PQCLEAN_FIRESABER_AVX2_cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b) { + size_t i; + + b = -b; + for (i = 0; i < len; i++) { + r[i] ^= b & (x[i] ^ r[i]); + } +} diff --git a/crypto_kem/firesaber/avx2/verify.h b/crypto_kem/firesaber/avx2/verify.h new file mode 100644 index 00000000..2ec50370 --- /dev/null +++ b/crypto_kem/firesaber/avx2/verify.h @@ -0,0 +1,22 @@ +#ifndef VERIFY_H +#define VERIFY_H +/*------------------------------------------------- +This file has been adapted from the implementation +(available at https://github.com/pq-crystals/kyber) of +"CRYSTALS – Kyber: a CCA-secure module-lattice-based KEM" + by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint, +Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle +----------------------------------------------------*/ + +#include +#include + +/* returns 0 for equal strings, 1 for non-equal strings */ +uint8_t PQCLEAN_FIRESABER_AVX2_verify(const uint8_t *a, const uint8_t *b, size_t len); + + +/* b = 1 means mov, b = 0 means don't mov*/ +void PQCLEAN_FIRESABER_AVX2_cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b); + + +#endif diff --git a/crypto_kem/firesaber/clean/LICENSE b/crypto_kem/firesaber/clean/LICENSE index 08c799e3..d5d21fff 100644 --- a/crypto_kem/firesaber/clean/LICENSE +++ b/crypto_kem/firesaber/clean/LICENSE @@ -1,8 +1 @@ ----------------------------------------------------------------------------------------- -SABER_v1.1 - -Public domain - -Authors: Jan-Pieter D'Anvers, Angshuman Karmakar, Sujoy Sinha Roy, -Frederik Vercauteren ----------------------------------------------------------------------------------------- +Public Domain diff --git a/crypto_kem/firesaber/clean/Makefile b/crypto_kem/firesaber/clean/Makefile index e00112e8..8f8dd8f7 100644 --- a/crypto_kem/firesaber/clean/Makefile +++ b/crypto_kem/firesaber/clean/Makefile @@ -1,10 +1,10 @@ # This Makefile can be used with GNU Make or BSD Make LIB=libfiresaber_clean.a -HEADERS=api.h cbd.h poly.h poly_mul.h SABER_indcpa.h SABER_params.h verify.h pack_unpack.h +HEADERS=api.h cbd.h pack_unpack.h poly.h poly_mul.h SABER_indcpa.h SABER_params.h verify.h OBJECTS=cbd.o kem.o pack_unpack.o poly.o poly_mul.o SABER_indcpa.o verify.o -CFLAGS=-O3 -Wall -Wextra -Wpedantic -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wredundant-decls -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_kem/firesaber/clean/SABER_indcpa.c b/crypto_kem/firesaber/clean/SABER_indcpa.c index da8aa685..8f4364e7 100644 --- a/crypto_kem/firesaber/clean/SABER_indcpa.c +++ b/crypto_kem/firesaber/clean/SABER_indcpa.c @@ -3,296 +3,90 @@ #include "fips202.h" #include "pack_unpack.h" #include "poly.h" -#include "poly_mul.h" #include "randombytes.h" #include #include +#define h1 (1 << (SABER_EQ - SABER_EP - 1)) +#define h2 ((1 << (SABER_EP - 2)) - (1 << (SABER_EP - SABER_ET - 1)) + (1 << (SABER_EQ - SABER_EP - 1))) +void PQCLEAN_FIRESABER_CLEAN_indcpa_kem_keypair(uint8_t pk[SABER_INDCPA_PUBLICKEYBYTES], uint8_t sk[SABER_INDCPA_SECRETKEYBYTES]) { + uint16_t A[SABER_L][SABER_L][SABER_N]; + uint16_t s[SABER_L][SABER_N]; + uint16_t b[SABER_L][SABER_N] = {0}; -/*----------------------------------------------------------------------------------- - This routine generates a=[Matrix K x K] of 256-coefficient polynomials --------------------------------------------------------------------------------------*/ + uint8_t seed_A[SABER_SEEDBYTES]; + uint8_t seed_s[SABER_NOISE_SEEDBYTES]; + int i, j; -#define h1 4 //2^(EQ-EP-1) + randombytes(seed_A, SABER_SEEDBYTES); + shake128(seed_A, SABER_SEEDBYTES, seed_A, SABER_SEEDBYTES); // for not revealing system RNG state + randombytes(seed_s, SABER_NOISE_SEEDBYTES); -#define h2 ( (1<<(SABER_EP-2)) - (1<<(SABER_EP-SABER_ET-1)) + (1<<(SABER_EQ-SABER_EP-1)) ) + PQCLEAN_FIRESABER_CLEAN_GenMatrix(A, seed_A); + PQCLEAN_FIRESABER_CLEAN_GenSecret(s, seed_s); + PQCLEAN_FIRESABER_CLEAN_MatrixVectorMul(b, (const uint16_t (*)[SABER_L][SABER_N])A, (const uint16_t (*)[SABER_N])s, 1); -static void InnerProd(uint16_t pkcl[SABER_K][SABER_N], uint16_t skpv[SABER_K][SABER_N], uint16_t mod, uint16_t res[SABER_N]); -static void MatrixVectorMul(polyvec *a, uint16_t skpv[SABER_K][SABER_N], uint16_t res[SABER_K][SABER_N], uint16_t mod, int16_t transpose); - -static void POL2MSG(const uint16_t *message_dec_unpacked, unsigned char *message_dec); - -static void GenMatrix(polyvec *a, const unsigned char *seed) { - unsigned char buf[SABER_K * SABER_K * (13 * SABER_N / 8)]; - - uint16_t temp_ar[SABER_N]; - - int i, j, k; - uint16_t mod = (SABER_Q - 1); - - shake128(buf, sizeof(buf), seed, SABER_SEEDBYTES); - - for (i = 0; i < SABER_K; i++) { - for (j = 0; j < SABER_K; j++) { - PQCLEAN_FIRESABER_CLEAN_BS2POL(buf + (i * SABER_K + j) * (13 * SABER_N / 8), temp_ar); - for (k = 0; k < SABER_N; k++) { - a[i].vec[j].coeffs[k] = (temp_ar[k])& mod ; - } + for (i = 0; i < SABER_L; i++) { + for (j = 0; j < SABER_N; j++) { + b[i][j] = (b[i][j] + h1) >> (SABER_EQ - SABER_EP); } } + + PQCLEAN_FIRESABER_CLEAN_POLVECq2BS(sk, (const uint16_t (*)[SABER_N])s); + PQCLEAN_FIRESABER_CLEAN_POLVECp2BS(pk, (const uint16_t (*)[SABER_N])b); + memcpy(pk + SABER_POLYVECCOMPRESSEDBYTES, seed_A, sizeof(seed_A)); } +void PQCLEAN_FIRESABER_CLEAN_indcpa_kem_enc(uint8_t ciphertext[SABER_BYTES_CCA_DEC], const uint8_t m[SABER_KEYBYTES], const uint8_t seed_sp[SABER_NOISE_SEEDBYTES], const uint8_t pk[SABER_INDCPA_PUBLICKEYBYTES]) { + uint16_t A[SABER_L][SABER_L][SABER_N]; + uint16_t sp[SABER_L][SABER_N]; + uint16_t bp[SABER_L][SABER_N] = {0}; + uint16_t vp[SABER_N] = {0}; + uint16_t mp[SABER_N]; + uint16_t b[SABER_L][SABER_N]; + int i, j; + const uint8_t *seed_A = pk + SABER_POLYVECCOMPRESSEDBYTES; -void PQCLEAN_FIRESABER_CLEAN_indcpa_kem_keypair(unsigned char *pk, unsigned char *sk) { - polyvec a[SABER_K]; + PQCLEAN_FIRESABER_CLEAN_GenMatrix(A, seed_A); + PQCLEAN_FIRESABER_CLEAN_GenSecret(sp, seed_sp); + PQCLEAN_FIRESABER_CLEAN_MatrixVectorMul(bp, (const uint16_t (*)[SABER_L][SABER_N])A, (const uint16_t (*)[SABER_N])sp, 0); - uint16_t skpv[SABER_K][SABER_N]; - - unsigned char seed[SABER_SEEDBYTES]; - unsigned char noiseseed[SABER_COINBYTES]; - int32_t i, j; - uint16_t mod_q = SABER_Q - 1; - - - uint16_t res[SABER_K][SABER_N]; - - randombytes(seed, SABER_SEEDBYTES); - - // for not revealing system RNG state - shake128(seed, SABER_SEEDBYTES, seed, SABER_SEEDBYTES); - randombytes(noiseseed, SABER_COINBYTES); - - GenMatrix(a, seed); //sample matrix A - - // generate secret from constant-time binomial distribution - PQCLEAN_FIRESABER_CLEAN_GenSecret(skpv, noiseseed); - - // do the matrix vector multiplication and rounding - for (i = 0; i < SABER_K; i++) { + for (i = 0; i < SABER_L; i++) { for (j = 0; j < SABER_N; j++) { - res[i][j] = 0; - } - } - MatrixVectorMul(a, skpv, res, SABER_Q - 1, 1); - - // now rounding - for (i = 0; i < SABER_K; i++) { - for (j = 0; j < SABER_N; j++) { - // shift right 3 bits - res[i][j] = (res[i][j] + h1) & (mod_q); - res[i][j] = (res[i][j] >> (SABER_EQ - SABER_EP)); + bp[i][j] = (bp[i][j] + h1) >> (SABER_EQ - SABER_EP); } } - // unload and pack sk=3 x (256 coefficients of 14 bits) - PQCLEAN_FIRESABER_CLEAN_POLVEC2BS(sk, skpv, SABER_Q); + PQCLEAN_FIRESABER_CLEAN_POLVECp2BS(ciphertext, (const uint16_t (*)[SABER_N])bp); + PQCLEAN_FIRESABER_CLEAN_BS2POLVECp(b, pk); + PQCLEAN_FIRESABER_CLEAN_InnerProd(vp, (const uint16_t (*)[SABER_N])b, (const uint16_t (*)[SABER_N])sp); - // unload and pack pk=256 bits seed and 3 x (256 coefficients of 11 bits) - // load the public-key coefficients - PQCLEAN_FIRESABER_CLEAN_POLVEC2BS(pk, res, SABER_P); + PQCLEAN_FIRESABER_CLEAN_BS2POLmsg(mp, m); - - // now load the seedbytes in PK. Easy since seed bytes are kept in byte format. - for (i = 0; i < SABER_SEEDBYTES; i++) { - pk[SABER_POLYVECCOMPRESSEDBYTES + i] = seed[i]; + for (j = 0; j < SABER_N; j++) { + vp[j] = (vp[j] - (mp[j] << (SABER_EP - 1)) + h1) >> (SABER_EP - SABER_ET); } + PQCLEAN_FIRESABER_CLEAN_POLT2BS(ciphertext + SABER_POLYVECCOMPRESSEDBYTES, vp); } +void PQCLEAN_FIRESABER_CLEAN_indcpa_kem_dec(uint8_t m[SABER_KEYBYTES], const uint8_t sk[SABER_INDCPA_SECRETKEYBYTES], const uint8_t ciphertext[SABER_BYTES_CCA_DEC]) { -void PQCLEAN_FIRESABER_CLEAN_indcpa_kem_enc(const unsigned char *message_received, unsigned char *noiseseed, const unsigned char *pk, unsigned char *ciphertext) { - uint32_t i, j, k; - polyvec a[SABER_K]; - unsigned char seed[SABER_SEEDBYTES]; - // public key of received by the client - uint16_t pkcl[SABER_K][SABER_N]; - uint16_t skpv1[SABER_K][SABER_N]; - uint16_t message[SABER_KEYBYTES * 8]; - uint16_t res[SABER_K][SABER_N]; - uint16_t mod_p = SABER_P - 1; - uint16_t mod_q = SABER_Q - 1; - uint16_t vprime[SABER_N]; - unsigned char msk_c[SABER_SCALEBYTES_KEM]; + uint16_t s[SABER_L][SABER_N]; + uint16_t b[SABER_L][SABER_N]; + uint16_t v[SABER_N] = {0}; + uint16_t cm[SABER_N]; + int i; - // extract the seedbytes from Public Key. - for (i = 0; i < SABER_SEEDBYTES; i++) { - seed[i] = pk[ SABER_POLYVECCOMPRESSEDBYTES + i]; - } + PQCLEAN_FIRESABER_CLEAN_BS2POLVECq(s, sk); + PQCLEAN_FIRESABER_CLEAN_BS2POLVECp(b, ciphertext); + PQCLEAN_FIRESABER_CLEAN_InnerProd(v, (const uint16_t (*)[SABER_N])b, (const uint16_t (*)[SABER_N])s); + PQCLEAN_FIRESABER_CLEAN_BS2POLT(cm, ciphertext + SABER_POLYVECCOMPRESSEDBYTES); - GenMatrix(a, seed); - - // generate secret from constant-time binomial distribution - PQCLEAN_FIRESABER_CLEAN_GenSecret(skpv1, noiseseed); - - // matrix-vector multiplication and rounding - for (i = 0; i < SABER_K; i++) { - for (j = 0; j < SABER_N; j++) { - res[i][j] = 0; - } - } - MatrixVectorMul(a, skpv1, res, SABER_Q - 1, 0); - - // now rounding - //shift right 3 bits - for (i = 0; i < SABER_K; i++) { - for (j = 0; j < SABER_N; j++) { - res[i][j] = ( res[i][j] + h1 ) & mod_q; - res[i][j] = (res[i][j] >> (SABER_EQ - SABER_EP) ); - } - } - - PQCLEAN_FIRESABER_CLEAN_POLVEC2BS(ciphertext, res, SABER_P); - - // ************client matrix-vector multiplication ends************ - - // now calculate the v' - // unpack the public_key - // pkcl is the b in the protocol - PQCLEAN_FIRESABER_CLEAN_BS2POLVEC(pk, pkcl, SABER_P); for (i = 0; i < SABER_N; i++) { - vprime[i] = 0; - } - for (i = 0; i < SABER_K; i++) { - for (j = 0; j < SABER_N; j++) { - skpv1[i][j] = skpv1[i][j] & (mod_p); - } + v[i] = (v[i] + h2 - (cm[i] << (SABER_EP - SABER_ET))) >> (SABER_EP - 1); } - // vector-vector scalar multiplication with mod p - InnerProd(pkcl, skpv1, mod_p, vprime); - - // addition of h1 to vprime - for (i = 0; i < SABER_N; i++) { - vprime[i] = vprime[i] + h1; - } - - // unpack message_received; - for (j = 0; j < SABER_KEYBYTES; j++) { - for (i = 0; i < 8; i++) { - message[8 * j + i] = ((message_received[j] >> i) & 0x01); - } - } - - // message encoding - for (i = 0; i < SABER_N; i++) { - message[i] = (message[i] << (SABER_EP - 1)); - } - - for (k = 0; k < SABER_N; k++) { - vprime[k] = ( (vprime[k] - message[k]) & (mod_p) ) >> (SABER_EP - SABER_ET); - } - - - PQCLEAN_FIRESABER_CLEAN_pack_6bit(msk_c, vprime); - - for (j = 0; j < SABER_SCALEBYTES_KEM; j++) { - ciphertext[SABER_POLYVECCOMPRESSEDBYTES + j] = msk_c[j]; - } -} - - -void PQCLEAN_FIRESABER_CLEAN_indcpa_kem_dec(const unsigned char *sk, const unsigned char *ciphertext, unsigned char message_dec[]) { - uint32_t i, j; - // secret key of the server - uint16_t sksv[SABER_K][SABER_N]; - uint16_t pksv[SABER_K][SABER_N]; - uint8_t scale_ar[SABER_SCALEBYTES_KEM]; - uint16_t mod_p = SABER_P - 1; - uint16_t v[SABER_N]; - uint16_t op[SABER_N]; - - // sksv is the secret-key - PQCLEAN_FIRESABER_CLEAN_BS2POLVEC(sk, sksv, SABER_Q); - // pksv is the ciphertext - PQCLEAN_FIRESABER_CLEAN_BS2POLVEC(ciphertext, pksv, SABER_P); - - // vector-vector scalar multiplication with mod p - for (i = 0; i < SABER_N; i++) { - v[i] = 0; - } - for (i = 0; i < SABER_K; i++) { - for (j = 0; j < SABER_N; j++) { - sksv[i][j] = sksv[i][j] & (mod_p); - } - } - InnerProd(pksv, sksv, mod_p, v); - - //Extraction - for (i = 0; i < SABER_SCALEBYTES_KEM; i++) { - scale_ar[i] = ciphertext[SABER_POLYVECCOMPRESSEDBYTES + i]; - } - - PQCLEAN_FIRESABER_CLEAN_un_pack6bit(scale_ar, op); - - //addition of h1 - for (i = 0; i < SABER_N; i++) { - v[i] = ( ( v[i] + h2 - (op[i] << (SABER_EP - SABER_ET)) ) & (mod_p) ) >> (SABER_EP - 1); - } - - // pack decrypted message - POL2MSG(v, message_dec); -} -static void MatrixVectorMul(polyvec *a, uint16_t skpv[SABER_K][SABER_N], uint16_t res[SABER_K][SABER_N], uint16_t mod, int16_t transpose) { - uint16_t acc[SABER_N]; - int32_t i, j, k; - - if (transpose == 1) { - for (i = 0; i < SABER_K; i++) { - for (j = 0; j < SABER_K; j++) { - PQCLEAN_FIRESABER_CLEAN_pol_mul((uint16_t *)&a[j].vec[i], skpv[j], acc, SABER_Q, SABER_N); - - for (k = 0; k < SABER_N; k++) { - res[i][k] = res[i][k] + acc[k]; - //reduction mod p - res[i][k] = (res[i][k] & mod); - //clear the accumulator - acc[k] = 0; - } - } - } - } else { - for (i = 0; i < SABER_K; i++) { - for (j = 0; j < SABER_K; j++) { - PQCLEAN_FIRESABER_CLEAN_pol_mul((uint16_t *)&a[i].vec[j], skpv[j], acc, SABER_Q, SABER_N); - for (k = 0; k < SABER_N; k++) { - res[i][k] = res[i][k] + acc[k]; - // reduction - res[i][k] = res[i][k] & mod; - // clear the accumulator - acc[k] = 0; - } - } - } - } -} - -static void POL2MSG(const uint16_t *message_dec_unpacked, unsigned char *message_dec) { - int32_t i, j; - - for (j = 0; j < SABER_KEYBYTES; j++) { - message_dec[j] = 0; - for (i = 0; i < 8; i++) { - message_dec[j] = message_dec[j] | (uint8_t) (message_dec_unpacked[j * 8 + i] << i); - } - } -} - - -static void InnerProd(uint16_t pkcl[SABER_K][SABER_N], uint16_t skpv[SABER_K][SABER_N], uint16_t mod, uint16_t res[SABER_N]) { - uint32_t j, k; - uint16_t acc[SABER_N]; - - // vector-vector scalar multiplication with mod p - for (j = 0; j < SABER_K; j++) { - PQCLEAN_FIRESABER_CLEAN_pol_mul(pkcl[j], skpv[j], acc, SABER_P, SABER_N); - - for (k = 0; k < SABER_N; k++) { - res[k] = res[k] + acc[k]; - // reduction - res[k] = res[k] & mod; - // clear the accumulator - acc[k] = 0; - } - } + PQCLEAN_FIRESABER_CLEAN_POLmsg2BS(m, v); } diff --git a/crypto_kem/firesaber/clean/SABER_indcpa.h b/crypto_kem/firesaber/clean/SABER_indcpa.h index 6007352d..28a5feee 100644 --- a/crypto_kem/firesaber/clean/SABER_indcpa.h +++ b/crypto_kem/firesaber/clean/SABER_indcpa.h @@ -1,9 +1,13 @@ #ifndef INDCPA_H #define INDCPA_H +#include "SABER_params.h" +#include + +void PQCLEAN_FIRESABER_CLEAN_indcpa_kem_keypair(uint8_t pk[SABER_INDCPA_PUBLICKEYBYTES], uint8_t sk[SABER_INDCPA_SECRETKEYBYTES]); + +void PQCLEAN_FIRESABER_CLEAN_indcpa_kem_enc(uint8_t ciphertext[SABER_BYTES_CCA_DEC], const uint8_t m[SABER_KEYBYTES], const uint8_t seed_sp[SABER_NOISE_SEEDBYTES], const uint8_t pk[SABER_INDCPA_PUBLICKEYBYTES]); + +void PQCLEAN_FIRESABER_CLEAN_indcpa_kem_dec(uint8_t m[SABER_KEYBYTES], const uint8_t sk[SABER_INDCPA_SECRETKEYBYTES], const uint8_t ciphertext[SABER_BYTES_CCA_DEC]); -void PQCLEAN_FIRESABER_CLEAN_indcpa_kem_keypair(unsigned char *pk, unsigned char *sk); -void PQCLEAN_FIRESABER_CLEAN_indcpa_kem_enc(const unsigned char *message, unsigned char *noiseseed, const unsigned char *pk, unsigned char *ciphertext); -void PQCLEAN_FIRESABER_CLEAN_indcpa_kem_dec(const unsigned char *sk, const unsigned char *ciphertext, unsigned char *message_dec); #endif - diff --git a/crypto_kem/firesaber/clean/SABER_params.h b/crypto_kem/firesaber/clean/SABER_params.h index b0d517f8..9121a12b 100644 --- a/crypto_kem/firesaber/clean/SABER_params.h +++ b/crypto_kem/firesaber/clean/SABER_params.h @@ -1,49 +1,39 @@ #ifndef PARAMS_H #define PARAMS_H -#include "api.h" -#define SABER_K 4 +/* Change this for different security strengths */ + +/* Don't change anything below this line */ +#define SABER_L 4 #define SABER_MU 6 #define SABER_ET 6 #define SABER_EQ 13 #define SABER_EP 10 - #define SABER_N 256 -#define SABER_Q 8192 -#define SABER_P 1024 -#define SABER_SEEDBYTES 32 -#define SABER_NOISESEEDBYTES 32 -#define SABER_COINBYTES 32 -#define SABER_KEYBYTES 32 +#define SABER_SEEDBYTES 32 +#define SABER_NOISE_SEEDBYTES 32 +#define SABER_KEYBYTES 32 +#define SABER_HASHBYTES 32 -#define SABER_HASHBYTES 32 +#define SABER_POLYCOINBYTES (SABER_MU * SABER_N / 8) -#define SABER_POLYBYTES 416 //13*256/8 +#define SABER_POLYBYTES (SABER_EQ * SABER_N / 8) +#define SABER_POLYVECBYTES (SABER_L * SABER_POLYBYTES) -#define SABER_POLYVECBYTES (SABER_K * SABER_POLYBYTES) +#define SABER_POLYCOMPRESSEDBYTES (SABER_EP * SABER_N / 8) +#define SABER_POLYVECCOMPRESSEDBYTES (SABER_L * SABER_POLYCOMPRESSEDBYTES) -#define SABER_POLYVECCOMPRESSEDBYTES (SABER_K * 320) //10*256/8 NOTE : changed till here due to parameter adaptation - -#define SABER_CIPHERTEXTBYTES (SABER_POLYVECCOMPRESSEDBYTES) - -#define SABER_SCALEBYTES (SABER_DELTA*SABER_N/8) - -#define SABER_SCALEBYTES_KEM ((SABER_ET)*SABER_N/8) +#define SABER_SCALEBYTES_KEM (SABER_ET * SABER_N / 8) #define SABER_INDCPA_PUBLICKEYBYTES (SABER_POLYVECCOMPRESSEDBYTES + SABER_SEEDBYTES) #define SABER_INDCPA_SECRETKEYBYTES (SABER_POLYVECBYTES) #define SABER_PUBLICKEYBYTES (SABER_INDCPA_PUBLICKEYBYTES) +#define SABER_SECRETKEYBYTES (SABER_INDCPA_SECRETKEYBYTES + SABER_INDCPA_PUBLICKEYBYTES + SABER_HASHBYTES + SABER_KEYBYTES) -#define SABER_SECRETKEYBYTES (SABER_INDCPA_SECRETKEYBYTES + SABER_INDCPA_PUBLICKEYBYTES + SABER_HASHBYTES + SABER_KEYBYTES) - -#define SABER_BYTES_CCA_DEC (SABER_POLYVECCOMPRESSEDBYTES + SABER_SCALEBYTES_KEM) /* Second part is for Targhi-Unruh */ - - - +#define SABER_BYTES_CCA_DEC (SABER_POLYVECCOMPRESSEDBYTES + SABER_SCALEBYTES_KEM) #endif - diff --git a/crypto_kem/firesaber/clean/api.h b/crypto_kem/firesaber/clean/api.h index 56d17038..14718674 100644 --- a/crypto_kem/firesaber/clean/api.h +++ b/crypto_kem/firesaber/clean/api.h @@ -1,14 +1,18 @@ #ifndef PQCLEAN_FIRESABER_CLEAN_API_H #define PQCLEAN_FIRESABER_CLEAN_API_H + #define PQCLEAN_FIRESABER_CLEAN_CRYPTO_ALGNAME "FireSaber" -#define PQCLEAN_FIRESABER_CLEAN_CRYPTO_SECRETKEYBYTES 3040 -#define PQCLEAN_FIRESABER_CLEAN_CRYPTO_PUBLICKEYBYTES (4*320+32) #define PQCLEAN_FIRESABER_CLEAN_CRYPTO_BYTES 32 #define PQCLEAN_FIRESABER_CLEAN_CRYPTO_CIPHERTEXTBYTES 1472 +#define PQCLEAN_FIRESABER_CLEAN_CRYPTO_PUBLICKEYBYTES 1312 +#define PQCLEAN_FIRESABER_CLEAN_CRYPTO_SECRETKEYBYTES 3040 int PQCLEAN_FIRESABER_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk); -int PQCLEAN_FIRESABER_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk); -int PQCLEAN_FIRESABER_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk); + +int PQCLEAN_FIRESABER_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *k, const unsigned char *pk); + +int PQCLEAN_FIRESABER_CLEAN_crypto_kem_dec(unsigned char *k, const unsigned char *ct, const unsigned char *sk); + #endif /* api_h */ diff --git a/crypto_kem/firesaber/clean/cbd.c b/crypto_kem/firesaber/clean/cbd.c index cca885a1..8032eb5c 100644 --- a/crypto_kem/firesaber/clean/cbd.c +++ b/crypto_kem/firesaber/clean/cbd.c @@ -1,3 +1,7 @@ +#include "SABER_params.h" +#include "api.h" +#include "cbd.h" +#include /*--------------------------------------------------------------------- This file has been adapted from the implementation (available at, Public Domain https://github.com/pq-crystals/kyber) @@ -6,12 +10,8 @@ by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint, Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle ----------------------------------------------------------------------*/ -#include "SABER_params.h" -#include "api.h" -#include "cbd.h" -#include -static uint64_t load_littleendian(const unsigned char *x, int bytes) { +static uint64_t load_littleendian(const uint8_t *x, int bytes) { int i; uint64_t r = x[0]; for (i = 1; i < bytes; i++) { @@ -20,33 +20,29 @@ static uint64_t load_littleendian(const unsigned char *x, int bytes) { return r; } - -void PQCLEAN_FIRESABER_CLEAN_cbd(uint16_t *r, const unsigned char *buf) { - uint16_t Qmod_minus1 = SABER_Q - 1; - +void PQCLEAN_FIRESABER_CLEAN_cbd(uint16_t s[SABER_N], const uint8_t buf[SABER_POLYCOINBYTES]) { uint32_t t, d, a[4], b[4]; int i, j; for (i = 0; i < SABER_N / 4; i++) { - t = (uint32_t) load_littleendian(buf + 3 * i, 3); + t = load_littleendian(buf + 3 * i, 3); d = 0; for (j = 0; j < 3; j++) { d += (t >> j) & 0x249249; } - a[0] = d & 0x7; - b[0] = (d >> 3) & 0x7; - a[1] = (d >> 6) & 0x7; - b[1] = (d >> 9) & 0x7; + a[0] = d & 0x7; + b[0] = (d >> 3) & 0x7; + a[1] = (d >> 6) & 0x7; + b[1] = (d >> 9) & 0x7; a[2] = (d >> 12) & 0x7; b[2] = (d >> 15) & 0x7; a[3] = (d >> 18) & 0x7; b[3] = (d >> 21); - r[4 * i + 0] = (uint16_t)(a[0] - b[0]) & Qmod_minus1; - r[4 * i + 1] = (uint16_t)(a[1] - b[1]) & Qmod_minus1; - r[4 * i + 2] = (uint16_t)(a[2] - b[2]) & Qmod_minus1; - r[4 * i + 3] = (uint16_t)(a[3] - b[3]) & Qmod_minus1; - + s[4 * i + 0] = (uint16_t)(a[0] - b[0]); + s[4 * i + 1] = (uint16_t)(a[1] - b[1]); + s[4 * i + 2] = (uint16_t)(a[2] - b[2]); + s[4 * i + 3] = (uint16_t)(a[3] - b[3]); } } diff --git a/crypto_kem/firesaber/clean/cbd.h b/crypto_kem/firesaber/clean/cbd.h index b10e5202..0fa18b02 100644 --- a/crypto_kem/firesaber/clean/cbd.h +++ b/crypto_kem/firesaber/clean/cbd.h @@ -1,6 +1,5 @@ #ifndef CBD_H #define CBD_H - /*--------------------------------------------------------------------- This file has been adapted from the implementation (available at, Public Domain https://github.com/pq-crystals/kyber) @@ -8,10 +7,10 @@ of "CRYSTALS – Kyber: a CCA-secure module-lattice-based KEM" by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint, Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle ----------------------------------------------------------------------*/ - -#include "poly.h" +#include "SABER_params.h" #include -void PQCLEAN_FIRESABER_CLEAN_cbd(uint16_t *r, const unsigned char *buf); +void PQCLEAN_FIRESABER_CLEAN_cbd(uint16_t s[SABER_N], const uint8_t buf[SABER_POLYCOINBYTES]); + #endif diff --git a/crypto_kem/firesaber/clean/kem.c b/crypto_kem/firesaber/clean/kem.c index c66cfed9..e94219a6 100644 --- a/crypto_kem/firesaber/clean/kem.c +++ b/crypto_kem/firesaber/clean/kem.c @@ -1,5 +1,6 @@ #include "SABER_indcpa.h" #include "SABER_params.h" +#include "api.h" #include "fips202.h" #include "randombytes.h" #include "verify.h" @@ -7,90 +8,71 @@ #include #include -int PQCLEAN_FIRESABER_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk) { + +int PQCLEAN_FIRESABER_CLEAN_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) { int i; - // sk[0:SABER_INDCPA_SECRETKEYBYTES-1] <-- sk - PQCLEAN_FIRESABER_CLEAN_indcpa_kem_keypair(pk, sk); - - // sk[SABER_INDCPA_SECRETKEYBYTES:SABER_INDCPA_SECRETKEYBYTES+SABER_INDCPA_SECRETKEYBYTES-1] <-- pk + PQCLEAN_FIRESABER_CLEAN_indcpa_kem_keypair(pk, sk); // sk[0:SABER_INDCPA_SECRETKEYBYTES-1] <-- sk for (i = 0; i < SABER_INDCPA_PUBLICKEYBYTES; i++) { - sk[i + SABER_INDCPA_SECRETKEYBYTES] = pk[i]; + sk[i + SABER_INDCPA_SECRETKEYBYTES] = pk[i]; // sk[SABER_INDCPA_SECRETKEYBYTES:SABER_INDCPA_SECRETKEYBYTES+SABER_INDCPA_SECRETKEYBYTES-1] <-- pk } - // Then hash(pk) is appended. - sha3_256(sk + SABER_SECRETKEYBYTES - 64, pk, SABER_INDCPA_PUBLICKEYBYTES); + sha3_256(sk + SABER_SECRETKEYBYTES - 64, pk, SABER_INDCPA_PUBLICKEYBYTES); // Then hash(pk) is appended. - // Remaining part of sk contains a pseudo-random number. - // This is output when check in crypto_kem_dec() fails. - randombytes(sk + SABER_SECRETKEYBYTES - SABER_KEYBYTES, SABER_KEYBYTES ); + randombytes(sk + SABER_SECRETKEYBYTES - SABER_KEYBYTES, SABER_KEYBYTES); // Remaining part of sk contains a pseudo-random number. + // This is output when check in PQCLEAN_FIRESABER_CLEAN_crypto_kem_dec() fails. return (0); } -int PQCLEAN_FIRESABER_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) { - // Will contain key, coins - unsigned char kr[64]; - unsigned char buf[64]; +int PQCLEAN_FIRESABER_CLEAN_crypto_kem_enc(uint8_t *c, uint8_t *k, const uint8_t *pk) { + + uint8_t kr[64]; // Will contain key, coins + uint8_t buf[64]; randombytes(buf, 32); - // BUF[0:31] <-- random message (will be used as the key for client) Note: hash doesnot release system RNG output - sha3_256(buf, buf, 32); + sha3_256(buf, buf, 32); // BUF[0:31] <-- random message (will be used as the key for client) Note: hash doesnot release system RNG output - // BUF[32:63] <-- Hash(public key); Multitarget countermeasure for coins + contributory KEM - sha3_256(buf + 32, pk, SABER_INDCPA_PUBLICKEYBYTES); - - // kr[0:63] <-- Hash(buf[0:63]); - sha3_512(kr, buf, 64); + sha3_256(buf + 32, pk, SABER_INDCPA_PUBLICKEYBYTES); // BUF[32:63] <-- Hash(public key); Multitarget countermeasure for coins + contributory KEM + sha3_512(kr, buf, 64); // kr[0:63] <-- Hash(buf[0:63]); // K^ <-- kr[0:31] // noiseseed (r) <-- kr[32:63]; - // buf[0:31] contains message; kr[32:63] contains randomness r; - PQCLEAN_FIRESABER_CLEAN_indcpa_kem_enc(buf, kr + 32, pk, ct); + PQCLEAN_FIRESABER_CLEAN_indcpa_kem_enc(c, buf, kr + 32, pk); // buf[0:31] contains message; kr[32:63] contains randomness r; - sha3_256(kr + 32, ct, SABER_BYTES_CCA_DEC); + sha3_256(kr + 32, c, SABER_BYTES_CCA_DEC); - // hash concatenation of pre-k and h(c) to k - sha3_256(ss, kr, 64); + sha3_256(k, kr, 64); // hash concatenation of pre-k and h(c) to k return (0); } - -int PQCLEAN_FIRESABER_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) { +int PQCLEAN_FIRESABER_CLEAN_crypto_kem_dec(uint8_t *k, const uint8_t *c, const uint8_t *sk) { int i; - unsigned char fail; - unsigned char cmp[SABER_BYTES_CCA_DEC]; - unsigned char buf[64]; - - // Will contain key, coins - unsigned char kr[64]; - const unsigned char *pk = sk + SABER_INDCPA_SECRETKEYBYTES; - - // buf[0:31] <-- message - PQCLEAN_FIRESABER_CLEAN_indcpa_kem_dec(sk, ct, buf); + uint8_t fail; + uint8_t cmp[SABER_BYTES_CCA_DEC]; + uint8_t buf[64]; + uint8_t kr[64]; // Will contain key, coins + const uint8_t *pk = sk + SABER_INDCPA_SECRETKEYBYTES; + PQCLEAN_FIRESABER_CLEAN_indcpa_kem_dec(buf, sk, c); // buf[0:31] <-- message // Multitarget countermeasure for coins + contributory KEM - // Save hash by storing h(pk) in sk - for (i = 0; i < 32; i++) { + for (i = 0; i < 32; i++) { // Save hash by storing h(pk) in sk buf[32 + i] = sk[SABER_SECRETKEYBYTES - 64 + i]; } sha3_512(kr, buf, 64); - PQCLEAN_FIRESABER_CLEAN_indcpa_kem_enc(buf, kr + 32, pk, cmp); + PQCLEAN_FIRESABER_CLEAN_indcpa_kem_enc(cmp, buf, kr + 32, pk); + fail = PQCLEAN_FIRESABER_CLEAN_verify(c, cmp, SABER_BYTES_CCA_DEC); - fail = PQCLEAN_FIRESABER_CLEAN_verify(ct, cmp, SABER_BYTES_CCA_DEC); - - // overwrite coins in kr with h(c) - sha3_256(kr + 32, ct, SABER_BYTES_CCA_DEC); + sha3_256(kr + 32, c, SABER_BYTES_CCA_DEC); // overwrite coins in kr with h(c) PQCLEAN_FIRESABER_CLEAN_cmov(kr, sk + SABER_SECRETKEYBYTES - SABER_KEYBYTES, SABER_KEYBYTES, fail); - // hash concatenation of pre-k and h(c) to k - sha3_256(ss, kr, 64); + sha3_256(k, kr, 64); // hash concatenation of pre-k and h(c) to k return (0); } diff --git a/crypto_kem/firesaber/clean/pack_unpack.c b/crypto_kem/firesaber/clean/pack_unpack.c index 9e68ffc1..0add1409 100644 --- a/crypto_kem/firesaber/clean/pack_unpack.c +++ b/crypto_kem/firesaber/clean/pack_unpack.c @@ -1,254 +1,136 @@ +#include "api.h" #include "pack_unpack.h" +#include -void PQCLEAN_FIRESABER_CLEAN_pack_3bit(uint8_t *bytes, const uint16_t *data) { - uint32_t j; - uint32_t offset_data, offset_byte; - - for (j = 0; j < SABER_N / 8; j++) { - offset_byte = 3 * j; - offset_data = 8 * j; - bytes[offset_byte + 0] = (data[offset_data + 0] & 0x7) | - ((data[offset_data + 1] & 0x7) << 3) | - ((data[offset_data + 2] & 0x3) << 6); - bytes[offset_byte + 1] = ((data[offset_data + 2] >> 2 ) & 0x01) | - ((data[offset_data + 3] & 0x7) << 1) | - ((data[offset_data + 4] & 0x7) << 4) | - (((data[offset_data + 5]) & 0x01) << 7); - bytes[offset_byte + 2] = ((data[offset_data + 5] >> 1 ) & 0x03) | - ((data[offset_data + 6] & 0x7) << 2) | - ((data[offset_data + 7] & 0x7) << 5); - } -} - -void PQCLEAN_FIRESABER_CLEAN_un_pack3bit(const uint8_t *bytes, uint16_t *data) { - uint32_t j; - uint32_t offset_data, offset_byte; - - for (j = 0; j < SABER_N / 8; j++) { - offset_byte = 3 * j; - offset_data = 8 * j; - data[offset_data + 0] = (bytes[offset_byte + 0]) & 0x07; - data[offset_data + 1] = ((bytes[offset_byte + 0]) >> 3 ) & 0x07; - data[offset_data + 2] = (((bytes[offset_byte + 0]) >> 6 ) & 0x03) | - (((bytes[offset_byte + 1]) & 0x01) << 2); - data[offset_data + 3] = ((bytes[offset_byte + 1]) >> 1 ) & 0x07; - data[offset_data + 4] = ((bytes[offset_byte + 1]) >> 4 ) & 0x07; - data[offset_data + 5] = (((bytes[offset_byte + 1]) >> 7 ) & 0x01) | - (((bytes[offset_byte + 2]) & 0x03) << 1); - data[offset_data + 6] = ((bytes[offset_byte + 2] >> 2) & 0x07); - data[offset_data + 7] = ((bytes[offset_byte + 2] >> 5) & 0x07); - } -} - -void PQCLEAN_FIRESABER_CLEAN_pack_4bit(uint8_t *bytes, const uint16_t *data) { - uint32_t j; - uint32_t offset_data; - - for (j = 0; j < SABER_N / 2; j++) { - offset_data = 2 * j; - bytes[j] = (data[offset_data] & 0x0f) | - ((data[offset_data + 1] & 0x0f) << 4); - } -} - -void PQCLEAN_FIRESABER_CLEAN_un_pack4bit(const unsigned char *bytes, uint16_t *ar) { - uint32_t j; - uint32_t offset_data; - - for (j = 0; j < SABER_N / 2; j++) { - offset_data = 2 * j; - ar[offset_data] = bytes[j] & 0x0f; - ar[offset_data + 1] = (bytes[j] >> 4) & 0x0f; - } -} - -void PQCLEAN_FIRESABER_CLEAN_pack_6bit(uint8_t *bytes, const uint16_t *data) { - uint32_t j; - uint32_t offset_data, offset_byte; - +void PQCLEAN_FIRESABER_CLEAN_POLT2BS(uint8_t bytes[SABER_SCALEBYTES_KEM], const uint16_t data[SABER_N]) { + size_t j, offset_byte, offset_data; for (j = 0; j < SABER_N / 4; j++) { offset_byte = 3 * j; offset_data = 4 * j; - bytes[offset_byte + 0] = (data[offset_data + 0] & 0x3f) | - ((data[offset_data + 1] & 0x03) << 6); - bytes[offset_byte + 1] = ((data[offset_data + 1] >> 2) & 0x0f) | - ((data[offset_data + 2] & 0x0f) << 4); - bytes[offset_byte + 2] = ((data[offset_data + 2] >> 4) & 0x03) | - ((data[offset_data + 3] & 0x3f) << 2); + bytes[offset_byte + 0] = (data[offset_data + 0] & 0x3f) | ((data[offset_data + 1] & 0x03) << 6); + bytes[offset_byte + 1] = ((data[offset_data + 1] >> 2) & 0x0f) | ((data[offset_data + 2] & 0x0f) << 4); + bytes[offset_byte + 2] = ((data[offset_data + 2] >> 4) & 0x03) | ((data[offset_data + 3] & 0x3f) << 2); } } - -void PQCLEAN_FIRESABER_CLEAN_un_pack6bit(const unsigned char *bytes, uint16_t *data) { - uint32_t j; - uint32_t offset_data, offset_byte; - +void PQCLEAN_FIRESABER_CLEAN_BS2POLT(uint16_t data[SABER_N], const uint8_t bytes[SABER_SCALEBYTES_KEM]) { + size_t j, offset_byte, offset_data; for (j = 0; j < SABER_N / 4; j++) { offset_byte = 3 * j; offset_data = 4 * j; data[offset_data + 0] = bytes[offset_byte + 0] & 0x3f; - data[offset_data + 1] = ((bytes[offset_byte + 0] >> 6) & 0x03) | - ((bytes[offset_byte + 1] & 0x0f) << 2); - data[offset_data + 2] = ((bytes[offset_byte + 1] & 0xff) >> 4) | - ((bytes[offset_byte + 2] & 0x03) << 4); + data[offset_data + 1] = ((bytes[offset_byte + 0] >> 6) & 0x03) | ((bytes[offset_byte + 1] & 0x0f) << 2); + data[offset_data + 2] = ((bytes[offset_byte + 1] & 0xff) >> 4) | ((bytes[offset_byte + 2] & 0x03) << 4); data[offset_data + 3] = ((bytes[offset_byte + 2] & 0xff) >> 2); } } - -static void POLVECp2BS(uint8_t *bytes, uint16_t data[SABER_K][SABER_N]) { - uint32_t i, j; - uint32_t offset_data, offset_byte, offset_byte1; - - for (i = 0; i < SABER_K; i++) { - offset_byte1 = i * (SABER_N * 10) / 8; - for (j = 0; j < SABER_N / 4; j++) { - offset_byte = offset_byte1 + 5 * j; - offset_data = 4 * j; - bytes[offset_byte + 0] = (data[i][offset_data + 0] & (0xff)); - bytes[offset_byte + 1] = ((data[i][offset_data + 0] >> 8) & 0x03) | - ((data[i][offset_data + 1] & 0x3f) << 2); - bytes[offset_byte + 2] = ((data[i][offset_data + 1] >> 6) & 0x0f) | - ((data[i][offset_data + 2] & 0x0f) << 4); - bytes[offset_byte + 3] = ((data[i][offset_data + 2] >> 4) & 0x3f) | - ((data[i][offset_data + 3] & 0x03) << 6); - bytes[offset_byte + 4] = ((data[i][offset_data + 3] >> 2) & 0xff); - } - } -} - -static void BS2POLVECp(const unsigned char *bytes, uint16_t data[SABER_K][SABER_N]) { - uint32_t i, j; - uint32_t offset_data, offset_byte, offset_byte1; - - for (i = 0; i < SABER_K; i++) { - offset_byte1 = i * (SABER_N * 10) / 8; - for (j = 0; j < SABER_N / 4; j++) { - offset_byte = offset_byte1 + 5 * j; - offset_data = 4 * j; - data[i][offset_data + 0] = (bytes[offset_byte + 0] & (0xff)) | - ((bytes[offset_byte + 1] & 0x03) << 8); - data[i][offset_data + 1] = ((bytes[offset_byte + 1] >> 2) & (0x3f)) | - ((bytes[offset_byte + 2] & 0x0f) << 6); - data[i][offset_data + 2] = ((bytes[offset_byte + 2] >> 4) & (0x0f)) | - ((bytes[offset_byte + 3] & 0x3f) << 4); - data[i][offset_data + 3] = ((bytes[offset_byte + 3] >> 6) & (0x03)) | - ((bytes[offset_byte + 4] & 0xff) << 2); - } - } -} - - - -static void POLVECq2BS(uint8_t *bytes, uint16_t data[SABER_K][SABER_N]) { - uint32_t i, j; - uint32_t offset_data, offset_byte, offset_byte1; - - for (i = 0; i < SABER_K; i++) { - offset_byte1 = i * (SABER_N * 13) / 8; - for (j = 0; j < SABER_N / 8; j++) { - offset_byte = offset_byte1 + 13 * j; - offset_data = 8 * j; - bytes[offset_byte + 0] = (data[i][offset_data + 0] & (0xff)); - bytes[offset_byte + 1] = ((data[i][offset_data + 0] >> 8) & 0x1f) | - ((data[i][offset_data + 1] & 0x07) << 5); - bytes[offset_byte + 2] = ((data[i][offset_data + 1] >> 3) & 0xff); - bytes[offset_byte + 3] = ((data[i][offset_data + 1] >> 11) & 0x03) | - ((data[i][offset_data + 2] & 0x3f) << 2); - bytes[offset_byte + 4] = ((data[i][offset_data + 2] >> 6) & 0x7f) | - ((data[i][offset_data + 3] & 0x01) << 7); - bytes[offset_byte + 5] = ((data[i][offset_data + 3] >> 1) & 0xff); - bytes[offset_byte + 6] = ((data[i][offset_data + 3] >> 9) & 0x0f) | - ((data[i][offset_data + 4] & 0x0f) << 4); - bytes[offset_byte + 7] = ((data[i][offset_data + 4] >> 4) & 0xff); - bytes[offset_byte + 8] = ((data[i][offset_data + 4] >> 12) & 0x01) | - ((data[i][offset_data + 5] & 0x7f) << 1); - bytes[offset_byte + 9] = ((data[i][offset_data + 5] >> 7) & 0x3f) | - ((data[i][offset_data + 6] & 0x03) << 6); - bytes[offset_byte + 10] = ((data[i][offset_data + 6] >> 2) & 0xff); - bytes[offset_byte + 11] = ((data[i][offset_data + 6] >> 10) & 0x07) | - ((data[i][offset_data + 7] & 0x1f) << 3); - bytes[offset_byte + 12] = ((data[i][offset_data + 7] >> 5) & 0xff); - } - } -} - -static void BS2POLVECq(const unsigned char *bytes, uint16_t data[SABER_K][SABER_N]) { - uint32_t i, j; - uint32_t offset_data, offset_byte, offset_byte1; - - for (i = 0; i < SABER_K; i++) { - offset_byte1 = i * (SABER_N * 13) / 8; - for (j = 0; j < SABER_N / 8; j++) { - offset_byte = offset_byte1 + 13 * j; - offset_data = 8 * j; - data[i][offset_data + 0] = (bytes[offset_byte + 0] & (0xff)) | - ((bytes[offset_byte + 1] & 0x1f) << 8); - data[i][offset_data + 1] = (bytes[offset_byte + 1] >> 5 & (0x07)) | - ((bytes[offset_byte + 2] & 0xff) << 3) | - ((bytes[offset_byte + 3] & 0x03) << 11); - data[i][offset_data + 2] = (bytes[offset_byte + 3] >> 2 & (0x3f)) | - ((bytes[offset_byte + 4] & 0x7f) << 6); - data[i][offset_data + 3] = (bytes[offset_byte + 4] >> 7 & (0x01)) | - ((bytes[offset_byte + 5] & 0xff) << 1) | - ((bytes[offset_byte + 6] & 0x0f) << 9); - data[i][offset_data + 4] = (bytes[offset_byte + 6] >> 4 & (0x0f)) | - ((bytes[offset_byte + 7] & 0xff) << 4) | - ((bytes[offset_byte + 8] & 0x01) << 12); - data[i][offset_data + 5] = (bytes[offset_byte + 8] >> 1 & (0x7f)) | - ((bytes[offset_byte + 9] & 0x3f) << 7); - data[i][offset_data + 6] = (bytes[offset_byte + 9] >> 6 & (0x03)) | - ((bytes[offset_byte + 10] & 0xff) << 2) | - ((bytes[offset_byte + 11] & 0x07) << 10); - data[i][offset_data + 7] = (bytes[offset_byte + 11] >> 3 & (0x1f)) | - ((bytes[offset_byte + 12] & 0xff) << 5); - } - } -} - -//only BS2POLq no BS2POLp -void PQCLEAN_FIRESABER_CLEAN_BS2POL(const unsigned char *bytes, uint16_t data[SABER_N]) { - uint32_t j; - uint32_t offset_data, offset_byte; - +static void POLq2BS(uint8_t bytes[SABER_POLYBYTES], const uint16_t data[SABER_N]) { + size_t j, offset_byte, offset_data; for (j = 0; j < SABER_N / 8; j++) { offset_byte = 13 * j; offset_data = 8 * j; - data[offset_data + 0] = (bytes[offset_byte + 0] & (0xff)) | - ((bytes[offset_byte + 1] & 0x1f) << 8); - data[offset_data + 1] = (bytes[offset_byte + 1] >> 5 & (0x07)) | - ((bytes[offset_byte + 2] & 0xff) << 3) | - ((bytes[offset_byte + 3] & 0x03) << 11); - data[offset_data + 2] = (bytes[offset_byte + 3] >> 2 & (0x3f)) | - ((bytes[offset_byte + 4] & 0x7f) << 6); - data[offset_data + 3] = (bytes[offset_byte + 4] >> 7 & (0x01)) | - ((bytes[offset_byte + 5] & 0xff) << 1) | - ((bytes[offset_byte + 6] & 0x0f) << 9); - data[offset_data + 4] = (bytes[offset_byte + 6] >> 4 & (0x0f)) | - ((bytes[offset_byte + 7] & 0xff) << 4) | - ((bytes[offset_byte + 8] & 0x01) << 12); - data[offset_data + 5] = (bytes[offset_byte + 8] >> 1 & (0x7f)) | - ((bytes[offset_byte + 9] & 0x3f) << 7); - data[offset_data + 6] = (bytes[offset_byte + 9] >> 6 & (0x03)) | - ((bytes[offset_byte + 10] & 0xff) << 2) | - ((bytes[offset_byte + 11] & 0x07) << 10); - data[offset_data + 7] = (bytes[offset_byte + 11] >> 3 & (0x1f)) | - ((bytes[offset_byte + 12] & 0xff) << 5); + bytes[offset_byte + 0] = (data[offset_data + 0] & (0xff)); + bytes[offset_byte + 1] = ((data[offset_data + 0] >> 8) & 0x1f) | ((data[offset_data + 1] & 0x07) << 5); + bytes[offset_byte + 2] = ((data[offset_data + 1] >> 3) & 0xff); + bytes[offset_byte + 3] = ((data[offset_data + 1] >> 11) & 0x03) | ((data[offset_data + 2] & 0x3f) << 2); + bytes[offset_byte + 4] = ((data[offset_data + 2] >> 6) & 0x7f) | ((data[offset_data + 3] & 0x01) << 7); + bytes[offset_byte + 5] = ((data[offset_data + 3] >> 1) & 0xff); + bytes[offset_byte + 6] = ((data[offset_data + 3] >> 9) & 0x0f) | ((data[offset_data + 4] & 0x0f) << 4); + bytes[offset_byte + 7] = ((data[offset_data + 4] >> 4) & 0xff); + bytes[offset_byte + 8] = ((data[offset_data + 4] >> 12) & 0x01) | ((data[offset_data + 5] & 0x7f) << 1); + bytes[offset_byte + 9] = ((data[offset_data + 5] >> 7) & 0x3f) | ((data[offset_data + 6] & 0x03) << 6); + bytes[offset_byte + 10] = ((data[offset_data + 6] >> 2) & 0xff); + bytes[offset_byte + 11] = ((data[offset_data + 6] >> 10) & 0x07) | ((data[offset_data + 7] & 0x1f) << 3); + bytes[offset_byte + 12] = ((data[offset_data + 7] >> 5) & 0xff); } } -void PQCLEAN_FIRESABER_CLEAN_POLVEC2BS(uint8_t *bytes, uint16_t data[SABER_K][SABER_N], uint16_t modulus) { - if (modulus == 1024) { - POLVECp2BS(bytes, data); - } else if (modulus == 8192) { - POLVECq2BS(bytes, data); +static void BS2POLq(uint16_t data[SABER_N], const uint8_t bytes[SABER_POLYBYTES]) { + size_t j, offset_byte, offset_data; + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = 13 * j; + offset_data = 8 * j; + data[offset_data + 0] = (bytes[offset_byte + 0] & (0xff)) | ((bytes[offset_byte + 1] & 0x1f) << 8); + data[offset_data + 1] = (bytes[offset_byte + 1] >> 5 & (0x07)) | ((bytes[offset_byte + 2] & 0xff) << 3) | ((bytes[offset_byte + 3] & 0x03) << 11); + data[offset_data + 2] = (bytes[offset_byte + 3] >> 2 & (0x3f)) | ((bytes[offset_byte + 4] & 0x7f) << 6); + data[offset_data + 3] = (bytes[offset_byte + 4] >> 7 & (0x01)) | ((bytes[offset_byte + 5] & 0xff) << 1) | ((bytes[offset_byte + 6] & 0x0f) << 9); + data[offset_data + 4] = (bytes[offset_byte + 6] >> 4 & (0x0f)) | ((bytes[offset_byte + 7] & 0xff) << 4) | ((bytes[offset_byte + 8] & 0x01) << 12); + data[offset_data + 5] = (bytes[offset_byte + 8] >> 1 & (0x7f)) | ((bytes[offset_byte + 9] & 0x3f) << 7); + data[offset_data + 6] = (bytes[offset_byte + 9] >> 6 & (0x03)) | ((bytes[offset_byte + 10] & 0xff) << 2) | ((bytes[offset_byte + 11] & 0x07) << 10); + data[offset_data + 7] = (bytes[offset_byte + 11] >> 3 & (0x1f)) | ((bytes[offset_byte + 12] & 0xff) << 5); } } -void PQCLEAN_FIRESABER_CLEAN_BS2POLVEC(const unsigned char *bytes, uint16_t data[SABER_K][SABER_N], uint16_t modulus) { - if (modulus == 1024) { - BS2POLVECp(bytes, data); - } else if (modulus == 8192) { - BS2POLVECq(bytes, data); +static void POLp2BS(uint8_t bytes[SABER_POLYCOMPRESSEDBYTES], const uint16_t data[SABER_N]) { + size_t j, offset_byte, offset_data; + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = 5 * j; + offset_data = 4 * j; + bytes[offset_byte + 0] = (data[offset_data + 0] & (0xff)); + bytes[offset_byte + 1] = ((data[offset_data + 0] >> 8) & 0x03) | ((data[offset_data + 1] & 0x3f) << 2); + bytes[offset_byte + 2] = ((data[offset_data + 1] >> 6) & 0x0f) | ((data[offset_data + 2] & 0x0f) << 4); + bytes[offset_byte + 3] = ((data[offset_data + 2] >> 4) & 0x3f) | ((data[offset_data + 3] & 0x03) << 6); + bytes[offset_byte + 4] = ((data[offset_data + 3] >> 2) & 0xff); + } +} + +static void BS2POLp(uint16_t data[SABER_N], const uint8_t bytes[SABER_POLYCOMPRESSEDBYTES]) { + size_t j, offset_byte, offset_data; + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = 5 * j; + offset_data = 4 * j; + data[offset_data + 0] = (bytes[offset_byte + 0] & (0xff)) | ((bytes[offset_byte + 1] & 0x03) << 8); + data[offset_data + 1] = ((bytes[offset_byte + 1] >> 2) & (0x3f)) | ((bytes[offset_byte + 2] & 0x0f) << 6); + data[offset_data + 2] = ((bytes[offset_byte + 2] >> 4) & (0x0f)) | ((bytes[offset_byte + 3] & 0x3f) << 4); + data[offset_data + 3] = ((bytes[offset_byte + 3] >> 6) & (0x03)) | ((bytes[offset_byte + 4] & 0xff) << 2); + } +} + +void PQCLEAN_FIRESABER_CLEAN_POLVECq2BS(uint8_t bytes[SABER_POLYVECBYTES], const uint16_t data[SABER_L][SABER_N]) { + size_t i; + for (i = 0; i < SABER_L; i++) { + POLq2BS(bytes + i * SABER_POLYBYTES, data[i]); + } +} + +void PQCLEAN_FIRESABER_CLEAN_BS2POLVECq(uint16_t data[SABER_L][SABER_N], const uint8_t bytes[SABER_POLYVECBYTES]) { + size_t i; + for (i = 0; i < SABER_L; i++) { + BS2POLq(data[i], bytes + i * SABER_POLYBYTES); + } +} + +void PQCLEAN_FIRESABER_CLEAN_POLVECp2BS(uint8_t bytes[SABER_POLYVECCOMPRESSEDBYTES], const uint16_t data[SABER_L][SABER_N]) { + size_t i; + for (i = 0; i < SABER_L; i++) { + POLp2BS(bytes + i * (SABER_EP * SABER_N / 8), data[i]); + } +} + +void PQCLEAN_FIRESABER_CLEAN_BS2POLVECp(uint16_t data[SABER_L][SABER_N], const uint8_t bytes[SABER_POLYVECCOMPRESSEDBYTES]) { + size_t i; + for (i = 0; i < SABER_L; i++) { + BS2POLp(data[i], bytes + i * (SABER_EP * SABER_N / 8)); + } +} + +void PQCLEAN_FIRESABER_CLEAN_BS2POLmsg(uint16_t data[SABER_N], const uint8_t bytes[SABER_KEYBYTES]) { + size_t i, j; + for (j = 0; j < SABER_KEYBYTES; j++) { + for (i = 0; i < 8; i++) { + data[j * 8 + i] = ((bytes[j] >> i) & 0x01); + } + } +} + +void PQCLEAN_FIRESABER_CLEAN_POLmsg2BS(uint8_t bytes[SABER_KEYBYTES], const uint16_t data[SABER_N]) { + size_t i, j; + memset(bytes, 0, SABER_KEYBYTES); + + for (j = 0; j < SABER_KEYBYTES; j++) { + for (i = 0; i < 8; i++) { + bytes[j] = bytes[j] | ((data[j * 8 + i] & 0x01) << i); + } } } diff --git a/crypto_kem/firesaber/clean/pack_unpack.h b/crypto_kem/firesaber/clean/pack_unpack.h index 6509f107..0a8ee253 100644 --- a/crypto_kem/firesaber/clean/pack_unpack.h +++ b/crypto_kem/firesaber/clean/pack_unpack.h @@ -1,28 +1,27 @@ #ifndef PACK_UNPACK_H #define PACK_UNPACK_H - #include "SABER_params.h" #include #include +void PQCLEAN_FIRESABER_CLEAN_POLT2BS(uint8_t bytes[SABER_SCALEBYTES_KEM], const uint16_t data[SABER_N]); -void PQCLEAN_FIRESABER_CLEAN_pack_3bit(uint8_t *bytes, const uint16_t *data); - -void PQCLEAN_FIRESABER_CLEAN_un_pack3bit(const uint8_t *bytes, uint16_t *data); - -void PQCLEAN_FIRESABER_CLEAN_pack_4bit(uint8_t *bytes, const uint16_t *data); - -void PQCLEAN_FIRESABER_CLEAN_un_pack4bit(const unsigned char *bytes, uint16_t *ar); - -void PQCLEAN_FIRESABER_CLEAN_pack_6bit(uint8_t *bytes, const uint16_t *data); - -void PQCLEAN_FIRESABER_CLEAN_un_pack6bit(const unsigned char *bytes, uint16_t *data); +void PQCLEAN_FIRESABER_CLEAN_BS2POLT(uint16_t data[SABER_N], const uint8_t bytes[SABER_SCALEBYTES_KEM]); -void PQCLEAN_FIRESABER_CLEAN_BS2POL(const unsigned char *bytes, uint16_t data[SABER_N]); +void PQCLEAN_FIRESABER_CLEAN_POLVECq2BS(uint8_t bytes[SABER_POLYVECBYTES], const uint16_t data[SABER_L][SABER_N]); -void PQCLEAN_FIRESABER_CLEAN_POLVEC2BS(uint8_t *bytes, uint16_t data[SABER_K][SABER_N], uint16_t modulus); +void PQCLEAN_FIRESABER_CLEAN_POLVECp2BS(uint8_t bytes[SABER_POLYVECCOMPRESSEDBYTES], const uint16_t data[SABER_L][SABER_N]); + + +void PQCLEAN_FIRESABER_CLEAN_BS2POLVECq(uint16_t data[SABER_L][SABER_N], const uint8_t bytes[SABER_POLYVECBYTES]); + +void PQCLEAN_FIRESABER_CLEAN_BS2POLVECp(uint16_t data[SABER_L][SABER_N], const uint8_t bytes[SABER_POLYVECCOMPRESSEDBYTES]); + + +void PQCLEAN_FIRESABER_CLEAN_BS2POLmsg(uint16_t data[SABER_N], const uint8_t bytes[SABER_KEYBYTES]); + +void PQCLEAN_FIRESABER_CLEAN_POLmsg2BS(uint8_t bytes[SABER_KEYBYTES], const uint16_t data[SABER_N]); -void PQCLEAN_FIRESABER_CLEAN_BS2POLVEC(const unsigned char *bytes, uint16_t data[SABER_K][SABER_N], uint16_t modulus); #endif diff --git a/crypto_kem/firesaber/clean/poly.c b/crypto_kem/firesaber/clean/poly.c index 6fef45d5..c65175fe 100644 --- a/crypto_kem/firesaber/clean/poly.c +++ b/crypto_kem/firesaber/clean/poly.c @@ -1,21 +1,49 @@ -/*--------------------------------------------------------------------- -This file has been adapted from the implementation -(available at, Public Domain https://github.com/pq-crystals/kyber) -of "CRYSTALS – Kyber: a CCA-secure module-lattice-based KEM" -by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint, -Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle -----------------------------------------------------------------------*/ -#include "SABER_params.h" +#include "api.h" #include "cbd.h" #include "fips202.h" +#include "pack_unpack.h" #include "poly.h" +#include "poly_mul.h" +#include -void PQCLEAN_FIRESABER_CLEAN_GenSecret(uint16_t r[SABER_K][SABER_N], const unsigned char *seed) { - uint8_t buf[SABER_MU * SABER_N * SABER_K / 8]; - - shake128(buf, sizeof(buf), seed, SABER_NOISESEEDBYTES); - - for (size_t i = 0; i < SABER_K; i++) { - PQCLEAN_FIRESABER_CLEAN_cbd(r[i], buf + i * SABER_MU * SABER_N / 8); +void PQCLEAN_FIRESABER_CLEAN_MatrixVectorMul(uint16_t res[SABER_L][SABER_N], const uint16_t A[SABER_L][SABER_L][SABER_N], const uint16_t s[SABER_L][SABER_N], int16_t transpose) { + int i, j; + for (i = 0; i < SABER_L; i++) { + for (j = 0; j < SABER_L; j++) { + if (transpose == 1) { + PQCLEAN_FIRESABER_CLEAN_poly_mul_acc(A[j][i], s[j], res[i]); + } else { + PQCLEAN_FIRESABER_CLEAN_poly_mul_acc(A[i][j], s[j], res[i]); + } + } + } +} + +void PQCLEAN_FIRESABER_CLEAN_InnerProd(uint16_t res[SABER_N], const uint16_t b[SABER_L][SABER_N], const uint16_t s[SABER_L][SABER_N]) { + int j; + for (j = 0; j < SABER_L; j++) { + PQCLEAN_FIRESABER_CLEAN_poly_mul_acc(b[j], s[j], res); + } +} + +void PQCLEAN_FIRESABER_CLEAN_GenMatrix(uint16_t A[SABER_L][SABER_L][SABER_N], const uint8_t seed[SABER_SEEDBYTES]) { + uint8_t buf[SABER_L * SABER_POLYVECBYTES]; + int i; + + shake128(buf, sizeof(buf), seed, SABER_SEEDBYTES); + + for (i = 0; i < SABER_L; i++) { + PQCLEAN_FIRESABER_CLEAN_BS2POLVECq(A[i], buf + i * SABER_POLYVECBYTES); + } +} + +void PQCLEAN_FIRESABER_CLEAN_GenSecret(uint16_t s[SABER_L][SABER_N], const uint8_t seed[SABER_NOISE_SEEDBYTES]) { + uint8_t buf[SABER_L * SABER_POLYCOINBYTES]; + size_t i; + + shake128(buf, sizeof(buf), seed, SABER_NOISE_SEEDBYTES); + + for (i = 0; i < SABER_L; i++) { + PQCLEAN_FIRESABER_CLEAN_cbd(s[i], buf + i * SABER_POLYCOINBYTES); } } diff --git a/crypto_kem/firesaber/clean/poly.h b/crypto_kem/firesaber/clean/poly.h index 4f69a068..044e4eec 100644 --- a/crypto_kem/firesaber/clean/poly.h +++ b/crypto_kem/firesaber/clean/poly.h @@ -1,26 +1,15 @@ #ifndef POLY_H #define POLY_H - -/*--------------------------------------------------------------------- -This file has been adapted from the implementation -(available at, Public Domain https://github.com/pq-crystals/kyber) -of "CRYSTALS – Kyber: a CCA-secure module-lattice-based KEM" -by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint, -Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle -----------------------------------------------------------------------*/ - - #include "SABER_params.h" #include -typedef struct { - uint16_t coeffs[SABER_N]; -} poly; +void PQCLEAN_FIRESABER_CLEAN_MatrixVectorMul(uint16_t res[SABER_L][SABER_N], const uint16_t a[SABER_L][SABER_L][SABER_N], const uint16_t s[SABER_L][SABER_N], int16_t transpose); -typedef struct { - poly vec[SABER_K]; -} polyvec; +void PQCLEAN_FIRESABER_CLEAN_InnerProd(uint16_t res[SABER_N], const uint16_t b[SABER_L][SABER_N], const uint16_t s[SABER_L][SABER_N]); + +void PQCLEAN_FIRESABER_CLEAN_GenMatrix(uint16_t a[SABER_L][SABER_L][SABER_N], const uint8_t seed[SABER_SEEDBYTES]); + +void PQCLEAN_FIRESABER_CLEAN_GenSecret(uint16_t s[SABER_L][SABER_N], const uint8_t seed[SABER_NOISE_SEEDBYTES]); -void PQCLEAN_FIRESABER_CLEAN_GenSecret(uint16_t r[SABER_K][SABER_N], const unsigned char *seed); #endif diff --git a/crypto_kem/firesaber/clean/poly_mul.c b/crypto_kem/firesaber/clean/poly_mul.c index 20f1d4ad..27c92f29 100644 --- a/crypto_kem/firesaber/clean/poly_mul.c +++ b/crypto_kem/firesaber/clean/poly_mul.c @@ -228,19 +228,15 @@ static void toom_cook_4way (const uint16_t *a1, const uint16_t *b1, uint16_t *re } } -void PQCLEAN_FIRESABER_CLEAN_pol_mul(uint16_t *a, uint16_t *b, uint16_t *res, uint16_t p, uint32_t n) { - uint32_t i; - // normal multiplication - uint16_t c[512]; - - for (i = 0; i < 512; i++) { - c[i] = 0; - } +/* res += a*b */ +void PQCLEAN_FIRESABER_CLEAN_poly_mul_acc(const uint16_t a[SABER_N], const uint16_t b[SABER_N], uint16_t res[SABER_N]) { + uint16_t c[2 * SABER_N] = {0}; + int i; toom_cook_4way(a, b, c); - // reduction - for (i = n; i < 2 * n; i++) { - res[i - n] = (c[i - n] - c[i]) & (p - 1); + /* reduction */ + for (i = SABER_N; i < 2 * SABER_N; i++) { + res[i - SABER_N] += (c[i - SABER_N] - c[i]); } } diff --git a/crypto_kem/firesaber/clean/poly_mul.h b/crypto_kem/firesaber/clean/poly_mul.h index 4d960042..e554d60c 100644 --- a/crypto_kem/firesaber/clean/poly_mul.h +++ b/crypto_kem/firesaber/clean/poly_mul.h @@ -1,9 +1,9 @@ -#ifndef POLYMUL_H -#define POLYMUL_H - +#ifndef POLY_MUL_H +#define POLY_MUL_H #include "SABER_params.h" #include -void PQCLEAN_FIRESABER_CLEAN_pol_mul(uint16_t *a, uint16_t *b, uint16_t *res, uint16_t p, uint32_t n); +void PQCLEAN_FIRESABER_CLEAN_poly_mul_acc(const uint16_t a[SABER_N], const uint16_t b[SABER_N], uint16_t res[SABER_N]); + #endif diff --git a/crypto_kem/firesaber/clean/verify.c b/crypto_kem/firesaber/clean/verify.c index 3c571e92..97a302a9 100644 --- a/crypto_kem/firesaber/clean/verify.c +++ b/crypto_kem/firesaber/clean/verify.c @@ -1,3 +1,5 @@ +#include "verify.h" + /*------------------------------------------------- This file has been adapted from the implementation (available at https://github.com/pq-crystals/kyber) of @@ -5,26 +7,25 @@ This file has been adapted from the implementation by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint, Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle ----------------------------------------------------*/ -#include "verify.h" -#include + /* returns 0 for equal strings, 1 for non-equal strings */ -unsigned char PQCLEAN_FIRESABER_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len) { +uint8_t PQCLEAN_FIRESABER_CLEAN_verify(const uint8_t *a, const uint8_t *b, size_t len) { uint64_t r; size_t i; - r = 0; + for (i = 0; i < len; i++) { r |= a[i] ^ b[i]; } r = (~r + 1); // Two's complement r >>= 63; - return (unsigned char)r; + return (uint8_t) r; } /* b = 1 means mov, b = 0 means don't mov*/ -void PQCLEAN_FIRESABER_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b) { +void PQCLEAN_FIRESABER_CLEAN_cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b) { size_t i; b = -b; diff --git a/crypto_kem/firesaber/clean/verify.h b/crypto_kem/firesaber/clean/verify.h index 1b69b071..1d5e4cb9 100644 --- a/crypto_kem/firesaber/clean/verify.h +++ b/crypto_kem/firesaber/clean/verify.h @@ -1,6 +1,5 @@ #ifndef VERIFY_H #define VERIFY_H - /*------------------------------------------------- This file has been adapted from the implementation (available at https://github.com/pq-crystals/kyber) of @@ -13,9 +12,11 @@ Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle #include /* returns 0 for equal strings, 1 for non-equal strings */ -unsigned char PQCLEAN_FIRESABER_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len); +uint8_t PQCLEAN_FIRESABER_CLEAN_verify(const uint8_t *a, const uint8_t *b, size_t len); + /* b = 1 means mov, b = 0 means don't mov*/ -void PQCLEAN_FIRESABER_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b); +void PQCLEAN_FIRESABER_CLEAN_cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b); + #endif diff --git a/crypto_kem/lightsaber/META.yml b/crypto_kem/lightsaber/META.yml index 1b7912f6..1cc06c9a 100644 --- a/crypto_kem/lightsaber/META.yml +++ b/crypto_kem/lightsaber/META.yml @@ -14,4 +14,13 @@ principal-submitters: - Frederik Vercauteren implementations: - name: clean - version: https://github.com/KULeuven-COSIC/SABER/commit/14ede83f1ff3bcc41f0464543542366c68b55871 + version: https://github.com/KULeuven-COSIC/SABER/commit/509cc5ec3a7e12a751ccdd2ef5bd6e54e00bd350 + - name: avx2 + version: https://github.com/KULeuven-COSIC/SABER/commit/509cc5ec3a7e12a751ccdd2ef5bd6e54e00bd350 + supported_platforms: + - architecture: x86_64 + operating_systems: + - Linux + - Darwin + required_flags: + - avx2 diff --git a/crypto_kem/lightsaber/avx2/LICENSE b/crypto_kem/lightsaber/avx2/LICENSE new file mode 100644 index 00000000..d5d21fff --- /dev/null +++ b/crypto_kem/lightsaber/avx2/LICENSE @@ -0,0 +1 @@ +Public Domain diff --git a/crypto_kem/lightsaber/avx2/Makefile b/crypto_kem/lightsaber/avx2/Makefile new file mode 100644 index 00000000..0522fe8d --- /dev/null +++ b/crypto_kem/lightsaber/avx2/Makefile @@ -0,0 +1,22 @@ +# This Makefile can be used with GNU Make or BSD Make + +LIB=liblightsaber_avx2.a +HEADERS=api.h cbd.h kem.h pack_unpack.h poly.h SABER_indcpa.h SABER_params.h verify.h +OBJECTS=cbd.o kem.o pack_unpack.o SABER_indcpa.o verify.o + +CFLAGS=-O3 -mavx2 -Wall -Wextra -Wpedantic -Wvla -Werror -Wredundant-decls -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) + +all: $(LIB) + +%.o: %.s $(HEADERS) + $(AS) -o $@ $< + +%.o: %.c $(HEADERS) + $(CC) $(CFLAGS) -c -o $@ $< + +$(LIB): $(OBJECTS) + $(AR) -r $@ $(OBJECTS) + +clean: + $(RM) $(OBJECTS) + $(RM) $(LIB) diff --git a/crypto_kem/lightsaber/avx2/SABER_indcpa.c b/crypto_kem/lightsaber/avx2/SABER_indcpa.c new file mode 100644 index 00000000..3270a8c9 --- /dev/null +++ b/crypto_kem/lightsaber/avx2/SABER_indcpa.c @@ -0,0 +1,416 @@ +#include "./polymul/toom-cook_4way.c" +#include "SABER_indcpa.h" +#include "SABER_params.h" +#include "api.h" +#include "cbd.h" +#include "fips202.h" +#include "pack_unpack.h" +#include "randombytes.h" +#include +#include +#include +//#include "randombytes.h" +//#include "./polymul/toom_cook_4/toom-cook_4way.c" + +#define h1 4 //2^(EQ-EP-1) + +#define h2 ( (1<<(SABER_EP-2)) - (1<<(SABER_EP-SABER_ET-1)) + (1<<(SABER_EQ-SABER_EP-1)) ) + + +static void POL2MSG(uint8_t *message_dec, const uint16_t *message_dec_unpacked) { + int32_t i, j; + + for (j = 0; j < SABER_KEYBYTES; j++) { + message_dec[j] = 0; + for (i = 0; i < 8; i++) { + message_dec[j] = message_dec[j] | (message_dec_unpacked[j * 8 + i] << i); + } + } +} + +/*----------------------------------------------------------------------------------- + This routine generates a=[Matrix K x K] of 256-coefficient polynomials +-------------------------------------------------------------------------------------*/ + +static void GenMatrix(polyvec *a, const uint8_t *seed) { + uint8_t buf[SABER_K * SABER_K * 13 * SABER_N / 8]; + + uint16_t temp_ar[SABER_N]; + + int i, j, k; + uint16_t mod = (SABER_Q - 1); + + shake128(buf, sizeof(buf), seed, SABER_SEEDBYTES); + + for (i = 0; i < SABER_K; i++) { + for (j = 0; j < SABER_K; j++) { + PQCLEAN_LIGHTSABER_AVX2_BS2POLq(temp_ar, buf + (i * SABER_K + j) * 13 * SABER_N / 8); + for (k = 0; k < SABER_N; k++) { + a[i].vec[j].coeffs[k] = (temp_ar[k])& mod ; + } + } + } +} + +static void GenSecret(uint16_t r[SABER_K][SABER_N], const uint8_t *seed) { + + uint32_t i; + + uint8_t buf[SABER_MU * SABER_N * SABER_K / 8]; + + shake128(buf, sizeof(buf), seed, SABER_NOISESEEDBYTES); + + for (i = 0; i < SABER_K; i++) { + PQCLEAN_LIGHTSABER_AVX2_cbd(r[i], buf + i * SABER_MU * SABER_N / 8); + } +} + +//********************************matrix-vector mul routines***************************************************** +static void matrix_vector_mul(__m256i a1_avx_combined[NUM_POLY][NUM_POLY][AVX_N1], __m256i b_bucket[NUM_POLY][SCHB_N * 4], __m256i res_avx[NUM_POLY][AVX_N1], int isTranspose) { + int64_t i, j; + + __m256i c_bucket[2 * SCM_SIZE * 4]; //Holds results for 9 Karatsuba at a time + + for (i = 0; i < NUM_POLY; i++) { + for (j = 0; j < NUM_POLY; j++) { + + if (isTranspose == 0) { + toom_cook_4way_avx_n1(a1_avx_combined[i][j], b_bucket[j], c_bucket, j); + } else { + toom_cook_4way_avx_n1(a1_avx_combined[j][i], b_bucket[j], c_bucket, j); + } + } + + TC_interpol(c_bucket, res_avx[i]); + } + +} + +static void vector_vector_mul(__m256i a_avx[NUM_POLY][AVX_N1], __m256i b_bucket[NUM_POLY][SCHB_N * 4], __m256i res_avx[AVX_N1]) { + + int64_t i; + + __m256i c_bucket[2 * SCM_SIZE * 4]; //Holds results for 9 Karatsuba at a time + + for (i = 0; i < NUM_POLY; i++) { + toom_cook_4way_avx_n1(a_avx[i], b_bucket[i], c_bucket, i); + } + TC_interpol(c_bucket, res_avx); +} + +//********************************matrix-vector mul routines***************************************************** + +void PQCLEAN_LIGHTSABER_AVX2_indcpa_kem_keypair(uint8_t *pk, uint8_t *sk) { + + polyvec a[SABER_K]; + + uint16_t skpv1[SABER_K][SABER_N]; + + + + uint8_t seed[SABER_SEEDBYTES]; + uint8_t noiseseed[SABER_COINBYTES]; + int32_t i, j, k; + + +//--------------AVX declaration------------------ + + __m256i sk_avx[SABER_K][SABER_N / 16]; + __m256i mod; + __m256i res_avx[SABER_K][SABER_N / 16]; + __m256i a_avx[SABER_K][SABER_K][SABER_N / 16]; + //__m256i acc[2*SABER_N/16]; + + mod = _mm256_set1_epi16(SABER_Q - 1); + + __m256i b_bucket[NUM_POLY][SCHB_N * 4]; + +//--------------AVX declaration ends------------------ + + randombytes(seed, SABER_SEEDBYTES); + + shake128(seed, SABER_SEEDBYTES, seed, SABER_SEEDBYTES); // for not revealing system RNG state + randombytes(noiseseed, SABER_COINBYTES); + + + GenMatrix(a, seed); //sample matrix A + + GenSecret(skpv1, noiseseed); + + +// Load sk into avx vectors + for (i = 0; i < SABER_K; i++) { + for (j = 0; j < SABER_N / 16; j++) { + sk_avx[i][j] = _mm256_loadu_si256 ((__m256i const *) (&skpv1[i][j * 16])); + } + + } + + // Load a into avx vectors + for (i = 0; i < SABER_K; i++) { + for (j = 0; j < SABER_K; j++) { + for (k = 0; k < SABER_N / 16; k++) { + a_avx[i][j][k] = _mm256_loadu_si256 ((__m256i const *) (&a[i].vec[j].coeffs[k * 16])); + } + } + } + + + + //------------------------do the matrix vector multiplication and rounding------------ + + for (j = 0; j < NUM_POLY; j++) { + TC_eval(sk_avx[j], b_bucket[j]); + } + matrix_vector_mul(a_avx, b_bucket, res_avx, 1);// Matrix-vector multiplication; Matrix in transposed order + + // Now truncation + + + for (i = 0; i < SABER_K; i++) { //shift right EQ-EP bits + for (j = 0; j < SABER_N / 16; j++) { + res_avx[i][j] = _mm256_add_epi16 (res_avx[i][j], _mm256_set1_epi16(h1)); + res_avx[i][j] = _mm256_srli_epi16 (res_avx[i][j], (SABER_EQ - SABER_EP) ); + res_avx[i][j] = _mm256_and_si256 (res_avx[i][j], mod); + } + } + + //------------------Pack sk into byte string------- + + PQCLEAN_LIGHTSABER_AVX2_POLVEC2BS(sk, (const uint16_t (*)[SABER_N])skpv1, SABER_Q); + + //------------------Pack pk into byte string------- + + for (i = 0; i < SABER_K; i++) { // reuses skpv1[] for unpacking avx of public-key + for (j = 0; j < SABER_N / 16; j++) { + _mm256_maskstore_epi32 ((int *) (skpv1[i] + j * 16), _mm256_set1_epi32(-1), res_avx[i][j]); + } + } + PQCLEAN_LIGHTSABER_AVX2_POLVEC2BS(pk, (const uint16_t (*)[SABER_N])skpv1, SABER_P); // load the public-key into pk byte string + + + for (i = 0; i < SABER_SEEDBYTES; i++) { // now load the seedbytes in PK. Easy since seed bytes are kept in byte format. + pk[SABER_POLYVECCOMPRESSEDBYTES + i] = seed[i]; + } + +} + + +void PQCLEAN_LIGHTSABER_AVX2_indcpa_kem_enc(uint8_t ciphertext[SABER_BYTES_CCA_DEC], const uint8_t m[SABER_KEYBYTES], const uint8_t noiseseed[SABER_NOISESEEDBYTES], const uint8_t pk[SABER_INDCPA_PUBLICKEYBYTES]) { + + + uint32_t i, j, k; + polyvec a[SABER_K]; // skpv; + uint8_t seed[SABER_SEEDBYTES]; + uint16_t pkcl[SABER_K][SABER_N]; //public key of received by the client + + + uint16_t skpv1[SABER_K][SABER_N]; + uint16_t temp[SABER_K][SABER_N]; + uint16_t message[SABER_KEYBYTES * 8]; + + uint8_t msk_c[SABER_SCALEBYTES_KEM]; + + //--------------AVX declaration------------------ + + __m256i sk_avx[SABER_K][SABER_N / 16]; + __m256i mod, mod_p; + __m256i res_avx[SABER_K][SABER_N / 16]; + __m256i vprime_avx[SABER_N / 16]; + __m256i a_avx[SABER_K][SABER_K][SABER_N / 16]; + //__m256i acc[2*SABER_N/16]; + + __m256i pkcl_avx[SABER_K][SABER_N / 16]; + + __m256i message_avx[SABER_N / 16]; + + mod = _mm256_set1_epi16(SABER_Q - 1); + mod_p = _mm256_set1_epi16(SABER_P - 1); + + + + __m256i b_bucket[NUM_POLY][SCHB_N * 4]; + + //--------------AVX declaration ends------------------ + for (i = 0; i < SABER_SEEDBYTES; i++) { // Load the seedbytes in the client seed from PK. + seed[i] = pk[ SABER_POLYVECCOMPRESSEDBYTES + i]; + } + + GenMatrix(a, seed); + GenSecret(skpv1, noiseseed); + + // ----------- Load skpv1 into avx vectors ---------- + for (i = 0; i < SABER_K; i++) { + for (j = 0; j < SABER_N / 16; j++) { + sk_avx[i][j] = _mm256_loadu_si256 ((__m256i const *) (&skpv1[i][j * 16])); + } + } + + // ----------- Load skpv1 into avx vectors ---------- + for (i = 0; i < SABER_K; i++) { + for (j = 0; j < SABER_K; j++) { + for (k = 0; k < SABER_N / 16; k++) { + a_avx[i][j][k] = _mm256_loadu_si256 ((__m256i const *) (&a[i].vec[j].coeffs[k * 16])); + } + } + } + //-----------------matrix-vector multiplication and rounding + + for (j = 0; j < NUM_POLY; j++) { + TC_eval(sk_avx[j], b_bucket[j]); + } + matrix_vector_mul(a_avx, b_bucket, res_avx, 0);// Matrix-vector multiplication; Matrix in normal order + + // Now truncation + + for (i = 0; i < SABER_K; i++) { //shift right EQ-EP bits + for (j = 0; j < SABER_N / 16; j++) { + res_avx[i][j] = _mm256_add_epi16 (res_avx[i][j], _mm256_set1_epi16(h1)); + res_avx[i][j] = _mm256_srli_epi16 (res_avx[i][j], (SABER_EQ - SABER_EP) ); + res_avx[i][j] = _mm256_and_si256 (res_avx[i][j], mod); + + } + } + + + //-----this result should be put in b_prime for later use in server. + for (i = 0; i < SABER_K; i++) { // first store in 16 bit arrays + for (j = 0; j < SABER_N / 16; j++) { + _mm256_maskstore_epi32 ((int *)(temp[i] + j * 16), _mm256_set1_epi32(-1), res_avx[i][j]); + } + } + + PQCLEAN_LIGHTSABER_AVX2_POLVEC2BS(ciphertext, (const uint16_t (*)[SABER_N])temp, SABER_P); // Pack b_prime into ciphertext byte string + +//**************client matrix-vector multiplication ends******************// + + //------now calculate the v' + + //-------unpack the public_key + PQCLEAN_LIGHTSABER_AVX2_BS2POLVEC(pkcl, pk, SABER_P); + + for (i = 0; i < SABER_K; i++) { + for (j = 0; j < SABER_N / 16; j++) { + pkcl_avx[i][j] = _mm256_loadu_si256 ((__m256i const *) (&pkcl[i][j * 16])); + } + } + + // InnerProduct + //for(k=0;k> i) & 0x01); + } + } + // message encoding + for (i = 0; i < SABER_N / 16; i++) { + message_avx[i] = _mm256_loadu_si256 ((__m256i const *) (&message[i * 16])); + message_avx[i] = _mm256_slli_epi16 (message_avx[i], (SABER_EP - 1) ); + } + + // SHIFTRIGHT(v'+h1-m mod p, EP-ET) + for (k = 0; k < SABER_N / 16; k++) { + vprime_avx[k] = _mm256_sub_epi16(vprime_avx[k], message_avx[k]); + vprime_avx[k] = _mm256_and_si256(vprime_avx[k], mod_p); + vprime_avx[k] = _mm256_srli_epi16 (vprime_avx[k], (SABER_EP - SABER_ET) ); + } + + // Unpack avx + for (j = 0; j < SABER_N / 16; j++) { + _mm256_maskstore_epi32 ((int *) (temp[0] + j * 16), _mm256_set1_epi32(-1), vprime_avx[j]); + } + + PQCLEAN_LIGHTSABER_AVX2_SABER_pack_3bit(msk_c, temp[0]); + + + for (j = 0; j < SABER_SCALEBYTES_KEM; j++) { + ciphertext[SABER_CIPHERTEXTBYTES + j] = msk_c[j]; + } + +} + + +void PQCLEAN_LIGHTSABER_AVX2_indcpa_kem_dec(uint8_t m[SABER_KEYBYTES], const uint8_t sk[SABER_INDCPA_SECRETKEYBYTES], const uint8_t ciphertext[SABER_BYTES_CCA_DEC]) { + + uint32_t i, j; + uint16_t sksv[SABER_K][SABER_N]; //secret key of the server + uint16_t pksv[SABER_K][SABER_N]; + uint16_t message_dec_unpacked[SABER_KEYBYTES * 8]; // one element containes on decrypted bit; + uint8_t scale_ar[SABER_SCALEBYTES_KEM]; + uint16_t op[SABER_N]; + + //--------------AVX declaration------------------ + + + //__m256i mod_p; + + __m256i v_avx[SABER_N / 16]; + + //__m256i acc[2*SABER_N/16]; + + __m256i sksv_avx[SABER_K][SABER_N / 16]; + __m256i pksv_avx[SABER_K][SABER_N / 16]; + + //mod_p=_mm256_set1_epi16(SABER_P-1); + + __m256i b_bucket[NUM_POLY][SCHB_N * 4]; + //--------------AVX declaration ends------------------ + + //-------unpack the public_key + + PQCLEAN_LIGHTSABER_AVX2_BS2POLVEC(sksv, sk, SABER_Q); //sksv is the secret-key + PQCLEAN_LIGHTSABER_AVX2_BS2POLVEC(pksv, ciphertext, SABER_P); //pksv is the ciphertext + + for (i = 0; i < SABER_K; i++) { + for (j = 0; j < SABER_N / 16; j++) { + sksv_avx[i][j] = _mm256_loadu_si256 ((__m256i const *) (&sksv[i][j * 16])); + pksv_avx[i][j] = _mm256_loadu_si256 ((__m256i const *) (&pksv[i][j * 16])); + } + } + + for (i = 0; i < SABER_N / 16; i++) { + v_avx[i] = _mm256_xor_si256(v_avx[i], v_avx[i]); + } + + + // InnerProduct(b', s, mod p) + + for (j = 0; j < NUM_POLY; j++) { + TC_eval(sksv_avx[j], b_bucket[j]); + } + + vector_vector_mul(pksv_avx, b_bucket, v_avx); + + for (i = 0; i < SABER_N / 16; i++) { + _mm256_maskstore_epi32 ((int *)(message_dec_unpacked + i * 16), _mm256_set1_epi32(-1), v_avx[i]); + } + + + for (i = 0; i < SABER_SCALEBYTES_KEM; i++) { + scale_ar[i] = ciphertext[SABER_CIPHERTEXTBYTES + i]; + } + + PQCLEAN_LIGHTSABER_AVX2_SABER_un_pack3bit(op, scale_ar); + + + //addition of h2 + for (i = 0; i < SABER_N; i++) { + message_dec_unpacked[i] = ( ( message_dec_unpacked[i] + h2 - (op[i] << (SABER_EP - SABER_ET)) ) & (SABER_P - 1) ) >> (SABER_EP - 1); + } + + + POL2MSG(m, message_dec_unpacked); +} diff --git a/crypto_kem/lightsaber/avx2/SABER_indcpa.h b/crypto_kem/lightsaber/avx2/SABER_indcpa.h new file mode 100644 index 00000000..61ee77ba --- /dev/null +++ b/crypto_kem/lightsaber/avx2/SABER_indcpa.h @@ -0,0 +1,13 @@ +#ifndef INDCPA_H +#define INDCPA_H +#include "SABER_params.h" +#include + +void PQCLEAN_LIGHTSABER_AVX2_indcpa_kem_keypair(uint8_t pk[SABER_INDCPA_PUBLICKEYBYTES], uint8_t sk[SABER_INDCPA_SECRETKEYBYTES]); + +void PQCLEAN_LIGHTSABER_AVX2_indcpa_kem_enc(uint8_t ciphertext[SABER_BYTES_CCA_DEC], const uint8_t m[SABER_KEYBYTES], const uint8_t noiseseed[SABER_NOISESEEDBYTES], const uint8_t pk[SABER_INDCPA_PUBLICKEYBYTES]); + +void PQCLEAN_LIGHTSABER_AVX2_indcpa_kem_dec(uint8_t m[SABER_KEYBYTES], const uint8_t sk[SABER_INDCPA_SECRETKEYBYTES], const uint8_t ciphertext[SABER_BYTES_CCA_DEC]); + + +#endif diff --git a/crypto_kem/lightsaber/avx2/SABER_params.h b/crypto_kem/lightsaber/avx2/SABER_params.h new file mode 100644 index 00000000..11d34fda --- /dev/null +++ b/crypto_kem/lightsaber/avx2/SABER_params.h @@ -0,0 +1,46 @@ +#ifndef PARAMS_H +#define PARAMS_H +#include "api.h" + + + + +#define SABER_K 2 +#define SABER_MU 10 +#define SABER_ET 3 + + +#define SABER_EQ 13 +#define SABER_EP 10 + +#define SABER_N 256 +#define SABER_Q 8192 //2^13 +#define SABER_P 1024 + +#define SABER_SEEDBYTES 32 +#define SABER_NOISESEEDBYTES 32 +#define SABER_COINBYTES 32 +#define SABER_KEYBYTES 32 + +#define SABER_HASHBYTES 32 + +#define SABER_POLYBYTES 416 //13*256/8 + +#define SABER_POLYVECBYTES (SABER_K * SABER_POLYBYTES) + +#define SABER_POLYVECCOMPRESSEDBYTES (SABER_K * 320) //10*256/8 NOTE : changed till here due to parameter adaptation + +#define SABER_CIPHERTEXTBYTES (SABER_POLYVECCOMPRESSEDBYTES) + +#define SABER_SCALEBYTES_KEM ((SABER_ET)*SABER_N/8) + +#define SABER_INDCPA_PUBLICKEYBYTES (SABER_POLYVECCOMPRESSEDBYTES + SABER_SEEDBYTES) +#define SABER_INDCPA_SECRETKEYBYTES (SABER_POLYVECBYTES) + +#define SABER_PUBLICKEYBYTES (SABER_INDCPA_PUBLICKEYBYTES) + +#define SABER_SECRETKEYBYTES (SABER_INDCPA_SECRETKEYBYTES + SABER_INDCPA_PUBLICKEYBYTES + SABER_HASHBYTES + SABER_KEYBYTES) + +#define SABER_BYTES_CCA_DEC (SABER_POLYVECCOMPRESSEDBYTES + SABER_SCALEBYTES_KEM) /* Second part is for Targhi-Unruh */ + +#endif diff --git a/crypto_kem/lightsaber/avx2/api.h b/crypto_kem/lightsaber/avx2/api.h new file mode 100644 index 00000000..d1e2105b --- /dev/null +++ b/crypto_kem/lightsaber/avx2/api.h @@ -0,0 +1,18 @@ +#ifndef PQCLEAN_LIGHTSABER_AVX2_API_H +#define PQCLEAN_LIGHTSABER_AVX2_API_H + + +#define PQCLEAN_LIGHTSABER_AVX2_CRYPTO_ALGNAME "LightSaber" +#define PQCLEAN_LIGHTSABER_AVX2_CRYPTO_BYTES 32 +#define PQCLEAN_LIGHTSABER_AVX2_CRYPTO_CIPHERTEXTBYTES 736 +#define PQCLEAN_LIGHTSABER_AVX2_CRYPTO_PUBLICKEYBYTES 672 +#define PQCLEAN_LIGHTSABER_AVX2_CRYPTO_SECRETKEYBYTES 1568 + +int PQCLEAN_LIGHTSABER_AVX2_crypto_kem_keypair(unsigned char *pk, unsigned char *sk); + +int PQCLEAN_LIGHTSABER_AVX2_crypto_kem_enc(unsigned char *ct, unsigned char *k, const unsigned char *pk); + +int PQCLEAN_LIGHTSABER_AVX2_crypto_kem_dec(unsigned char *k, const unsigned char *ct, const unsigned char *sk); + + +#endif /* PQCLEAN_LIGHTSABER_AVX2_API_H */ diff --git a/crypto_kem/lightsaber/avx2/cbd.c b/crypto_kem/lightsaber/avx2/cbd.c new file mode 100644 index 00000000..a43170e2 --- /dev/null +++ b/crypto_kem/lightsaber/avx2/cbd.c @@ -0,0 +1,51 @@ +#include "SABER_params.h" +#include "api.h" +#include "cbd.h" +#include +/*--------------------------------------------------------------------- +This file has been adapted from the implementation +(available at, Public Domain https://github.com/pq-crystals/kyber) +of "CRYSTALS – Kyber: a CCA-secure module-lattice-based KEM" +by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint, +Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle +----------------------------------------------------------------------*/ + + +static uint64_t load_littleendian(const unsigned char *x, int bytes) { + int i; + uint64_t r = x[0]; + for (i = 1; i < bytes; i++) { + r |= (uint64_t)x[i] << (8 * i); + } + return r; +} + + +void PQCLEAN_LIGHTSABER_AVX2_cbd(uint16_t *r, const unsigned char *buf) { + uint16_t Qmod_minus1 = SABER_Q - 1; + + uint64_t t, d, a[4], b[4]; + int i, j; + + for (i = 0; i < SABER_N / 4; i++) { + t = load_littleendian(buf + 5 * i, 5); + d = 0; + for (j = 0; j < 5; j++) { + d += (t >> j) & 0x0842108421UL; + } + + a[0] = d & 0x1f; + b[0] = (d >> 5) & 0x1f; + a[1] = (d >> 10) & 0x1f; + b[1] = (d >> 15) & 0x1f; + a[2] = (d >> 20) & 0x1f; + b[2] = (d >> 25) & 0x1f; + a[3] = (d >> 30) & 0x1f; + b[3] = (d >> 35); + + r[4 * i + 0] = (uint16_t)(a[0] - b[0]) & Qmod_minus1; + r[4 * i + 1] = (uint16_t)(a[1] - b[1]) & Qmod_minus1; + r[4 * i + 2] = (uint16_t)(a[2] - b[2]) & Qmod_minus1; + r[4 * i + 3] = (uint16_t)(a[3] - b[3]) & Qmod_minus1; + } +} diff --git a/crypto_kem/lightsaber/avx2/cbd.h b/crypto_kem/lightsaber/avx2/cbd.h new file mode 100644 index 00000000..01ba76e8 --- /dev/null +++ b/crypto_kem/lightsaber/avx2/cbd.h @@ -0,0 +1,16 @@ +#ifndef CBD_H +#define CBD_H +/*--------------------------------------------------------------------- +This file has been adapted from the implementation +(available at, Public Domain https://github.com/pq-crystals/kyber) +of "CRYSTALS – Kyber: a CCA-secure module-lattice-based KEM" +by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint, +Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle +----------------------------------------------------------------------*/ +#include "poly.h" +#include + +void PQCLEAN_LIGHTSABER_AVX2_cbd(uint16_t *r, const unsigned char *buf); + + +#endif diff --git a/crypto_kem/lightsaber/avx2/kem.c b/crypto_kem/lightsaber/avx2/kem.c new file mode 100644 index 00000000..70221f10 --- /dev/null +++ b/crypto_kem/lightsaber/avx2/kem.c @@ -0,0 +1,79 @@ +#include "SABER_indcpa.h" +#include "SABER_params.h" +#include "api.h" +#include "fips202.h" +#include "randombytes.h" +#include "verify.h" +#include +#include +#include +#include + + +int PQCLEAN_LIGHTSABER_AVX2_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) { + int i; + + PQCLEAN_LIGHTSABER_AVX2_indcpa_kem_keypair(pk, sk); // sk[0:SABER_INDCPA_SECRETKEYBYTES-1] <-- sk + for (i = 0; i < SABER_INDCPA_PUBLICKEYBYTES; i++) { + sk[i + SABER_INDCPA_SECRETKEYBYTES] = pk[i]; // sk[SABER_INDCPA_SECRETKEYBYTES:SABER_INDCPA_SECRETKEYBYTES+SABER_INDCPA_SECRETKEYBYTES-1] <-- pk + } + + sha3_256(sk + SABER_SECRETKEYBYTES - 64, pk, SABER_INDCPA_PUBLICKEYBYTES); // Then hash(pk) is appended. + + randombytes(sk + SABER_SECRETKEYBYTES - SABER_KEYBYTES, SABER_KEYBYTES); // Remaining part of sk contains a pseudo-random number. + // This is output when check in PQCLEAN_LIGHTSABER_AVX2_crypto_kem_dec() fails. + return (0); +} + +int PQCLEAN_LIGHTSABER_AVX2_crypto_kem_enc(uint8_t *c, uint8_t *k, const uint8_t *pk) { + + uint8_t kr[64]; // Will contain key, coins + uint8_t buf[64]; + + randombytes(buf, 32); + + sha3_256(buf, buf, 32); // BUF[0:31] <-- random message (will be used as the key for client) Note: hash doesnot release system RNG output + + sha3_256(buf + 32, pk, SABER_INDCPA_PUBLICKEYBYTES); // BUF[32:63] <-- Hash(public key); Multitarget countermeasure for coins + contributory KEM + + sha3_512(kr, buf, 64); // kr[0:63] <-- Hash(buf[0:63]); + // K^ <-- kr[0:31] + // noiseseed (r) <-- kr[32:63]; + PQCLEAN_LIGHTSABER_AVX2_indcpa_kem_enc(c, buf, (const uint8_t *) (kr + 32), pk); // buf[0:31] contains message; kr[32:63] contains randomness r; + + sha3_256(kr + 32, c, SABER_BYTES_CCA_DEC); + + sha3_256(k, kr, 64); // hash concatenation of pre-k and h(c) to k + + return (0); +} + +int PQCLEAN_LIGHTSABER_AVX2_crypto_kem_dec(uint8_t *k, const uint8_t *c, const uint8_t *sk) { + int i; + uint8_t fail; + uint8_t cmp[SABER_BYTES_CCA_DEC]; + uint8_t buf[64]; + uint8_t kr[64]; // Will contain key, coins + const uint8_t *pk = sk + SABER_INDCPA_SECRETKEYBYTES; + + PQCLEAN_LIGHTSABER_AVX2_indcpa_kem_dec(buf, sk, c); // buf[0:31] <-- message + + // Multitarget countermeasure for coins + contributory KEM + for (i = 0; i < 32; i++) { // Save hash by storing h(pk) in sk + buf[32 + i] = sk[SABER_SECRETKEYBYTES - 64 + i]; + } + + sha3_512(kr, buf, 64); + + PQCLEAN_LIGHTSABER_AVX2_indcpa_kem_enc(cmp, buf, (const uint8_t *) (kr + 32), pk); + + fail = PQCLEAN_LIGHTSABER_AVX2_verify(c, cmp, SABER_BYTES_CCA_DEC); + + sha3_256(kr + 32, c, SABER_BYTES_CCA_DEC); // overwrite coins in kr with h(c) + + PQCLEAN_LIGHTSABER_AVX2_cmov(kr, sk + SABER_SECRETKEYBYTES - SABER_KEYBYTES, SABER_KEYBYTES, fail); + + sha3_256(k, kr, 64); // hash concatenation of pre-k and h(c) to k + + return (0); +} diff --git a/crypto_kem/lightsaber/avx2/kem.h b/crypto_kem/lightsaber/avx2/kem.h new file mode 100644 index 00000000..b80c335d --- /dev/null +++ b/crypto_kem/lightsaber/avx2/kem.h @@ -0,0 +1,35 @@ +#ifndef INDCPA_H +#define INDCPA_H + +#include + +void PQCLEAN_LIGHTSABER_AVX2_indcpa_keypair(uint8_t *pk, uint8_t *sk); + + +void PQCLEAN_LIGHTSABER_AVX2_indcpa_client(uint8_t *pk, uint8_t *b_prime, uint8_t *c, uint8_t *key); + + +void PQCLEAN_LIGHTSABER_AVX2_indcpa_server(uint8_t *pk, uint8_t *b_prime, uint8_t *c, uint8_t *key); + + +void PQCLEAN_LIGHTSABER_AVX2_indcpa_kem_keypair(uint8_t *pk, uint8_t *sk); + +void PQCLEAN_LIGHTSABER_AVX2_indcpa_kem_enc(uint8_t *message, uint8_t *noiseseed, uint8_t *pk, uint8_t *ciphertext); + +void PQCLEAN_LIGHTSABER_AVX2_indcpa_kem_dec(uint8_t *sk, uint8_t *ciphertext, uint8_t message_dec[]); + + +int PQCLEAN_LIGHTSABER_AVX2_crypto_kem_keypair(unsigned char *pk, unsigned char *sk); + +int PQCLEAN_LIGHTSABER_AVX2_crypto_kem_enc(unsigned char *c, unsigned char *k, const unsigned char *pk); + +int PQCLEAN_LIGHTSABER_AVX2_crypto_kem_dec(unsigned char *k, const unsigned char *c, const unsigned char *sk); + + + +//uint64_t clock1,clock2; + +//uint64_t clock_kp_kex, clock_enc_kex, clock_dec_kex; + + +#endif diff --git a/crypto_kem/lightsaber/avx2/pack_unpack.c b/crypto_kem/lightsaber/avx2/pack_unpack.c new file mode 100644 index 00000000..e912fd0a --- /dev/null +++ b/crypto_kem/lightsaber/avx2/pack_unpack.c @@ -0,0 +1,502 @@ +#include "pack_unpack.h" + + +void PQCLEAN_LIGHTSABER_AVX2_SABER_pack_3bit(uint8_t *bytes, const uint16_t *data) { + + uint32_t j; + uint32_t offset_data = 0, offset_byte = 0; + + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = 3 * j; + offset_data = 8 * j; + bytes[offset_byte + 0] = (data[offset_data + 0] & 0x7) | ( (data[offset_data + 1] & 0x7) << 3 ) | ((data[offset_data + 2] & 0x3) << 6); + bytes[offset_byte + 1] = ((data[offset_data + 2] >> 2 ) & 0x01) | ( (data[offset_data + 3] & 0x7) << 1 ) | ( (data[offset_data + 4] & 0x7) << 4 ) | (((data[offset_data + 5]) & 0x01) << 7); + bytes[offset_byte + 2] = ((data[offset_data + 5] >> 1 ) & 0x03) | ( (data[offset_data + 6] & 0x7) << 2 ) | ( (data[offset_data + 7] & 0x7) << 5 ); + } +} + +void PQCLEAN_LIGHTSABER_AVX2_SABER_un_pack3bit(uint16_t *data, const uint8_t *bytes) { + + uint32_t j; + uint32_t offset_data = 0, offset_byte = 0; + + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = 3 * j; + offset_data = 8 * j; + data[offset_data + 0] = (bytes[offset_byte + 0]) & 0x07; + data[offset_data + 1] = ( (bytes[offset_byte + 0]) >> 3 ) & 0x07; + data[offset_data + 2] = ( ( (bytes[offset_byte + 0]) >> 6 ) & 0x03) | ( ( (bytes[offset_byte + 1]) & 0x01) << 2 ); + data[offset_data + 3] = ( (bytes[offset_byte + 1]) >> 1 ) & 0x07; + data[offset_data + 4] = ( (bytes[offset_byte + 1]) >> 4 ) & 0x07; + data[offset_data + 5] = ( ( (bytes[offset_byte + 1]) >> 7 ) & 0x01) | ( ( (bytes[offset_byte + 2]) & 0x03) << 1 ); + data[offset_data + 6] = ( (bytes[offset_byte + 2] >> 2) & 0x07 ); + data[offset_data + 7] = ( (bytes[offset_byte + 2] >> 5) & 0x07 ); + } + +} + +void PQCLEAN_LIGHTSABER_AVX2_SABER_pack_4bit(uint8_t *bytes, const uint16_t *data) { + + uint32_t j; + uint32_t offset_data = 0; + + for (j = 0; j < SABER_N / 2; j++) { + offset_data = 2 * j; + bytes[j] = (data[offset_data] & 0x0f) | ( (data[offset_data + 1] & 0x0f) << 4 ); + } +} + +void PQCLEAN_LIGHTSABER_AVX2_SABER_un_pack4bit(uint16_t *data, const uint8_t *bytes) { + + uint32_t j; + uint32_t offset_data = 0; + + for (j = 0; j < SABER_N / 2; j++) { + offset_data = 2 * j; + data[offset_data] = bytes[j] & 0x0f; + data[offset_data + 1] = (bytes[j] >> 4) & 0x0f; + } +} + +void PQCLEAN_LIGHTSABER_AVX2_SABER_pack_6bit(uint8_t *bytes, const uint16_t *data) { + + uint32_t j; + uint32_t offset_data = 0, offset_byte = 0; + + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = 3 * j; + offset_data = 4 * j; + bytes[offset_byte + 0] = (data[offset_data + 0] & 0x3f) | ((data[offset_data + 1] & 0x03) << 6); + bytes[offset_byte + 1] = ((data[offset_data + 1] >> 2) & 0x0f) | ((data[offset_data + 2] & 0x0f) << 4); + bytes[offset_byte + 2] = ((data[offset_data + 2] >> 4) & 0x03) | ((data[offset_data + 3] & 0x3f) << 2); + } +} + + +void PQCLEAN_LIGHTSABER_AVX2_SABER_un_pack6bit(uint16_t *data, const uint8_t *bytes) { + + uint32_t j; + uint32_t offset_data = 0, offset_byte = 0; + + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = 3 * j; + offset_data = 4 * j; + data[offset_data + 0] = bytes[offset_byte + 0] & 0x3f; + data[offset_data + 1] = ((bytes[offset_byte + 0] >> 6) & 0x03) | ((bytes[offset_byte + 1] & 0x0f) << 2) ; + data[offset_data + 2] = ((bytes[offset_byte + 1] & 0xff) >> 4) | ((bytes[offset_byte + 2] & 0x03) << 4) ; + data[offset_data + 3] = ((bytes[offset_byte + 2] & 0xff) >> 2); + } + +} + +void PQCLEAN_LIGHTSABER_AVX2_SABER_pack10bit(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 10) / 8; + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = offset_byte1 + 5 * j; + offset_data = 4 * j; + bytes[offset_byte + 0] = ( data[i][ offset_data + 0 ] & (0xff)); + + bytes[offset_byte + 1] = ( (data[i][ offset_data + 0 ] >> 8) & 0x03 ) | ((data[i][ offset_data + 1 ] & 0x3f) << 2); + + bytes[offset_byte + 2] = ( (data[i][ offset_data + 1 ] >> 6) & 0x0f ) | ( (data[i][ offset_data + 2 ] & 0x0f) << 4); + + bytes[offset_byte + 3] = ( (data[i][ offset_data + 2 ] >> 4) & 0x3f ) | ((data[i][ offset_data + 3 ] & 0x03) << 6); + + bytes[offset_byte + 4] = ( (data[i][ offset_data + 3 ] >> 2) & 0xff ); + } + } +} + +void PQCLEAN_LIGHTSABER_AVX2_POLVECp2BS(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 10) / 8; + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = offset_byte1 + 5 * j; + offset_data = 4 * j; + bytes[offset_byte + 0] = ( data[i][ offset_data + 0 ] & (0xff)); + + bytes[offset_byte + 1] = ( (data[i][ offset_data + 0 ] >> 8) & 0x03 ) | ((data[i][ offset_data + 1 ] & 0x3f) << 2); + + bytes[offset_byte + 2] = ( (data[i][ offset_data + 1 ] >> 6) & 0x0f ) | ( (data[i][ offset_data + 2 ] & 0x0f) << 4); + + bytes[offset_byte + 3] = ( (data[i][ offset_data + 2 ] >> 4) & 0x3f ) | ((data[i][ offset_data + 3 ] & 0x03) << 6); + + bytes[offset_byte + 4] = ( (data[i][ offset_data + 3 ] >> 2) & 0xff ); + } + } +} + +void PQCLEAN_LIGHTSABER_AVX2_POLVECq2BS(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 13) / 8; + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = offset_byte1 + 13 * j; + offset_data = 8 * j; + bytes[offset_byte + 0] = ( data[i][ offset_data + 0 ] & (0xff)); + + bytes[offset_byte + 1] = ( (data[i][ offset_data + 0 ] >> 8) & 0x1f ) | ((data[i][ offset_data + 1 ] & 0x07) << 5); + + bytes[offset_byte + 2] = ( (data[i][ offset_data + 1 ] >> 3) & 0xff ); + + bytes[offset_byte + 3] = ( (data[i][ offset_data + 1 ] >> 11) & 0x03 ) | ((data[i][ offset_data + 2 ] & 0x3f) << 2); + + bytes[offset_byte + 4] = ( (data[i][ offset_data + 2 ] >> 6) & 0x7f ) | ( (data[i][ offset_data + 3 ] & 0x01) << 7 ); + + bytes[offset_byte + 5] = ( (data[i][ offset_data + 3 ] >> 1) & 0xff ); + + bytes[offset_byte + 6] = ( (data[i][ offset_data + 3 ] >> 9) & 0x0f ) | ( (data[i][ offset_data + 4 ] & 0x0f) << 4 ); + + bytes[offset_byte + 7] = ( (data[i][ offset_data + 4] >> 4) & 0xff ); + + bytes[offset_byte + 8] = ( (data[i][ offset_data + 4 ] >> 12) & 0x01 ) | ( (data[i][ offset_data + 5 ] & 0x7f) << 1 ); + + bytes[offset_byte + 9] = ( (data[i][ offset_data + 5 ] >> 7) & 0x3f ) | ( (data[i][ offset_data + 6 ] & 0x03) << 6 ); + + bytes[offset_byte + 10] = ( (data[i][ offset_data + 6 ] >> 2) & 0xff ); + + bytes[offset_byte + 11] = ( (data[i][ offset_data + 6 ] >> 10) & 0x07 ) | ( (data[i][ offset_data + 7 ] & 0x1f) << 3 ); + + bytes[offset_byte + 12] = ( (data[i][ offset_data + 7 ] >> 5) & 0xff ); + + } + } + + +} + +void PQCLEAN_LIGHTSABER_AVX2_BS2POLq(uint16_t data[SABER_N], const uint8_t *bytes) { + + uint32_t j; + uint32_t offset_data = 0, offset_byte = 0; + + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = 13 * j; + offset_data = 8 * j; + data[offset_data + 0] = ( bytes[ offset_byte + 0 ] & (0xff)) | ((bytes[offset_byte + 1] & 0x1f) << 8); + data[offset_data + 1] = ( bytes[ offset_byte + 1 ] >> 5 & (0x07)) | ((bytes[offset_byte + 2] & 0xff) << 3) | ((bytes[offset_byte + 3] & 0x03) << 11); + data[offset_data + 2] = ( bytes[ offset_byte + 3 ] >> 2 & (0x3f)) | ((bytes[offset_byte + 4] & 0x7f) << 6); + data[offset_data + 3] = ( bytes[ offset_byte + 4 ] >> 7 & (0x01)) | ((bytes[offset_byte + 5] & 0xff) << 1) | ((bytes[offset_byte + 6] & 0x0f) << 9); + data[offset_data + 4] = ( bytes[ offset_byte + 6 ] >> 4 & (0x0f)) | ((bytes[offset_byte + 7] & 0xff) << 4) | ((bytes[offset_byte + 8] & 0x01) << 12); + data[offset_data + 5] = ( bytes[ offset_byte + 8] >> 1 & (0x7f)) | ((bytes[offset_byte + 9] & 0x3f) << 7); + data[offset_data + 6] = ( bytes[ offset_byte + 9] >> 6 & (0x03)) | ((bytes[offset_byte + 10] & 0xff) << 2) | ((bytes[offset_byte + 11] & 0x07) << 10); + data[offset_data + 7] = ( bytes[ offset_byte + 11] >> 3 & (0x1f)) | ((bytes[offset_byte + 12] & 0xff) << 5); + } +} + + + +void PQCLEAN_LIGHTSABER_AVX2_BS2POLVECp(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 10) / 8; + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = offset_byte1 + 5 * j; + offset_data = 4 * j; + data[i][offset_data + 0] = ( bytes[ offset_byte + 0 ] & (0xff)) | ((bytes[ offset_byte + 1 ] & 0x03) << 8); + data[i][offset_data + 1] = ( (bytes[ offset_byte + 1 ] >> 2) & (0x3f)) | ((bytes[ offset_byte + 2 ] & 0x0f) << 6); + data[i][offset_data + 2] = ( (bytes[ offset_byte + 2 ] >> 4) & (0x0f)) | ((bytes[ offset_byte + 3 ] & 0x3f) << 4); + data[i][offset_data + 3] = ( (bytes[ offset_byte + 3 ] >> 6) & (0x03)) | ((bytes[ offset_byte + 4 ] & 0xff) << 2); + + } + } +} + +void PQCLEAN_LIGHTSABER_AVX2_BS2POLVECq(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 13) / 8; + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = offset_byte1 + 13 * j; + offset_data = 8 * j; + data[i][offset_data + 0] = ( bytes[ offset_byte + 0 ] & (0xff)) | ((bytes[offset_byte + 1] & 0x1f) << 8); + data[i][offset_data + 1] = ( bytes[ offset_byte + 1 ] >> 5 & (0x07)) | ((bytes[offset_byte + 2] & 0xff) << 3) | ((bytes[offset_byte + 3] & 0x03) << 11); + data[i][offset_data + 2] = ( bytes[ offset_byte + 3 ] >> 2 & (0x3f)) | ((bytes[offset_byte + 4] & 0x7f) << 6); + data[i][offset_data + 3] = ( bytes[ offset_byte + 4 ] >> 7 & (0x01)) | ((bytes[offset_byte + 5] & 0xff) << 1) | ((bytes[offset_byte + 6] & 0x0f) << 9); + data[i][offset_data + 4] = ( bytes[ offset_byte + 6 ] >> 4 & (0x0f)) | ((bytes[offset_byte + 7] & 0xff) << 4) | ((bytes[offset_byte + 8] & 0x01) << 12); + data[i][offset_data + 5] = ( bytes[ offset_byte + 8] >> 1 & (0x7f)) | ((bytes[offset_byte + 9] & 0x3f) << 7); + data[i][offset_data + 6] = ( bytes[ offset_byte + 9] >> 6 & (0x03)) | ((bytes[offset_byte + 10] & 0xff) << 2) | ((bytes[offset_byte + 11] & 0x07) << 10); + data[i][offset_data + 7] = ( bytes[ offset_byte + 11] >> 3 & (0x1f)) | ((bytes[offset_byte + 12] & 0xff) << 5); + } + } + + +} + + + +void PQCLEAN_LIGHTSABER_AVX2_SABER_un_pack10bit(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 10) / 8; + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = offset_byte1 + 5 * j; + offset_data = 4 * j; + data[i][offset_data + 0] = ( bytes[ offset_byte + 0 ] & (0xff)) | ((bytes[ offset_byte + 1 ] & 0x03) << 8); + data[i][offset_data + 1] = ( (bytes[ offset_byte + 1 ] >> 2) & (0x3f)) | ((bytes[ offset_byte + 2 ] & 0x0f) << 6); + data[i][offset_data + 2] = ( (bytes[ offset_byte + 2 ] >> 4) & (0x0f)) | ((bytes[ offset_byte + 3 ] & 0x3f) << 4); + data[i][offset_data + 3] = ( (bytes[ offset_byte + 3 ] >> 6) & (0x03)) | ((bytes[ offset_byte + 4 ] & 0xff) << 2); + + } + } + + +} + + +void PQCLEAN_LIGHTSABER_AVX2_SABER_pack13bit(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 13) / 8; + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = offset_byte1 + 13 * j; + offset_data = 8 * j; + bytes[offset_byte + 0] = ( data[i][ offset_data + 0 ] & (0xff)); + + bytes[offset_byte + 1] = ( (data[i][ offset_data + 0 ] >> 8) & 0x1f ) | ((data[i][ offset_data + 1 ] & 0x07) << 5); + + bytes[offset_byte + 2] = ( (data[i][ offset_data + 1 ] >> 3) & 0xff ); + + bytes[offset_byte + 3] = ( (data[i][ offset_data + 1 ] >> 11) & 0x03 ) | ((data[i][ offset_data + 2 ] & 0x3f) << 2); + + bytes[offset_byte + 4] = ( (data[i][ offset_data + 2 ] >> 6) & 0x7f ) | ( (data[i][ offset_data + 3 ] & 0x01) << 7 ); + + bytes[offset_byte + 5] = ( (data[i][ offset_data + 3 ] >> 1) & 0xff ); + + bytes[offset_byte + 6] = ( (data[i][ offset_data + 3 ] >> 9) & 0x0f ) | ( (data[i][ offset_data + 4 ] & 0x0f) << 4 ); + + bytes[offset_byte + 7] = ( (data[i][ offset_data + 4] >> 4) & 0xff ); + + bytes[offset_byte + 8] = ( (data[i][ offset_data + 4 ] >> 12) & 0x01 ) | ( (data[i][ offset_data + 5 ] & 0x7f) << 1 ); + + bytes[offset_byte + 9] = ( (data[i][ offset_data + 5 ] >> 7) & 0x3f ) | ( (data[i][ offset_data + 6 ] & 0x03) << 6 ); + + bytes[offset_byte + 10] = ( (data[i][ offset_data + 6 ] >> 2) & 0xff ); + + bytes[offset_byte + 11] = ( (data[i][ offset_data + 6 ] >> 10) & 0x07 ) | ( (data[i][ offset_data + 7 ] & 0x1f) << 3 ); + + bytes[offset_byte + 12] = ( (data[i][ offset_data + 7 ] >> 5) & 0xff ); + + } + } + + +} + +void PQCLEAN_LIGHTSABER_AVX2_SABER_un_pack13bit(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 13) / 8; + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = offset_byte1 + 13 * j; + offset_data = 8 * j; + data[i][offset_data + 0] = ( bytes[ offset_byte + 0 ] & (0xff)) | ((bytes[offset_byte + 1] & 0x1f) << 8); + data[i][offset_data + 1] = ( bytes[ offset_byte + 1 ] >> 5 & (0x07)) | ((bytes[offset_byte + 2] & 0xff) << 3) | ((bytes[offset_byte + 3] & 0x03) << 11); + data[i][offset_data + 2] = ( bytes[ offset_byte + 3 ] >> 2 & (0x3f)) | ((bytes[offset_byte + 4] & 0x7f) << 6); + data[i][offset_data + 3] = ( bytes[ offset_byte + 4 ] >> 7 & (0x01)) | ((bytes[offset_byte + 5] & 0xff) << 1) | ((bytes[offset_byte + 6] & 0x0f) << 9); + data[i][offset_data + 4] = ( bytes[ offset_byte + 6 ] >> 4 & (0x0f)) | ((bytes[offset_byte + 7] & 0xff) << 4) | ((bytes[offset_byte + 8] & 0x01) << 12); + data[i][offset_data + 5] = ( bytes[ offset_byte + 8] >> 1 & (0x7f)) | ((bytes[offset_byte + 9] & 0x3f) << 7); + data[i][offset_data + 6] = ( bytes[ offset_byte + 9] >> 6 & (0x03)) | ((bytes[offset_byte + 10] & 0xff) << 2) | ((bytes[offset_byte + 11] & 0x07) << 10); + data[i][offset_data + 7] = ( bytes[ offset_byte + 11] >> 3 & (0x1f)) | ((bytes[offset_byte + 12] & 0xff) << 5); + } + } + + +} + +void PQCLEAN_LIGHTSABER_AVX2_SABER_poly_un_pack13bit(uint16_t data[SABER_N], const uint8_t *bytes) { + + uint32_t j; + uint32_t offset_data = 0, offset_byte = 0; + + //for(i=0;i> 5 & (0x07)) | ((bytes[offset_byte + 2] & 0xff) << 3) | ((bytes[offset_byte + 3] & 0x03) << 11); + data[offset_data + 2] = ( bytes[ offset_byte + 3 ] >> 2 & (0x3f)) | ((bytes[offset_byte + 4] & 0x7f) << 6); + data[offset_data + 3] = ( bytes[ offset_byte + 4 ] >> 7 & (0x01)) | ((bytes[offset_byte + 5] & 0xff) << 1) | ((bytes[offset_byte + 6] & 0x0f) << 9); + data[offset_data + 4] = ( bytes[ offset_byte + 6 ] >> 4 & (0x0f)) | ((bytes[offset_byte + 7] & 0xff) << 4) | ((bytes[offset_byte + 8] & 0x01) << 12); + data[offset_data + 5] = ( bytes[ offset_byte + 8] >> 1 & (0x7f)) | ((bytes[offset_byte + 9] & 0x3f) << 7); + data[offset_data + 6] = ( bytes[ offset_byte + 9] >> 6 & (0x03)) | ((bytes[offset_byte + 10] & 0xff) << 2) | ((bytes[offset_byte + 11] & 0x07) << 10); + data[offset_data + 7] = ( bytes[ offset_byte + 11] >> 3 & (0x1f)) | ((bytes[offset_byte + 12] & 0xff) << 5); + } + //} + + +} + + +void PQCLEAN_LIGHTSABER_AVX2_SABER_pack11bit(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]) { + /*This function packs 11 bit data stream into 8 bits of data. + */ + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 11) / 8; + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = offset_byte1 + 11 * j; + offset_data = 8 * j; + bytes[offset_byte + 0] = ( data[i][ offset_data + 0 ] & (0xff)); + + bytes[offset_byte + 1] = ( (data[i][ offset_data + 0 ] >> 8) & 0x07 ) | ((data[i][ offset_data + 1 ] & 0x1f) << 3); + + bytes[offset_byte + 2] = ( (data[i][ offset_data + 1 ] >> 5) & 0x3f ) | ((data[i][ offset_data + 2 ] & 0x03) << 6); + + bytes[offset_byte + 3] = ( (data[i][ offset_data + 2 ] >> 2) & 0xff ); + + bytes[offset_byte + 4] = ( (data[i][ offset_data + 2 ] >> 10) & 0x01 ) | ((data[i][ offset_data + 3 ] & 0x7f) << 1); + + bytes[offset_byte + 5] = ( (data[i][ offset_data + 3 ] >> 7) & 0x0f ) | ((data[i][ offset_data + 4 ] & 0x0f) << 4); + + bytes[offset_byte + 6] = ( (data[i][ offset_data + 4 ] >> 4) & 0x7f ) | ((data[i][ offset_data + 5 ] & 0x01) << 7); + + bytes[offset_byte + 7] = ( (data[i][ offset_data + 5 ] >> 1) & 0xff ); + + bytes[offset_byte + 8] = ( (data[i][ offset_data + 5 ] >> 9) & 0x03 ) | ((data[i][ offset_data + 6 ] & 0x3f) << 2); + + bytes[offset_byte + 9] = ( (data[i][ offset_data + 6 ] >> 6) & 0x1f ) | ((data[i][ offset_data + 7 ] & 0x07) << 5); + + bytes[offset_byte + 10] = ( (data[i][ offset_data + 7 ] >> 3) & 0xff ); + + } + } + +} + +void PQCLEAN_LIGHTSABER_AVX2_SABER_un_pack11bit(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 11) / 8; + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = offset_byte1 + 11 * j; + offset_data = 8 * j; + + data[i][offset_data + 0] = (bytes[offset_byte + 0]) | ( (bytes[offset_byte + 1] & 0x07) << 8 ); + + data[i][offset_data + 1] = ( (bytes[offset_byte + 1] >> 3) & 0x1f) | ( (bytes[offset_byte + 2] & 0x3f) << 5 ); + + data[i][offset_data + 2] = ( (bytes[offset_byte + 2] >> 6) & 0x03) | ( (bytes[offset_byte + 3] & 0xff) << 2 ) | ( (bytes[offset_byte + 4] & 0x01) << 10 ); + + data[i][offset_data + 3] = ( (bytes[offset_byte + 4] >> 1) & 0x7f) | ( (bytes[offset_byte + 5] & 0x0f) << 7 ); + + data[i][offset_data + 4] = ( (bytes[offset_byte + 5] >> 4) & 0x0f) | ( (bytes[offset_byte + 6] & 0x7f) << 4 ); + + data[i][offset_data + 5] = ( (bytes[offset_byte + 6] >> 7) & 0x01) | ( (bytes[offset_byte + 7] & 0xff) << 1 ) | ( (bytes[offset_byte + 8] & 0x03) << 9 ); + + data[i][offset_data + 6] = ( (bytes[offset_byte + 8] >> 2) & 0x3f) | ( (bytes[offset_byte + 9] & 0x1f) << 6 ); + + data[i][offset_data + 7] = ( (bytes[offset_byte + 9] >> 5) & 0x07) | ( (bytes[offset_byte + 10] & 0xff) << 3 ); + } + } + + +} + +void PQCLEAN_LIGHTSABER_AVX2_SABER_pack14bit(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 14) / 8; + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = offset_byte1 + 7 * j; + offset_data = 4 * j; + bytes[offset_byte + 0] = ( data[i][ offset_data + 0 ] & (0xff)); + + bytes[offset_byte + 1] = ( (data[i][ offset_data + 0 ] >> 8) & 0x3f ) | ((data[i][ offset_data + 1 ] & 0x03) << 6); + + bytes[offset_byte + 2] = ( (data[i][ offset_data + 1 ] >> 2) & 0xff ); + + bytes[offset_byte + 3] = ( (data[i][ offset_data + 1 ] >> 10) & 0x0f ) | ((data[i][ offset_data + 2 ] & 0x0f) << 4); + + bytes[offset_byte + 4] = ( (data[i][ offset_data + 2 ] >> 4) & 0xff ); + + bytes[offset_byte + 5] = ( (data[i][ offset_data + 2 ] >> 12) & 0x03 ) | ((data[i][ offset_data + 3 ] & 0x3f) << 2); + + bytes[offset_byte + 6] = ( (data[i][ offset_data + 3 ] >> 6) & 0xff ); + } + } + + +} + + +void PQCLEAN_LIGHTSABER_AVX2_SABER_un_pack14bit(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 14) / 8; + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = offset_byte1 + 7 * j; + offset_data = 4 * j; + data[i][offset_data + 0] = (bytes[offset_byte + 0] & 0xff) | ( (bytes[offset_byte + 1] & 0x3f) << 8 ); + + data[i][offset_data + 1] = ( (bytes[offset_byte + 1] >> 6) & 0x03) | ((bytes[offset_byte + 2] & 0xff) << 2 ) | ( (bytes[offset_byte + 3] & 0x0f) << 10 ); + + data[i][offset_data + 2] = ( (bytes[offset_byte + 3] >> 4) & 0x0f) | ( (bytes[offset_byte + 4] ) << 4 ) | ( (bytes[offset_byte + 5] & 0x03) << 12 ); + + data[i][offset_data + 3] = ( (bytes[offset_byte + 5] >> 2) & 0x3f) | ( (bytes[offset_byte + 6] ) << 6 ); + } + } + + +} + +void PQCLEAN_LIGHTSABER_AVX2_POLVEC2BS(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N], uint16_t modulus) { + + if (modulus == 1024) { + PQCLEAN_LIGHTSABER_AVX2_POLVECp2BS(bytes, data); + } else if (modulus == 8192) { + PQCLEAN_LIGHTSABER_AVX2_POLVECq2BS(bytes, data); + } +} + +void PQCLEAN_LIGHTSABER_AVX2_BS2POLVEC(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes, uint16_t modulus) { + + if (modulus == 1024) { + PQCLEAN_LIGHTSABER_AVX2_BS2POLVECp(data, bytes); + } else if (modulus == 8192) { + PQCLEAN_LIGHTSABER_AVX2_BS2POLVECq(data, bytes); + } + +} diff --git a/crypto_kem/lightsaber/avx2/pack_unpack.h b/crypto_kem/lightsaber/avx2/pack_unpack.h new file mode 100644 index 00000000..9a5d41f0 --- /dev/null +++ b/crypto_kem/lightsaber/avx2/pack_unpack.h @@ -0,0 +1,56 @@ +#ifndef PACK_UNPACK_H +#define PACK_UNPACK_H +#include "SABER_params.h" +#include +#include + +void PQCLEAN_LIGHTSABER_AVX2_BS2POLq(uint16_t data[SABER_N], const uint8_t *bytes); + +void PQCLEAN_LIGHTSABER_AVX2_BS2POLVEC(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes, uint16_t modulus); + +void PQCLEAN_LIGHTSABER_AVX2_BS2POLVECq(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes); + +void PQCLEAN_LIGHTSABER_AVX2_BS2POLVECp(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes); + + +void PQCLEAN_LIGHTSABER_AVX2_POLVEC2BS(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N], uint16_t modulus); + +void PQCLEAN_LIGHTSABER_AVX2_POLVECq2BS(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]); + +void PQCLEAN_LIGHTSABER_AVX2_POLVECp2BS(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]); + + +void PQCLEAN_LIGHTSABER_AVX2_SABER_pack_3bit(uint8_t *bytes, const uint16_t *data); + +void PQCLEAN_LIGHTSABER_AVX2_SABER_pack_4bit(uint8_t *bytes, const uint16_t *data); + +void PQCLEAN_LIGHTSABER_AVX2_SABER_pack_6bit(uint8_t *bytes, const uint16_t *data); + +void PQCLEAN_LIGHTSABER_AVX2_SABER_pack10bit(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]); + +void PQCLEAN_LIGHTSABER_AVX2_SABER_pack11bit(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]); + +void PQCLEAN_LIGHTSABER_AVX2_SABER_pack13bit(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]); + +void PQCLEAN_LIGHTSABER_AVX2_SABER_pack14bit(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]); + + +void PQCLEAN_LIGHTSABER_AVX2_SABER_poly_un_pack13bit(uint16_t data[SABER_N], const uint8_t *bytes); + + +void PQCLEAN_LIGHTSABER_AVX2_SABER_un_pack3bit(uint16_t *data, const uint8_t *bytes); + +void PQCLEAN_LIGHTSABER_AVX2_SABER_un_pack4bit(uint16_t *data, const uint8_t *bytes); + +void PQCLEAN_LIGHTSABER_AVX2_SABER_un_pack6bit(uint16_t *data, const uint8_t *bytes); + +void PQCLEAN_LIGHTSABER_AVX2_SABER_un_pack10bit(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes); + +void PQCLEAN_LIGHTSABER_AVX2_SABER_un_pack11bit(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes); + +void PQCLEAN_LIGHTSABER_AVX2_SABER_un_pack13bit(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes); + +void PQCLEAN_LIGHTSABER_AVX2_SABER_un_pack14bit(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes); + + +#endif diff --git a/crypto_kem/lightsaber/avx2/poly.h b/crypto_kem/lightsaber/avx2/poly.h new file mode 100644 index 00000000..8f2a7574 --- /dev/null +++ b/crypto_kem/lightsaber/avx2/poly.h @@ -0,0 +1,27 @@ +#ifndef POLY_H +#define POLY_H +/*--------------------------------------------------------------------- +This file has been adapted from the implementation +(available at, Public Domain https://github.com/pq-crystals/kyber) +of "CRYSTALS – Kyber: a CCA-secure module-lattice-based KEM" +by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint, +Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle +----------------------------------------------------------------------*/ +#include "SABER_params.h" +#include + +typedef struct { + uint16_t coeffs[SABER_N]; +} poly; + +typedef struct { + poly vec[SABER_K]; +} polyvec; + +void PQCLEAN_LIGHTSABER_AVX2_poly_getnoise(uint16_t *r, const unsigned char *seed, unsigned char nonce); + + +void PQCLEAN_LIGHTSABER_AVX2_poly_getnoise4x(uint16_t *r0, uint16_t *r1, uint16_t *r2, const unsigned char *seed, unsigned char nonce0, unsigned char nonce1, unsigned char nonce2, unsigned char nonce3); + + +#endif diff --git a/crypto_kem/lightsaber/avx2/polymul/consts.h b/crypto_kem/lightsaber/avx2/polymul/consts.h new file mode 100644 index 00000000..40826398 --- /dev/null +++ b/crypto_kem/lightsaber/avx2/polymul/consts.h @@ -0,0 +1,20 @@ +#include "../SABER_params.h" + +#define AVX_N (SABER_N >> 4) +#define small_len_avx (AVX_N >> 2) + +#define SCHB_N 16 + +#define N_SB (SABER_N >> 2) +#define N_SB_RES (2*N_SB-1) + +#define N_SB_16 (N_SB >> 2) +#define N_SB_16_RES (2*N_SB_16-1) + +#define AVX_N1 16 /*N/16*/ + +#define SCM_SIZE 16 + +// The dimension of a vector. i.e vector has NUM_POLY elements and Matrix has NUM_POLY X NUM_POLY elements +#define NUM_POLY SABER_K +//int NUM_POLY=2; diff --git a/crypto_kem/lightsaber/avx2/polymul/matrix.c b/crypto_kem/lightsaber/avx2/polymul/matrix.c new file mode 100644 index 00000000..5fa35783 --- /dev/null +++ b/crypto_kem/lightsaber/avx2/polymul/matrix.c @@ -0,0 +1,303 @@ +#include + +static void transpose_n1(__m256i *M) +{ + //int i; + register __m256i r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11; + register __m256i temp, temp0, temp1, temp2; + + //for(i=0; i<8; i=i+1) + //{ + r0 = _mm256_unpacklo_epi16(M[0], M[1]); + r1 = _mm256_unpacklo_epi16(M[2], M[3]); + r2 = _mm256_unpacklo_epi16(M[4], M[5]); + r3 = _mm256_unpacklo_epi16(M[6], M[7]); + r4 = _mm256_unpacklo_epi16(M[8], M[9]); + r5 = _mm256_unpacklo_epi16(M[10], M[11]); + r6 = _mm256_unpacklo_epi16(M[12], M[13]); + r7 = _mm256_unpacklo_epi16(M[14], M[15]); + + + temp = _mm256_unpacklo_epi32(r0, r1); + temp0 = _mm256_unpacklo_epi32(r2, r3); + temp1 = _mm256_unpacklo_epi32(r4, r5); + temp2 = _mm256_unpacklo_epi32(r6, r7); + + r8 = _mm256_unpackhi_epi32(r0, r1); + r9 = _mm256_unpackhi_epi32(r2, r3); + r10 = _mm256_unpackhi_epi32(r4, r5); + r11 = _mm256_unpackhi_epi32(r6, r7); + + r0 = _mm256_unpacklo_epi64(temp, temp0); + r2 = _mm256_unpackhi_epi64(temp, temp0); + + r1 = _mm256_unpacklo_epi64(temp1, temp2); + r3 = _mm256_unpackhi_epi64(temp1, temp2); + + temp = _mm256_unpackhi_epi16(M[0], M[1]); + temp0 = _mm256_unpackhi_epi16(M[2], M[3]); + temp1 = _mm256_unpackhi_epi16(M[4], M[5]); + temp2 = _mm256_unpackhi_epi16(M[6], M[7]); + r4 = _mm256_unpackhi_epi16(M[8], M[9]); + + M[0] = _mm256_permute2f128_si256(r0, r1, 0x20); + M[8] = _mm256_permute2f128_si256(r0, r1, 0x31); + M[1] = _mm256_permute2f128_si256(r2, r3, 0x20); + M[9] = _mm256_permute2f128_si256(r2, r3, 0x31); + + + r5 = _mm256_unpackhi_epi16(M[10], M[11]); + r6 = _mm256_unpackhi_epi16(M[12], M[13]); + r7 = _mm256_unpackhi_epi16(M[14], M[15]); + + + + r0 = _mm256_unpacklo_epi64(r8, r9); + r1 = _mm256_unpacklo_epi64(r10, r11); + + r2 = _mm256_unpackhi_epi64(r8, r9); + r3 = _mm256_unpackhi_epi64(r10, r11); + + + + M[3] = _mm256_permute2f128_si256(r2, r3, 0x20); + M[11] = _mm256_permute2f128_si256(r2, r3, 0x31); + M[2] = _mm256_permute2f128_si256(r0, r1, 0x20); + M[10] = _mm256_permute2f128_si256(r0, r1, 0x31); + + + //for(i=0; i<4; i=i+1) + //{ + r0 = _mm256_unpacklo_epi32(temp, temp0); + r1 = _mm256_unpacklo_epi32(temp1, temp2); + r2 = _mm256_unpacklo_epi32(r4, r5); + r3 = _mm256_unpacklo_epi32(r6, r7); + + //} + + + //for(i=0; i<2; i=i+1) + //{ + r8 = _mm256_unpacklo_epi64(r0, r1); + r10 = _mm256_unpackhi_epi64(r0, r1); + + r9 = _mm256_unpacklo_epi64(r2, r3); + r11 = _mm256_unpackhi_epi64(r2, r3); + + M[4] = _mm256_permute2f128_si256(r8, r9, 0x20); + M[12] = _mm256_permute2f128_si256(r8, r9, 0x31); + M[5] = _mm256_permute2f128_si256(r10, r11, 0x20); + M[13] = _mm256_permute2f128_si256(r10, r11, 0x31); + + r0 = _mm256_unpackhi_epi32(temp, temp0); + r1 = _mm256_unpackhi_epi32(temp1, temp2); + r2 = _mm256_unpackhi_epi32(r4, r5); + r3 = _mm256_unpackhi_epi32(r6, r7); + + //} +// for(i=0; i<2; i=i+1) +// { + r4 = _mm256_unpacklo_epi64(r0, r1); + r6 = _mm256_unpackhi_epi64(r0, r1); + + r5 = _mm256_unpacklo_epi64(r2, r3); + r7 = _mm256_unpackhi_epi64(r2, r3); + +// } + + //------------------------------------------------------- + + M[6] = _mm256_permute2f128_si256(r4, r5, 0x20); + M[14] = _mm256_permute2f128_si256(r4, r5, 0x31); + M[7] = _mm256_permute2f128_si256(r6, r7, 0x20); + M[15] = _mm256_permute2f128_si256(r6, r7, 0x31); +} + +/* +void transpose_unrolled(__m256i *M) +{ + int i; + __m256i tL[8], tH[8]; + __m256i bL[4], bH[4], cL[4], cH[4]; + __m256i dL[2], dH[2], eL[2], eH[2], fL[2], fH[2], gL[2], gH[2]; + + __m256i r0, r1, r2, r3, r4, r5, r6, r7; + + //for(i=0; i<8; i=i+1) + //{ + tL[0] = _mm256_unpacklo_epi16(M[0], M[1]); + tH[0] = _mm256_unpackhi_epi16(M[0], M[1]); + + tL[1] = _mm256_unpacklo_epi16(M[2], M[3]); + tH[1] = _mm256_unpackhi_epi16(M[2], M[3]); + + tL[2] = _mm256_unpacklo_epi16(M[4], M[5]); + tH[2] = _mm256_unpackhi_epi16(M[4], M[5]); + + tL[3] = _mm256_unpacklo_epi16(M[6], M[7]); + tH[3] = _mm256_unpackhi_epi16(M[6], M[7]); + + tL[4] = _mm256_unpacklo_epi16(M[8], M[9]); + tH[4] = _mm256_unpackhi_epi16(M[8], M[9]); + + tL[5] = _mm256_unpacklo_epi16(M[10], M[11]); + tH[5] = _mm256_unpackhi_epi16(M[10], M[11]); + + tL[6] = _mm256_unpacklo_epi16(M[12], M[13]); + tH[6] = _mm256_unpackhi_epi16(M[12], M[13]); + + tL[7] = _mm256_unpacklo_epi16(M[14], M[15]); + tH[7] = _mm256_unpackhi_epi16(M[14], M[15]); + + //} + + //------------------------------------------------------- + //for(i=0; i<4; i=i+1) + //{ + bL[0] = _mm256_unpacklo_epi32(tL[0], tL[1]); + bH[0] = _mm256_unpackhi_epi32(tL[0], tL[1]); + + bL[1] = _mm256_unpacklo_epi32(tL[2], tL[3]); + bH[1] = _mm256_unpackhi_epi32(tL[2], tL[3]); + + bL[2] = _mm256_unpacklo_epi32(tL[4], tL[5]); + bH[2] = _mm256_unpackhi_epi32(tL[4], tL[5]); + + bL[3] = _mm256_unpacklo_epi32(tL[6], tL[7]); + bH[3] = _mm256_unpackhi_epi32(tL[6], tL[7]); + + //} + + //for(i=0; i<2; i=i+1) + //{ + dL[0] = _mm256_unpacklo_epi64(bL[0], bL[1]); + dH[0] = _mm256_unpackhi_epi64(bL[0], bL[1]); + + dL[1] = _mm256_unpacklo_epi64(bL[2], bL[3]); + dH[1] = _mm256_unpackhi_epi64(bL[2], bL[3]); + + M[0] = _mm256_permute2f128_si256(dL[0], dL[1], 0x20); + M[8] = _mm256_permute2f128_si256(dL[0], dL[1], 0x31); + M[1] = _mm256_permute2f128_si256(dH[0], dH[1], 0x20); + M[9] = _mm256_permute2f128_si256(dH[0], dH[1], 0x31); + + //} + //for(i=0; i<2; i=i+1) + //{ + eL[0] = _mm256_unpacklo_epi64(bH[0], bH[1]); + eH[0] = _mm256_unpackhi_epi64(bH[0], bH[1]); + + eL[1] = _mm256_unpacklo_epi64(bH[2], bH[3]); + eH[1] = _mm256_unpackhi_epi64(bH[2], bH[3]); + + //} + + //------------------------------------------------------- + + //------------------------------------------------------- + for(i=0; i<4; i=i+1) + { + cL[i] = _mm256_unpacklo_epi32(tH[2*i], tH[2*i+1]); + cH[i] = _mm256_unpackhi_epi32(tH[2*i], tH[2*i+1]); + } + + + for(i=0; i<2; i=i+1) + { + fL[i] = _mm256_unpacklo_epi64(cL[2*i], cL[2*i+1]); + fH[i] = _mm256_unpackhi_epi64(cL[2*i], cL[2*i+1]); + } + for(i=0; i<2; i=i+1) + { + gL[i] = _mm256_unpacklo_epi64(cH[2*i], cH[2*i+1]); + gH[i] = _mm256_unpackhi_epi64(cH[2*i], cH[2*i+1]); + } + + //------------------------------------------------------- + + + + M[2] = _mm256_permute2f128_si256(eL[0], eL[1], 0x20); + M[10] = _mm256_permute2f128_si256(eL[0], eL[1], 0x31); + M[3] = _mm256_permute2f128_si256(eH[0], eH[1], 0x20); + M[11] = _mm256_permute2f128_si256(eH[0], eH[1], 0x31); + + M[4] = _mm256_permute2f128_si256(fL[0], fL[1], 0x20); + M[12] = _mm256_permute2f128_si256(fL[0], fL[1], 0x31); + M[5] = _mm256_permute2f128_si256(fH[0], fH[1], 0x20); + M[13] = _mm256_permute2f128_si256(fH[0], fH[1], 0x31); + + M[6] = _mm256_permute2f128_si256(gL[0], gL[1], 0x20); + M[14] = _mm256_permute2f128_si256(gL[0], gL[1], 0x31); + M[7] = _mm256_permute2f128_si256(gH[0], gH[1], 0x20); + M[15] = _mm256_permute2f128_si256(gH[0], gH[1], 0x31); +} + + +void transpose1(__m256i *M) +{ + int i; + __m256i tL[8], tH[8]; + __m256i bL[4], bH[4], cL[4], cH[4]; + __m256i dL[2], dH[2], eL[2], eH[2], fL[2], fH[2], gL[2], gH[2]; + + for(i=0; i<8; i=i+1) + { + tL[i] = _mm256_unpacklo_epi16(M[2*i], M[2*i+1]); + tH[i] = _mm256_unpackhi_epi16(M[2*i], M[2*i+1]); + } + + for(i=0; i<4; i=i+1) + { + bL[i] = _mm256_unpacklo_epi32(tL[2*i], tL[2*i+1]); + bH[i] = _mm256_unpackhi_epi32(tL[2*i], tL[2*i+1]); + } + for(i=0; i<4; i=i+1) + { + cL[i] = _mm256_unpacklo_epi32(tH[2*i], tH[2*i+1]); + cH[i] = _mm256_unpackhi_epi32(tH[2*i], tH[2*i+1]); + } + + for(i=0; i<2; i=i+1) + { + dL[i] = _mm256_unpacklo_epi64(bL[2*i], bL[2*i+1]); + dH[i] = _mm256_unpackhi_epi64(bL[2*i], bL[2*i+1]); + } + for(i=0; i<2; i=i+1) + { + eL[i] = _mm256_unpacklo_epi64(bH[2*i], bH[2*i+1]); + eH[i] = _mm256_unpackhi_epi64(bH[2*i], bH[2*i+1]); + } + + for(i=0; i<2; i=i+1) + { + fL[i] = _mm256_unpacklo_epi64(cL[2*i], cL[2*i+1]); + fH[i] = _mm256_unpackhi_epi64(cL[2*i], cL[2*i+1]); + } + for(i=0; i<2; i=i+1) + { + gL[i] = _mm256_unpacklo_epi64(cH[2*i], cH[2*i+1]); + gH[i] = _mm256_unpackhi_epi64(cH[2*i], cH[2*i+1]); + } + + M[0] = _mm256_permute2f128_si256(dL[0], dL[1], 0x20); + M[8] = _mm256_permute2f128_si256(dL[0], dL[1], 0x31); + M[1] = _mm256_permute2f128_si256(dH[0], dH[1], 0x20); + M[9] = _mm256_permute2f128_si256(dH[0], dH[1], 0x31); + + M[2] = _mm256_permute2f128_si256(eL[0], eL[1], 0x20); + M[10] = _mm256_permute2f128_si256(eL[0], eL[1], 0x31); + M[3] = _mm256_permute2f128_si256(eH[0], eH[1], 0x20); + M[11] = _mm256_permute2f128_si256(eH[0], eH[1], 0x31); + + M[4] = _mm256_permute2f128_si256(fL[0], fL[1], 0x20); + M[12] = _mm256_permute2f128_si256(fL[0], fL[1], 0x31); + M[5] = _mm256_permute2f128_si256(fH[0], fH[1], 0x20); + M[13] = _mm256_permute2f128_si256(fH[0], fH[1], 0x31); + + M[6] = _mm256_permute2f128_si256(gL[0], gL[1], 0x20); + M[14] = _mm256_permute2f128_si256(gL[0], gL[1], 0x31); + M[7] = _mm256_permute2f128_si256(gH[0], gH[1], 0x20); + M[15] = _mm256_permute2f128_si256(gH[0], gH[1], 0x31); +} +*/ diff --git a/crypto_kem/lightsaber/avx2/polymul/scm_avx.c b/crypto_kem/lightsaber/avx2/polymul/scm_avx.c new file mode 100644 index 00000000..4e4f11f8 --- /dev/null +++ b/crypto_kem/lightsaber/avx2/polymul/scm_avx.c @@ -0,0 +1,753 @@ +//#define SCM_SIZE 16 + +//#pragma STDC FP_CONTRACT ON + +#include + +inline __m256i mul_add(__m256i a, __m256i b, __m256i c) { + return _mm256_add_epi16(_mm256_mullo_epi16(a, b), c); +} + + +static void schoolbook_avx_new3_acc(__m256i* a, __m256i* b, __m256i* c_avx) ////8 coefficients of a and b has been prefetched + //the c_avx are added cummulatively +{ + + register __m256i a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7; + register __m256i temp; + + + a0=a[0]; + a1=a[1]; + a2=a[2]; + a3=a[3]; + a4=a[4]; + a5=a[5]; + a6=a[6]; + a7=a[7]; + + b0=b[0]; + b1=b[1]; + b2=b[2]; + b3=b[3]; + b4=b[4]; + b5=b[5]; + b6=b[6]; + b7=b[7]; + + // New Unrolled first triangle + + //otherwise accumulate + c_avx[0] = mul_add(a0, b0, c_avx[0]); + + + temp = _mm256_mullo_epi16 (a0, b1); + temp=mul_add(a1, b0, temp); + c_avx[1] = _mm256_add_epi16(temp, c_avx[1]); + + + temp = _mm256_mullo_epi16 (a0, b2); + temp = mul_add(a1, b1, temp); + temp=mul_add(a2, b0, temp); + c_avx[2] = _mm256_add_epi16(temp, c_avx[2]); + + + temp = _mm256_mullo_epi16 (a0, b3); + temp = mul_add(a1, b2, temp); + temp = mul_add(a2, b1, temp); + temp=mul_add(a3, b0, temp); + c_avx[3] = _mm256_add_epi16(temp, c_avx[3]); + + temp = _mm256_mullo_epi16 (a0, b4); + temp = mul_add(a1, b3, temp); + temp = mul_add(a3, b1, temp); + temp = mul_add(a4, b0, temp); + temp=mul_add(a2, b2, temp); + c_avx[4] = _mm256_add_epi16(temp, c_avx[4]); + + + temp = _mm256_mullo_epi16 (a0, b5); + temp = mul_add(a1, b4 , temp); + temp = mul_add(a2, b3, temp); + temp = mul_add(a3, b2, temp); + temp = mul_add( a4, b1, temp); + temp=mul_add(a5, b0, temp); + c_avx[5] = _mm256_add_epi16(temp, c_avx[5]); + + temp = _mm256_mullo_epi16 (a0, b6); + temp = mul_add(a1, b5, temp); + temp = mul_add(a5, b1, temp); + temp = mul_add(a6, b0, temp); + temp = mul_add(a2, b4, temp); + temp = mul_add(a3, b3, temp); + temp=mul_add(a4, b2, temp); + c_avx[6] = _mm256_add_epi16(temp, c_avx[6]); + + + temp = _mm256_mullo_epi16 (a0, b7); + temp = mul_add(a1, b6, temp); + temp = mul_add (a6, b1, temp); + temp = mul_add (a7, b0, temp); + temp = mul_add(a2, b5, temp); + temp = mul_add (a3, b4, temp); + temp = mul_add (a4, b3, temp); + temp=mul_add(a5, b2, temp); + c_avx[7] = _mm256_add_epi16(temp, c_avx[7]); + + temp = _mm256_mullo_epi16 (a0, b[8]); + temp = mul_add (a1, b7, temp); + temp = mul_add (a7, b1, temp); + temp = mul_add (a[8], b0, temp); + temp = mul_add (a2, b6,temp); + temp = mul_add(a3, b5, temp); + temp = mul_add (a4, b4,temp); + temp = mul_add (a5, b3, temp); + + temp=mul_add(a6, b2, temp); + c_avx[8] = _mm256_add_epi16(temp, c_avx[8]); + + + temp = _mm256_mullo_epi16 (a0, b[9]); + temp = mul_add (a1, b[8], temp); + temp = mul_add (a[8], b1, temp); + temp = mul_add (a[9], b0, temp); + temp = mul_add (a2, b7, temp); + temp = mul_add (a3, b6, temp); + temp = mul_add (a4, b5, temp); + temp = mul_add (a5, b4, temp); + temp = mul_add (a6, b3, temp); + temp=mul_add(a7, b2, temp); + c_avx[9] = _mm256_add_epi16(temp, c_avx[9]); + + + temp= _mm256_mullo_epi16 (a0, b[10]); + temp = mul_add (a1, b[9], temp); + temp = mul_add (a[9], b1, temp); + temp = mul_add (a[10], b0, temp); + temp = mul_add (a2, b[8], temp); + temp = mul_add (a3, b7, temp); + temp = mul_add (a4, b6, temp); + temp = mul_add (a5, b5, temp); + temp = mul_add (a6, b4, temp); + temp = mul_add (a7, b3, temp); + temp=mul_add(a[8], b2, temp); + c_avx[10] = _mm256_add_epi16(temp, c_avx[10]); + + + temp = _mm256_mullo_epi16 (a0, b[11]); + temp = mul_add (a1, b[10], temp ); + temp = mul_add (a[10], b1, temp ); + temp = mul_add (a[11], b0, temp ); + temp = mul_add (a2, b[9], temp ); + temp = mul_add (a3, b[8], temp ); + temp = mul_add (a4, b7, temp ); + temp = mul_add (a5, b6, temp ); + temp = mul_add (a6, b5, temp ); + temp = mul_add (a7, b4, temp ); + temp = mul_add (a[8], b3, temp ); + temp=mul_add(a[9], b2, temp); + c_avx[11] = _mm256_add_epi16(temp, c_avx[11]); + + + temp = _mm256_mullo_epi16 (a0, b[12]); + temp = mul_add (a1, b[11], temp); + temp = mul_add (a[11], b1, temp); + temp = mul_add (a[12], b0, temp); + temp = mul_add (a2, b[10], temp); + temp = mul_add (a3, b[9], temp); + temp = mul_add (a4, b[8], temp); + temp = mul_add (a5, b7, temp); + temp = mul_add (a6, b6, temp); + temp = mul_add (a7, b5, temp); + temp = mul_add (a[8], b4, temp); + temp = mul_add (a[9], b3, temp); + temp=mul_add(a[10], b2, temp); + c_avx[12] = _mm256_add_epi16(temp, c_avx[12]); + + + temp = _mm256_mullo_epi16 (a0, b[13]); + temp = mul_add (a1, b[12], temp ); + temp = mul_add (a[12], b1, temp ); + temp = mul_add (a[13], b0, temp ); + temp = mul_add (a2, b[11], temp ); + temp = mul_add (a3, b[10], temp ); + temp = mul_add (a4, b[9], temp ); + temp = mul_add (a5, b[8], temp ); + temp = mul_add (a6, b7, temp ); + temp = mul_add (a7, b6, temp ); + temp = mul_add (a[8], b5, temp ); + temp = mul_add (a[9], b4, temp ); + temp = mul_add (a[10], b3, temp ); + temp=mul_add(a[11], b2, temp); + c_avx[13] = _mm256_add_epi16(temp, c_avx[13]); + + + + temp = _mm256_mullo_epi16 (a0, b[14]); + temp = mul_add (a1, b[13], temp ); + temp = mul_add (a[13], b1, temp ); + temp = mul_add (a[14], b0, temp ); + temp = mul_add (a2, b[12], temp ); + temp = mul_add (a3, b[11], temp ); + temp = mul_add (a4, b[10], temp ); + temp = mul_add (a5, b[9], temp ); + temp = mul_add (a6, b[8], temp ); + temp = mul_add (a7, b7, temp ); + temp = mul_add (a[8], b6, temp ); + temp = mul_add (a[9], b5, temp ); + temp = mul_add (a[10], b4, temp ); + temp = mul_add (a[11], b3, temp ); + temp=mul_add(a[12], b2, temp); + c_avx[14] = _mm256_add_epi16(temp, c_avx[14]); + + + temp = _mm256_mullo_epi16 (a0, b[15]); + temp = mul_add (a1, b[14], temp ); + temp = mul_add (a[14], b1, temp ); + temp = mul_add (a[15], b0, temp ); + temp = mul_add (a2, b[13], temp ); + temp = mul_add (a3, b[12], temp ); + temp = mul_add (a4, b[11], temp ); + temp = mul_add (a5, b[10], temp ); + temp = mul_add (a6, b[9], temp ); + temp = mul_add (a7, b[8], temp ); + temp = mul_add (a[8], b7, temp ); + temp = mul_add (a[9], b6, temp ); + temp = mul_add (a[10], b5, temp ); + temp = mul_add (a[11], b4, temp ); + temp = mul_add (a[12], b3, temp ); + temp=mul_add(a[13], b2, temp); + c_avx[15] = _mm256_add_epi16(temp, c_avx[15]); + + + // unrolled second triangle + a0=a[14]; + a1=a[15]; + a2=a[13]; + a3=a[12]; + a4=a[11]; + a5=a[10]; + a6=a[9]; + a7=a[8]; + + b0=b[14]; + b1=b[15]; + b2=b[13]; + b3=b[12]; + b4=b[11]; + b5=b[10]; + b6=b[9]; + b7=b[8]; + + temp = _mm256_mullo_epi16 (a[1], b1); + temp = mul_add (a[2], b0, temp ); + temp = mul_add (a[3], b2, temp ); + temp = mul_add (a[4], b3, temp ); + temp = mul_add (a[5], b4, temp ); + temp = mul_add (a[6], b5, temp ); + temp = mul_add (a[7], b6, temp ); + temp = mul_add (a7, b7, temp ); + temp = mul_add (a6, b[7], temp ); + temp = mul_add (a5, b[6], temp ); + temp = mul_add (a4, b[5], temp ); + temp = mul_add (a3, b[4], temp ); + temp = mul_add (a2, b[3], temp ); + temp = mul_add (a0, b[2], temp ); + temp=mul_add(a1, b[1], temp); + c_avx[16] = _mm256_add_epi16(temp, c_avx[16]); + + + temp = _mm256_mullo_epi16 (a[2], b1); + temp = mul_add (a[3], b0, temp ); + temp = mul_add (a[4], b2, temp ); + temp = mul_add (a[5], b3, temp ); + temp = mul_add (a[6], b4, temp ); + temp = mul_add (a[7], b5, temp ); + temp = mul_add (a7, b6, temp ); + temp = mul_add (a6, b7, temp ); + temp = mul_add (a5, b[7], temp ); + temp = mul_add (a4, b[6], temp ); + temp = mul_add (a3, b[5], temp ); + temp = mul_add (a2, b[4], temp ); + temp = mul_add (a0, b[3], temp ); + temp=mul_add(a1, b[2], temp); + c_avx[17] = _mm256_add_epi16(temp, c_avx[17]); + + + temp = _mm256_mullo_epi16 (a[3], b1); + temp = mul_add (a[4], b0, temp ); + temp = mul_add (a[5], b2, temp ); + temp = mul_add (a[6], b3, temp ); + temp = mul_add (a[7], b4, temp ); + temp = mul_add (a7, b5, temp ); + temp = mul_add (a6, b6, temp ); + temp = mul_add (a5, b7, temp ); + temp = mul_add (a4, b[7], temp ); + temp = mul_add (a3, b[6], temp ); + temp = mul_add (a2, b[5], temp ); + temp = mul_add (a0, b[4], temp ); + temp=mul_add(a1, b[3], temp); + c_avx[18] = _mm256_add_epi16(temp, c_avx[18]); + + + temp = _mm256_mullo_epi16 (a[4], b1); + temp = mul_add (a[5], b0, temp ); + temp = mul_add (a[6], b2, temp ); + temp = mul_add (a[7], b3, temp ); + temp = mul_add (a7, b4, temp ); + temp = mul_add (a6, b5, temp ); + temp = mul_add (a5, b6, temp ); + temp = mul_add (a4, b7, temp ); + temp = mul_add (a3, b[7], temp ); + temp = mul_add (a2, b[6], temp ); + temp = mul_add (a0, b[5], temp ); + temp=mul_add(a1, b[4], temp); + c_avx[19] = _mm256_add_epi16(temp, c_avx[19]); + + + temp = _mm256_mullo_epi16 (a[5], b1); + temp = mul_add (a[6], b0, temp ); + temp = mul_add (a[7], b2, temp ); + temp = mul_add (a7, b3, temp ); + temp = mul_add (a6, b4, temp ); + temp = mul_add (a5, b5, temp ); + temp = mul_add (a4, b6, temp ); + temp = mul_add (a3, b7, temp ); + temp = mul_add (a2, b[7], temp ); + temp = mul_add (a0, b[6], temp ); + temp=mul_add(a1, b[5], temp); + c_avx[20] = _mm256_add_epi16(temp, c_avx[20]); + + + temp = _mm256_mullo_epi16 (a[6], b1); + temp = mul_add (a[7], b0, temp ); + temp = mul_add (a7, b2, temp ); + temp = mul_add (a6, b3, temp ); + temp = mul_add (a5, b4, temp ); + temp = mul_add (a4, b5, temp ); + temp = mul_add (a3, b6, temp ); + temp = mul_add (a2, b7, temp ); + temp = mul_add (a0, b[7], temp ); + temp=mul_add(a1, b[6], temp); + c_avx[21] = _mm256_add_epi16(temp, c_avx[21]); + + + temp = _mm256_mullo_epi16 (a[7], b1); + temp = mul_add (a7, b0, temp ); + temp = mul_add (a6, b2, temp ); + temp = mul_add (a5, b3, temp ); + temp = mul_add (a4, b4, temp ); + temp = mul_add (a3, b5, temp ); + temp = mul_add (a2, b6, temp ); + temp = mul_add (a0, b7, temp ); + temp=mul_add(a1, b[7], temp); + c_avx[22] = _mm256_add_epi16(temp, c_avx[22]); + + + temp = _mm256_mullo_epi16 (a7, b1); + temp = mul_add (a6, b0, temp ); + temp = mul_add (a5, b2, temp ); + temp = mul_add (a4, b3, temp ); + temp = mul_add (a3, b4, temp ); + temp = mul_add (a2, b5, temp ); + temp = mul_add (a0, b6, temp ); + temp=mul_add(a1, b7, temp); + c_avx[23] = _mm256_add_epi16(temp, c_avx[23]); + + + temp = _mm256_mullo_epi16 (a6, b1); + temp = mul_add (a5, b0, temp ); + temp = mul_add (a4, b2, temp ); + temp = mul_add (a3, b3, temp ); + temp = mul_add (a2, b4, temp ); + temp = mul_add (a0, b5, temp ); + temp=mul_add(a1, b6, temp); + c_avx[24] = _mm256_add_epi16(temp, c_avx[24]); + + + temp = _mm256_mullo_epi16 (a5, b1); + temp = mul_add (a4, b0, temp ); + temp = mul_add (a3, b2, temp ); + temp = mul_add (a2, b3, temp ); + temp = mul_add (a0, b4, temp ); + temp=mul_add(a1, b5, temp); + c_avx[25] = _mm256_add_epi16(temp, c_avx[25]); + + + temp = _mm256_mullo_epi16 (a4, b1); + temp = mul_add (a3, b0, temp ); + temp = mul_add (a2, b2, temp ); + temp = mul_add (a0, b3, temp ); + temp=mul_add(a1, b4, temp); + c_avx[26] = _mm256_add_epi16(temp, c_avx[26]); + + + temp = _mm256_mullo_epi16 (a3, b1); + temp = mul_add (a2, b0, temp ); + temp = mul_add (a0, b2, temp ); + temp=mul_add(a1, b3, temp); + c_avx[27] = _mm256_add_epi16(temp, c_avx[27]); + + + temp = _mm256_mullo_epi16 (a2, b1); + temp = mul_add (a0, b0, temp ); + temp=mul_add(a1, b2, temp); + c_avx[28] = _mm256_add_epi16(temp, c_avx[28]); + + + temp = _mm256_mullo_epi16 (a0, b1); + temp=mul_add(a1, b0, temp); + c_avx[29] = _mm256_add_epi16(temp, c_avx[29]); + + + c_avx[30] = mul_add(a1, b1, c_avx[30]); + + + + c_avx[2*SCM_SIZE-1] = _mm256_set_epi64x(0, 0, 0, 0); + + +} + + + +static void schoolbook_avx_new2(__m256i* a, __m256i* b, __m256i* c_avx) ////8 coefficients of a and b has been prefetched + //the c_avx are not added cummulatively +{ + + __m256i a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7; + __m256i temp; + + + a0=a[0]; + a1=a[1]; + a2=a[2]; + a3=a[3]; + a4=a[4]; + a5=a[5]; + a6=a[6]; + a7=a[7]; + + b0=b[0]; + b1=b[1]; + b2=b[2]; + b3=b[3]; + b4=b[4]; + b5=b[5]; + b6=b[6]; + b7=b[7]; + + // New Unrolled first triangle + c_avx[0] = _mm256_mullo_epi16 (a0, b0); + + temp = _mm256_mullo_epi16 (a0, b1); + c_avx[1]=mul_add(a1, b0, temp); + + temp = _mm256_mullo_epi16 (a0, b2); + + temp = mul_add(a1, b1, temp); + c_avx[2]= mul_add(a2, b0, temp); + + temp = _mm256_mullo_epi16 (a0, b3); + temp = mul_add(a1, b2, temp); + temp = mul_add(a2, b1, temp); + c_avx[3]= mul_add(a3, b0, temp); + + temp = _mm256_mullo_epi16 (a0, b4); + temp = mul_add(a1, b3, temp); + temp = mul_add(a3, b1, temp); + temp = mul_add(a4, b0, temp); + c_avx[4]= mul_add(a2, b2, temp); + + temp = _mm256_mullo_epi16 (a0, b5); + temp = mul_add(a1, b4 , temp); + temp = mul_add(a2, b3, temp); + temp = mul_add(a3, b2, temp); + temp = mul_add( a4, b1, temp); + c_avx[5] = mul_add(a5, b0, temp); + + temp = _mm256_mullo_epi16 (a0, b6); + temp = mul_add(a1, b5, temp); + temp = mul_add(a5, b1, temp); + temp = mul_add(a6, b0, temp); + temp = mul_add(a2, b4, temp); + temp = mul_add(a3, b3, temp); + c_avx[6] = mul_add(a4, b2, temp); + + temp = _mm256_mullo_epi16 (a0, b7); + temp = mul_add(a1, b6, temp); + temp = mul_add (a6, b1, temp); + temp = mul_add (a7, b0, temp); + temp = mul_add(a2, b5, temp); + temp = mul_add (a3, b4, temp); + temp = mul_add (a4, b3, temp); + c_avx[7] = mul_add (a5, b2, temp); + + temp = _mm256_mullo_epi16 (a0, b[8]); + temp = mul_add (a1, b7, temp); + temp = mul_add (a7, b1, temp); + temp = mul_add (a[8], b0, temp); + temp = mul_add (a2, b6,temp); + temp = mul_add(a3, b5, temp); + temp = mul_add (a4, b4,temp); + temp = mul_add (a5, b3, temp); + c_avx[8] = mul_add (a6, b2, temp); + + temp = _mm256_mullo_epi16 (a0, b[9]); + temp = mul_add (a1, b[8], temp); + temp = mul_add (a[8], b1, temp); + temp = mul_add (a[9], b0, temp); + temp = mul_add (a2, b7, temp); + temp = mul_add (a3, b6, temp); + temp = mul_add (a4, b5, temp); + temp = mul_add (a5, b4, temp); + temp = mul_add (a6, b3, temp); + c_avx[9] = mul_add (a7, b2, temp); + + temp= _mm256_mullo_epi16 (a0, b[10]); + temp = mul_add (a1, b[9], temp); + temp = mul_add (a[9], b1, temp); + temp = mul_add (a[10], b0, temp); + temp = mul_add (a2, b[8], temp); + temp = mul_add (a3, b7, temp); + temp = mul_add (a4, b6, temp); + temp = mul_add (a5, b5, temp); + temp = mul_add (a6, b4, temp); + temp = mul_add (a7, b3, temp); + c_avx[10] = mul_add (a[8], b2, temp); + + temp = _mm256_mullo_epi16 (a0, b[11]); + temp = mul_add (a1, b[10], temp ); + temp = mul_add (a[10], b1, temp ); + temp = mul_add (a[11], b0, temp ); + temp = mul_add (a2, b[9], temp ); + temp = mul_add (a3, b[8], temp ); + temp = mul_add (a4, b7, temp ); + temp = mul_add (a5, b6, temp ); + temp = mul_add (a6, b5, temp ); + temp = mul_add (a7, b4, temp ); + temp = mul_add (a[8], b3, temp ); + c_avx[11] = mul_add (a[9], b2, temp ); + + temp = _mm256_mullo_epi16 (a0, b[12]); + temp = mul_add (a1, b[11], temp); + temp = mul_add (a[11], b1, temp); + temp = mul_add (a[12], b0, temp); + temp = mul_add (a2, b[10], temp); + temp = mul_add (a3, b[9], temp); + temp = mul_add (a4, b[8], temp); + temp = mul_add (a5, b7, temp); + temp = mul_add (a6, b6, temp); + temp = mul_add (a7, b5, temp); + temp = mul_add (a[8], b4, temp); + temp = mul_add (a[9], b3, temp); + c_avx[12] = mul_add (a[10], b2, temp); + + temp = _mm256_mullo_epi16 (a0, b[13]); + temp = mul_add (a1, b[12], temp ); + temp = mul_add (a[12], b1, temp ); + temp = mul_add (a[13], b0, temp ); + temp = mul_add (a2, b[11], temp ); + temp = mul_add (a3, b[10], temp ); + temp = mul_add (a4, b[9], temp ); + temp = mul_add (a5, b[8], temp ); + temp = mul_add (a6, b7, temp ); + temp = mul_add (a7, b6, temp ); + temp = mul_add (a[8], b5, temp ); + temp = mul_add (a[9], b4, temp ); + temp = mul_add (a[10], b3, temp ); + c_avx[13] = mul_add (a[11], b2, temp ); + + temp = _mm256_mullo_epi16 (a0, b[14]); + temp = mul_add (a1, b[13], temp ); + temp = mul_add (a[13], b1, temp ); + temp = mul_add (a[14], b0, temp ); + temp = mul_add (a2, b[12], temp ); + temp = mul_add (a3, b[11], temp ); + temp = mul_add (a4, b[10], temp ); + temp = mul_add (a5, b[9], temp ); + temp = mul_add (a6, b[8], temp ); + temp = mul_add (a7, b7, temp ); + temp = mul_add (a[8], b6, temp ); + temp = mul_add (a[9], b5, temp ); + temp = mul_add (a[10], b4, temp ); + temp = mul_add (a[11], b3, temp ); + c_avx[14] = mul_add (a[12], b2, temp ); + + temp = _mm256_mullo_epi16 (a0, b[15]); + temp = mul_add (a1, b[14], temp ); + temp = mul_add (a[14], b1, temp ); + temp = mul_add (a[15], b0, temp ); + temp = mul_add (a2, b[13], temp ); + temp = mul_add (a3, b[12], temp ); + temp = mul_add (a4, b[11], temp ); + temp = mul_add (a5, b[10], temp ); + temp = mul_add (a6, b[9], temp ); + temp = mul_add (a7, b[8], temp ); + temp = mul_add (a[8], b7, temp ); + temp = mul_add (a[9], b6, temp ); + temp = mul_add (a[10], b5, temp ); + temp = mul_add (a[11], b4, temp ); + temp = mul_add (a[12], b3, temp ); + c_avx[15] = mul_add (a[13], b2, temp ); + + + // unrolled second triangle + a0=a[14]; + a1=a[15]; + a2=a[13]; + a3=a[12]; + a4=a[11]; + a5=a[10]; + a6=a[9]; + a7=a[8]; + + b0=b[14]; + b1=b[15]; + b2=b[13]; + b3=b[12]; + b4=b[11]; + b5=b[10]; + b6=b[9]; + b7=b[8]; + + + temp = _mm256_mullo_epi16 (a[1], b1); + temp = mul_add (a[2], b0, temp ); + temp = mul_add (a[3], b2, temp ); + temp = mul_add (a[4], b3, temp ); + temp = mul_add (a[5], b4, temp ); + temp = mul_add (a[6], b5, temp ); + temp = mul_add (a[7], b6, temp ); + temp = mul_add (a7, b7, temp ); + temp = mul_add (a6, b[7], temp ); + temp = mul_add (a5, b[6], temp ); + temp = mul_add (a4, b[5], temp ); + temp = mul_add (a3, b[4], temp ); + temp = mul_add (a2, b[3], temp ); + temp = mul_add (a0, b[2], temp ); + c_avx[16] = mul_add (a1, b[1], temp ); + + temp = _mm256_mullo_epi16 (a[2], b1); + temp = mul_add (a[3], b0, temp ); + temp = mul_add (a[4], b2, temp ); + temp = mul_add (a[5], b3, temp ); + temp = mul_add (a[6], b4, temp ); + temp = mul_add (a[7], b5, temp ); + temp = mul_add (a7, b6, temp ); + temp = mul_add (a6, b7, temp ); + temp = mul_add (a5, b[7], temp ); + temp = mul_add (a4, b[6], temp ); + temp = mul_add (a3, b[5], temp ); + temp = mul_add (a2, b[4], temp ); + temp = mul_add (a0, b[3], temp ); + c_avx[17] = mul_add (a1, b[2], temp ); + + temp = _mm256_mullo_epi16 (a[3], b1); + temp = mul_add (a[4], b0, temp ); + temp = mul_add (a[5], b2, temp ); + temp = mul_add (a[6], b3, temp ); + temp = mul_add (a[7], b4, temp ); + temp = mul_add (a7, b5, temp ); + temp = mul_add (a6, b6, temp ); + temp = mul_add (a5, b7, temp ); + temp = mul_add (a4, b[7], temp ); + temp = mul_add (a3, b[6], temp ); + temp = mul_add (a2, b[5], temp ); + temp = mul_add (a0, b[4], temp ); + c_avx[18] = mul_add (a1, b[3], temp ); + + temp = _mm256_mullo_epi16 (a[4], b1); + temp = mul_add (a[5], b0, temp ); + temp = mul_add (a[6], b2, temp ); + temp = mul_add (a[7], b3, temp ); + temp = mul_add (a7, b4, temp ); + temp = mul_add (a6, b5, temp ); + temp = mul_add (a5, b6, temp ); + temp = mul_add (a4, b7, temp ); + temp = mul_add (a3, b[7], temp ); + temp = mul_add (a2, b[6], temp ); + temp = mul_add (a0, b[5], temp ); + c_avx[19] = mul_add (a1, b[4], temp ); + + temp = _mm256_mullo_epi16 (a[5], b1); + temp = mul_add (a[6], b0, temp ); + temp = mul_add (a[7], b2, temp ); + temp = mul_add (a7, b3, temp ); + temp = mul_add (a6, b4, temp ); + temp = mul_add (a5, b5, temp ); + temp = mul_add (a4, b6, temp ); + temp = mul_add (a3, b7, temp ); + temp = mul_add (a2, b[7], temp ); + temp = mul_add (a0, b[6], temp ); + c_avx[20] = mul_add (a1, b[5], temp ); + + temp = _mm256_mullo_epi16 (a[6], b1); + temp = mul_add (a[7], b0, temp ); + temp = mul_add (a7, b2, temp ); + temp = mul_add (a6, b3, temp ); + temp = mul_add (a5, b4, temp ); + temp = mul_add (a4, b5, temp ); + temp = mul_add (a3, b6, temp ); + temp = mul_add (a2, b7, temp ); + temp = mul_add (a0, b[7], temp ); + c_avx[21] = mul_add (a1, b[6], temp ); + + temp = _mm256_mullo_epi16 (a[7], b1); + temp = mul_add (a7, b0, temp ); + temp = mul_add (a6, b2, temp ); + temp = mul_add (a5, b3, temp ); + temp = mul_add (a4, b4, temp ); + temp = mul_add (a3, b5, temp ); + temp = mul_add (a2, b6, temp ); + temp = mul_add (a0, b7, temp ); + c_avx[22] = mul_add (a1, b[7], temp ); + + temp = _mm256_mullo_epi16 (a7, b1); + temp = mul_add (a6, b0, temp ); + temp = mul_add (a5, b2, temp ); + temp = mul_add (a4, b3, temp ); + temp = mul_add (a3, b4, temp ); + temp = mul_add (a2, b5, temp ); + temp = mul_add (a0, b6, temp ); + c_avx[23] = mul_add (a1, b7, temp ); + + temp = _mm256_mullo_epi16 (a6, b1); + temp = mul_add (a5, b0, temp ); + temp = mul_add (a4, b2, temp ); + temp = mul_add (a3, b3, temp ); + temp = mul_add (a2, b4, temp ); + temp = mul_add (a0, b5, temp ); + c_avx[24] = mul_add (a1, b6, temp ); + + temp = _mm256_mullo_epi16 (a5, b1); + temp = mul_add (a4, b0, temp ); + temp = mul_add (a3, b2, temp ); + temp = mul_add (a2, b3, temp ); + temp = mul_add (a0, b4, temp ); + c_avx[25] = mul_add (a1, b5, temp ); + + temp = _mm256_mullo_epi16 (a4, b1); + temp = mul_add (a3, b0, temp ); + temp = mul_add (a2, b2, temp ); + temp = mul_add (a0, b3, temp ); + c_avx[26] = mul_add (a1, b4, temp ); + + temp = _mm256_mullo_epi16 (a3, b1); + temp = mul_add (a2, b0, temp ); + temp = mul_add (a0, b2, temp ); + c_avx[27] = mul_add (a1, b3, temp ); + + temp = _mm256_mullo_epi16 (a2, b1); + temp = mul_add (a0, b0, temp ); + c_avx[28] = mul_add (a1, b2, temp ); + + temp = _mm256_mullo_epi16 (a0, b1); + c_avx[29] = mul_add (a1, b0, temp); + + c_avx[30] = _mm256_mullo_epi16 (a1, b1); + + + c_avx[2*SCM_SIZE-1] = _mm256_set_epi64x(0, 0, 0, 0); + +} diff --git a/crypto_kem/lightsaber/avx2/polymul/toom-cook_4way.c b/crypto_kem/lightsaber/avx2/polymul/toom-cook_4way.c new file mode 100644 index 00000000..78fb86c2 --- /dev/null +++ b/crypto_kem/lightsaber/avx2/polymul/toom-cook_4way.c @@ -0,0 +1,1010 @@ +/* +Cleaned version for step by step approach look into the _debug file +*/ +//#include "timing.c" +#include "consts.h" +#include "matrix.c" +#include "scm_avx.c" + +static void batch_64coefficient_multiplications_new(__m256i* a, __m256i* b_bucket, __m256i* c_bucket, int f)//all 7 Karatsuba evaluation and interpolation are done in AVX. +{ + __m256i a_bucket[SCM_SIZE*4]; //SCM_SIZE = 16; Holds evaluation (a & b) for 7 Karatsuba at a time + + //uint16_t i; + + register __m256i r0_avx, r1_avx, r2_avx, r3_avx; + + + + //CLOCK1=cpucycles(); + + //------------------AVX evaluation for 1st poly----------------------- + + r0_avx=a[0]; + r1_avx=a[1]; + r2_avx=a[2]; + r3_avx=a[3]; + a_bucket[0]=r0_avx; + a_bucket[1]=r1_avx; + a_bucket[2]=r2_avx; + a_bucket[3]=r3_avx; + a_bucket[4]= _mm256_add_epi16(r0_avx, r1_avx); + a_bucket[5]= _mm256_add_epi16(r2_avx, r3_avx); + a_bucket[6]= _mm256_add_epi16(r0_avx, r2_avx); + a_bucket[7]= _mm256_add_epi16(r1_avx, r3_avx); + a_bucket[8]= _mm256_add_epi16(a_bucket[6],a_bucket[7]); + + + //------------------AVX evaluation for 1st poly ends------------------ + + + //------------------AVX evaluation for 2nd poly----------------------- + r0_avx=a[small_len_avx]; + r1_avx=a[small_len_avx+1]; + r2_avx=a[small_len_avx+2]; + r3_avx=a[small_len_avx+3]; + a_bucket[0+9]=r0_avx; + a_bucket[1+9]=r1_avx; + a_bucket[2+9]=r2_avx; + a_bucket[3+9]=r3_avx; + a_bucket[4+9]= _mm256_add_epi16(r0_avx, r1_avx); + a_bucket[5+9]= _mm256_add_epi16(r2_avx, r3_avx); + a_bucket[6+9]= _mm256_add_epi16(r0_avx, r2_avx); + a_bucket[7+9]= _mm256_add_epi16(r1_avx, r3_avx); + a_bucket[8+9]= _mm256_add_epi16(a_bucket[6+9],a_bucket[7+9]); + + + //------------------AVX evaluation for 2nd poly ends------------------ + + + //------------------AVX evaluation for 3rd poly----------------------- + r0_avx=a[2*small_len_avx]; + r1_avx=a[2*small_len_avx+1]; + r2_avx=a[2*small_len_avx+2]; + r3_avx=a[2*small_len_avx+3]; + a_bucket[0+18]=r0_avx; + a_bucket[1+18]=r1_avx; + a_bucket[2+18]=r2_avx; + a_bucket[3+18]=r3_avx; + a_bucket[4+18]= _mm256_add_epi16(r0_avx, r1_avx); + a_bucket[5+18]= _mm256_add_epi16(r2_avx, r3_avx); + a_bucket[6+18]= _mm256_add_epi16(r0_avx, r2_avx); + a_bucket[7+18]= _mm256_add_epi16(r1_avx, r3_avx); + a_bucket[8+18]= _mm256_add_epi16(a_bucket[6+18],a_bucket[7+18]); + + //------------------AVX evaluation for 3rd poly ends------------------ + + + //------------------AVX evaluation for 4th poly----------------------- + + r0_avx=a[3*small_len_avx]; + r1_avx=a[3*small_len_avx+1]; + r2_avx=a[3*small_len_avx+2]; + r3_avx=a[3*small_len_avx+3]; + a_bucket[0+27]=r0_avx; + a_bucket[1+27]=r1_avx; + a_bucket[2+27]=r2_avx; + a_bucket[3+27]=r3_avx; + a_bucket[4+27]= _mm256_add_epi16(r0_avx, r1_avx); + a_bucket[5+27]= _mm256_add_epi16(r2_avx, r3_avx); + a_bucket[6+27]= _mm256_add_epi16(r0_avx, r2_avx); + a_bucket[7+27]= _mm256_add_epi16(r1_avx, r3_avx); + a_bucket[8+27]= _mm256_add_epi16(a_bucket[6+27],a_bucket[7+27]); + + //------------------AVX evaluation for 4th poly ends------------------ + + //------------------AVX evaluation for 5th poly----------------------- + + r0_avx=a[4*small_len_avx+0]; + r1_avx=a[4*small_len_avx+1]; + r2_avx=a[4*small_len_avx+2]; + r3_avx=a[4*small_len_avx+3]; + a_bucket[0+36]=r0_avx; + a_bucket[1+36]=r1_avx; + a_bucket[2+36]=r2_avx; + a_bucket[3+36]=r3_avx; + a_bucket[4+36]= _mm256_add_epi16(r0_avx, r1_avx); + a_bucket[5+36]= _mm256_add_epi16(r2_avx, r3_avx); + a_bucket[6+36]= _mm256_add_epi16(r0_avx, r2_avx); + a_bucket[7+36]= _mm256_add_epi16(r1_avx, r3_avx); + a_bucket[8+36]= _mm256_add_epi16(a_bucket[6+36],a_bucket[7+36]); + + //------------------AVX evaluation for 5th poly ends------------------ + + + //------------------AVX evaluation for 6th poly----------------------- + r0_avx=a[5*small_len_avx]; + r1_avx=a[5*small_len_avx+1]; + r2_avx=a[5*small_len_avx+2]; + r3_avx=a[5*small_len_avx+3]; + a_bucket[0+45]=r0_avx; + a_bucket[1+45]=r1_avx; + a_bucket[2+45]=r2_avx; + a_bucket[3+45]=r3_avx; + a_bucket[4+45]= _mm256_add_epi16(r0_avx, r1_avx); + a_bucket[5+45]= _mm256_add_epi16(r2_avx, r3_avx); + a_bucket[6+45]= _mm256_add_epi16(r0_avx, r2_avx); + a_bucket[7+45]= _mm256_add_epi16(r1_avx, r3_avx); + a_bucket[8+45]= _mm256_add_epi16(a_bucket[6+45],a_bucket[7+45]); + + //------------------AVX evaluation for 6th poly ends------------------ + + //------------------AVX evaluation for 7th poly----------------------- + + r0_avx=a[6*small_len_avx]; + r1_avx=a[6*small_len_avx+1]; + r2_avx=a[6*small_len_avx+2]; + r3_avx=a[6*small_len_avx+3]; + a_bucket[0+54]=r0_avx; + a_bucket[1+54]=r1_avx; + a_bucket[2+54]=r2_avx; + a_bucket[3+54]=r3_avx; + a_bucket[4+54]= _mm256_add_epi16(r0_avx, r1_avx); + a_bucket[5+54]= _mm256_add_epi16(r2_avx, r3_avx); + a_bucket[6+54]= _mm256_add_epi16(r0_avx, r2_avx); + a_bucket[7+54]= _mm256_add_epi16(r1_avx, r3_avx); + a_bucket[8+54]= _mm256_add_epi16(a_bucket[6+54],a_bucket[7+54]); + + //------------------AVX evaluation for 7th poly ends------------------ + + + + //CLOCK2=cpucycles(); + //CLOCK_EVAL=CLOCK_EVAL+(CLOCK2-CLOCK1); + //printf("\nTime for multiplication : %llu\n", CLOCK2-CLOCK1); + + + //CLOCK1=cpucycles(); + //-----------------Forward transposes-------------------------------------- + transpose_n1(a_bucket); + transpose_n1(a_bucket+16); + transpose_n1(a_bucket+32); + transpose_n1(a_bucket+48); + + //-----------------Forwatrd transposes ends--------------------------------- + + //----------------------all multiplications--------------------------------- + if(f==0){ + schoolbook_avx_new2(a_bucket, b_bucket, c_bucket); + schoolbook_avx_new2(a_bucket+16, b_bucket+16, c_bucket+2*SCM_SIZE); + schoolbook_avx_new2(a_bucket+32, b_bucket+32, c_bucket+4*SCM_SIZE); + schoolbook_avx_new2(a_bucket+48, b_bucket+48, c_bucket+6*SCM_SIZE); + } + else{ + schoolbook_avx_new3_acc(a_bucket, b_bucket, c_bucket); + schoolbook_avx_new3_acc(a_bucket+16, b_bucket+16, c_bucket+2*SCM_SIZE); + //schoolbook_avx_new3_acc_fused(a_bucket, b_bucket, c_bucket); + schoolbook_avx_new3_acc(a_bucket+32, b_bucket+32, c_bucket+4*SCM_SIZE); + schoolbook_avx_new3_acc(a_bucket+48, b_bucket+48, c_bucket+6*SCM_SIZE); + } + /* + schoolbook_avx_new2_acc(a_bucket, b_bucket, c_bucket, f); + schoolbook_avx_new2_acc(a_bucket+16, b_bucket+16, c_bucket+2*SCM_SIZE, f); + schoolbook_avx_new2_acc(a_bucket+32, b_bucket+32, c_bucket+4*SCM_SIZE, f); + schoolbook_avx_new2_acc(a_bucket+48, b_bucket+48, c_bucket+6*SCM_SIZE, f); + */ + + + //----------------------all multiplications ends----------------------------- + + + //-----------------Reverse transposes-------------------------------------- + + /* + transpose(c_bucket); + transpose(c_bucket+16); + + transpose(c_bucket+2*SCM_SIZE); + transpose(c_bucket+16+2*SCM_SIZE); + + transpose(c_bucket+4*SCM_SIZE); + transpose(c_bucket+16+4*SCM_SIZE); + + transpose(c_bucket+6*SCM_SIZE); + transpose(c_bucket+16+6*SCM_SIZE); + */ + //-----------------Reverse transposes ends--------------------------------- + + //CLOCK2=cpucycles(); + //CLOCK_MULT=CLOCK_MULT+(CLOCK2-CLOCK1); + + //KARA_interpol(c_bucket, result_final0, result_final1, result_final2, result_final3, result_final4, result_final5, result_final6); + +} + +static void KARA_eval(__m256i* b, __m256i *b_bucket){ + + __m256i r0_avx, r1_avx, r2_avx, r3_avx; + + + //-------1st poly---------------------------------------------------- + r0_avx=b[0]; + r1_avx=b[1]; + r2_avx=b[2]; + r3_avx=b[3]; + b_bucket[0]=r0_avx; + b_bucket[1]=r1_avx; + b_bucket[2]=r2_avx; + b_bucket[3]=r3_avx; + b_bucket[4]= _mm256_add_epi16(r0_avx, r1_avx); + b_bucket[5]= _mm256_add_epi16(r2_avx, r3_avx); + b_bucket[6]= _mm256_add_epi16(r0_avx, r2_avx); + b_bucket[7]= _mm256_add_epi16(r1_avx, r3_avx); + b_bucket[8]= _mm256_add_epi16(b_bucket[6],b_bucket[7]); + //-------2nd poly---------------------------------------------------- + + r0_avx=b[small_len_avx]; + r1_avx=b[small_len_avx+1]; + r2_avx=b[small_len_avx+2]; + r3_avx=b[small_len_avx+3]; + b_bucket[0+9]=r0_avx; + b_bucket[1+9]=r1_avx; + b_bucket[2+9]=r2_avx; + b_bucket[3+9]=r3_avx; + b_bucket[4+9]= _mm256_add_epi16(r0_avx, r1_avx); + b_bucket[5+9]= _mm256_add_epi16(r2_avx, r3_avx); + b_bucket[6+9]= _mm256_add_epi16(r0_avx, r2_avx); + b_bucket[7+9]= _mm256_add_epi16(r1_avx, r3_avx); + b_bucket[8+9]= _mm256_add_epi16(b_bucket[6+9],b_bucket[7+9]); + + //-------3rd poly---------------------------------------------------- + + r0_avx=b[2*small_len_avx+0]; + r1_avx=b[2*small_len_avx+1]; + r2_avx=b[2*small_len_avx+2]; + r3_avx=b[2*small_len_avx+3]; + b_bucket[0+18]=r0_avx; + b_bucket[1+18]=r1_avx; + b_bucket[2+18]=r2_avx; + b_bucket[3+18]=r3_avx; + b_bucket[4+18]= _mm256_add_epi16(r0_avx, r1_avx); + b_bucket[5+18]= _mm256_add_epi16(r2_avx, r3_avx); + b_bucket[6+18]= _mm256_add_epi16(r0_avx, r2_avx); + b_bucket[7+18]= _mm256_add_epi16(r1_avx, r3_avx); + b_bucket[8+18]= _mm256_add_epi16(b_bucket[6+18],b_bucket[7+18]); + + //-------4th poly---------------------------------------------------- + r0_avx=b[3*small_len_avx]; + r1_avx=b[3*small_len_avx+1]; + r2_avx=b[3*small_len_avx+2]; + r3_avx=b[3*small_len_avx+3]; + b_bucket[0+27]=r0_avx; + b_bucket[1+27]=r1_avx; + b_bucket[2+27]=r2_avx; + b_bucket[3+27]=r3_avx; + b_bucket[4+27]= _mm256_add_epi16(r0_avx, r1_avx); + b_bucket[5+27]= _mm256_add_epi16(r2_avx, r3_avx); + b_bucket[6+27]= _mm256_add_epi16(r0_avx, r2_avx); + b_bucket[7+27]= _mm256_add_epi16(r1_avx, r3_avx); + b_bucket[8+27]= _mm256_add_epi16(b_bucket[6+27],b_bucket[7+27]); + + //-------5th poly---------------------------------------------------- + + r0_avx=b[4*small_len_avx]; + r1_avx=b[4*small_len_avx+1]; + r2_avx=b[4*small_len_avx+2]; + r3_avx=b[4*small_len_avx+3]; + b_bucket[0+36]=r0_avx; + b_bucket[1+36]=r1_avx; + b_bucket[2+36]=r2_avx; + b_bucket[3+36]=r3_avx; + b_bucket[4+36]= _mm256_add_epi16(r0_avx, r1_avx); + b_bucket[5+36]= _mm256_add_epi16(r2_avx, r3_avx); + b_bucket[6+36]= _mm256_add_epi16(r0_avx, r2_avx); + b_bucket[7+36]= _mm256_add_epi16(r1_avx, r3_avx); + b_bucket[8+36]= _mm256_add_epi16(b_bucket[6+36],b_bucket[7+36]); + + //-------6th poly---------------------------------------------------- + + r0_avx=b[5*small_len_avx]; + r1_avx=b[5*small_len_avx+1]; + r2_avx=b[5*small_len_avx+2]; + r3_avx=b[5*small_len_avx+3]; + b_bucket[0+45]=r0_avx; + b_bucket[1+45]=r1_avx; + b_bucket[2+45]=r2_avx; + b_bucket[3+45]=r3_avx; + b_bucket[4+45]= _mm256_add_epi16(r0_avx, r1_avx); + b_bucket[5+45]= _mm256_add_epi16(r2_avx, r3_avx); + b_bucket[6+45]= _mm256_add_epi16(r0_avx, r2_avx); + b_bucket[7+45]= _mm256_add_epi16(r1_avx, r3_avx); + b_bucket[8+45]= _mm256_add_epi16(b_bucket[6+45],b_bucket[7+45]); + + //-------7th poly---------------------------------------------------- + + r0_avx=b[6*small_len_avx]; + r1_avx=b[6*small_len_avx+1]; + r2_avx=b[6*small_len_avx+2]; + r3_avx=b[6*small_len_avx+3]; + b_bucket[0+54]=r0_avx; + b_bucket[1+54]=r1_avx; + b_bucket[2+54]=r2_avx; + b_bucket[3+54]=r3_avx; + b_bucket[4+54]= _mm256_add_epi16(r0_avx, r1_avx); + b_bucket[5+54]= _mm256_add_epi16(r2_avx, r3_avx); + b_bucket[6+54]= _mm256_add_epi16(r0_avx, r2_avx); + b_bucket[7+54]= _mm256_add_epi16(r1_avx, r3_avx); + b_bucket[8+54]= _mm256_add_epi16(b_bucket[6+54],b_bucket[7+54]); + + //--------------Evaluating B poly ends------------------------------- + + transpose_n1(b_bucket); + transpose_n1(b_bucket+16); + transpose_n1(b_bucket+32); + transpose_n1(b_bucket+48); +} + +static void KARA_interpol(__m256i *c_bucket, __m256i* result_final0, __m256i* result_final1, __m256i* result_final2, __m256i* result_final3, __m256i* result_final4, __m256i* result_final5, __m256i* result_final6){ + + //int64_t i; + register __m256i res_avx0, res_avx1, res_avx2, res_avx3, res_avx4, res_avx5, res_avx6, res_avx7; // to hold each 64X64 poly mul results + + __m256i temp, c6_avx, c7_avx, c8_avx, c20_avx, c21_avx, c22_avx, c23_avx, c24_avx; + + //CLOCK1=cpucycles(); + + //------------------------AVX interpolation for 1st poly external------------------- + + //loop1 + res_avx0 = c_bucket[0]; + res_avx2 = c_bucket[1]; + res_avx4 = c_bucket[2]; + res_avx6 = c_bucket[3]; + + c6_avx=c_bucket[6]; + c7_avx=c_bucket[7]; + + c8_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[8], c6_avx), c7_avx); + + res_avx1 = c_bucket[16]; + res_avx3 = c_bucket[17]; + res_avx5 = c_bucket[18]; + res_avx7 = c_bucket[19]; + + c22_avx=c_bucket[22]; + c23_avx=c_bucket[23]; + + c21_avx=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[21], res_avx5),res_avx7); + + c24_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[24], c22_avx), c23_avx); + + c20_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[20], res_avx1), res_avx3); + + temp=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[5], res_avx4),res_avx6); + res_avx5 = _mm256_add_epi16(res_avx5, temp); + + temp = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[4], res_avx0), res_avx2); + res_avx1 = _mm256_add_epi16(res_avx1, temp); + + c22_avx=_mm256_add_epi16(c22_avx, c8_avx); + + res_avx6 = _mm256_add_epi16(res_avx6, c21_avx); + + res_avx2 = _mm256_add_epi16(res_avx2, c20_avx); + + c7_avx=_mm256_add_epi16(c7_avx, c24_avx); + + + //loop4 + + c6_avx=_mm256_sub_epi16(_mm256_sub_epi16(c6_avx, res_avx0), res_avx4); + c22_avx=_mm256_sub_epi16(_mm256_sub_epi16(c22_avx, res_avx1), res_avx5); + + c7_avx=_mm256_sub_epi16(_mm256_sub_epi16(c7_avx, res_avx2), res_avx6); + c23_avx=_mm256_sub_epi16(_mm256_sub_epi16(c23_avx, res_avx3), res_avx7); + + //loop5 + result_final0[0]=res_avx0; + result_final0[1]=res_avx1; + + result_final0[2]=_mm256_add_epi16(res_avx2, c6_avx); + result_final0[3]=_mm256_add_epi16(res_avx3, c22_avx); + + + result_final0[4]=_mm256_add_epi16(res_avx4, c7_avx); + result_final0[5]=_mm256_add_epi16(res_avx5, c23_avx); + + result_final0[6]=res_avx6; + result_final0[7]=res_avx7; + + + //------------------------AVX interpolation for 1st poly ends-------------- + + + //------------------------AVX interpolation for 2nd poly external------------------- + + //loop1 + res_avx0 = c_bucket[9]; //c_bucket0 + res_avx2 = c_bucket[10]; //c_bucket1 + res_avx4 = c_bucket[11]; //c_bucket2 + res_avx6 = c_bucket[12]; //c_bucket3 + + c6_avx=c_bucket[15]; //c_bucket6 + c7_avx=c_bucket[32]; //c_bucket7 + + c8_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[33], c6_avx), c7_avx); + + res_avx1 = c_bucket[25]; //c_bucket0 + res_avx3 = c_bucket[26]; //c_bucket1 + res_avx5 = c_bucket[27]; //c_bucket2 + res_avx7 = c_bucket[28]; //c_bucket3 + + c22_avx=c_bucket[31]; + c23_avx=c_bucket[48]; + + c21_avx=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[30], res_avx5),res_avx7); + + c24_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[49], c22_avx), c23_avx); + + c20_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[29], res_avx1), res_avx3); + + temp=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[14], res_avx4),res_avx6); + res_avx5 = _mm256_add_epi16(res_avx5, temp); + + temp = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[13], res_avx0), res_avx2); + res_avx1 = _mm256_add_epi16(res_avx1, temp); + + c22_avx=_mm256_add_epi16(c22_avx, c8_avx); + + res_avx6 = _mm256_add_epi16(res_avx6, c21_avx); + + res_avx2 = _mm256_add_epi16(res_avx2, c20_avx); + + c7_avx=_mm256_add_epi16(c7_avx, c24_avx); + + + //loop4 + + c6_avx=_mm256_sub_epi16(_mm256_sub_epi16(c6_avx, res_avx0), res_avx4); + c22_avx=_mm256_sub_epi16(_mm256_sub_epi16(c22_avx, res_avx1), res_avx5); + + c7_avx=_mm256_sub_epi16(_mm256_sub_epi16(c7_avx, res_avx2), res_avx6); + c23_avx=_mm256_sub_epi16(_mm256_sub_epi16(c23_avx, res_avx3), res_avx7); + + //loop5 + result_final1[0]=res_avx0; + result_final1[1]=res_avx1; + + result_final1[2]=_mm256_add_epi16(res_avx2, c6_avx); + result_final1[3]=_mm256_add_epi16(res_avx3, c22_avx); + + + result_final1[4]=_mm256_add_epi16(res_avx4, c7_avx); + result_final1[5]=_mm256_add_epi16(res_avx5, c23_avx); + + result_final1[6]=res_avx6; + result_final1[7]=res_avx7; + + + //------------------------AVX interpolation for 2nd poly ends-------------- + + //------------------------AVX interpolation for 3rd poly external------------------- + + //loop1 + res_avx0 = c_bucket[34]; //c_bucket0 + res_avx2 = c_bucket[35]; //c_bucket1 + res_avx4 = c_bucket[36]; + res_avx6 = c_bucket[37]; + + c6_avx=c_bucket[40]; + c7_avx=c_bucket[41]; + + c8_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[42], c6_avx), c7_avx); + + res_avx1 = c_bucket[50]; //c_bucket0 + res_avx3 = c_bucket[51]; //c_bucket1 + res_avx5 = c_bucket[52]; + res_avx7 = c_bucket[53]; + + c22_avx=c_bucket[56]; + c23_avx=c_bucket[57]; + + c21_avx=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[55], res_avx5),res_avx7); + + c24_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[58], c22_avx), c23_avx); + + c20_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[54], res_avx1), res_avx3); + + temp=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[39], res_avx4),res_avx6); + res_avx5 = _mm256_add_epi16(res_avx5, temp); + + temp = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[38], res_avx0), res_avx2); + res_avx1 = _mm256_add_epi16(res_avx1, temp); + + c22_avx=_mm256_add_epi16(c22_avx, c8_avx); + + res_avx6 = _mm256_add_epi16(res_avx6, c21_avx); + + res_avx2 = _mm256_add_epi16(res_avx2, c20_avx); + + c7_avx=_mm256_add_epi16(c7_avx, c24_avx); + + //loop4 + c6_avx=_mm256_sub_epi16(_mm256_sub_epi16(c6_avx, res_avx0), res_avx4); + c22_avx=_mm256_sub_epi16(_mm256_sub_epi16(c22_avx, res_avx1), res_avx5); + + c7_avx=_mm256_sub_epi16(_mm256_sub_epi16(c7_avx, res_avx2), res_avx6); + c23_avx=_mm256_sub_epi16(_mm256_sub_epi16(c23_avx, res_avx3), res_avx7); + //loop5 + result_final2[0]=res_avx0; + result_final2[1]=res_avx1; + + result_final2[2]=_mm256_add_epi16(res_avx2, c6_avx); + result_final2[3]=_mm256_add_epi16(res_avx3, c22_avx); + + + result_final2[4]=_mm256_add_epi16(res_avx4, c7_avx); + result_final2[5]=_mm256_add_epi16(res_avx5, c23_avx); + + result_final2[6]=res_avx6; + result_final2[7]=res_avx7; + + //------------------------AVX interpolation for 3rd poly ends-------------- + + //------------------------AVX interpolation for 4th poly external------------------- + + //loop1 + res_avx0 = c_bucket[43]; + res_avx2 = c_bucket[44]; + res_avx4 = c_bucket[45]; + res_avx6 = c_bucket[46]; + + c6_avx=c_bucket[65]; + c7_avx=c_bucket[66]; + + c8_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[67], c6_avx), c7_avx); + + res_avx1 = c_bucket[59]; + res_avx3 = c_bucket[60]; + res_avx5 = c_bucket[61]; + res_avx7 = c_bucket[62]; + + c22_avx=c_bucket[81]; + c23_avx=c_bucket[82]; + + c21_avx=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[80], res_avx5),res_avx7); + + c24_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[83], c22_avx), c23_avx); + + c20_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[63], res_avx1), res_avx3); + + temp=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[64], res_avx4),res_avx6); + res_avx5 = _mm256_add_epi16(res_avx5, temp); + + temp = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[47], res_avx0), res_avx2); + res_avx1 = _mm256_add_epi16(res_avx1, temp); + + c22_avx=_mm256_add_epi16(c22_avx, c8_avx); + + res_avx6 = _mm256_add_epi16(res_avx6, c21_avx); + + res_avx2 = _mm256_add_epi16(res_avx2, c20_avx); + + c7_avx=_mm256_add_epi16(c7_avx, c24_avx); + + + //loop4 + + c6_avx=_mm256_sub_epi16(_mm256_sub_epi16(c6_avx, res_avx0), res_avx4); + c22_avx=_mm256_sub_epi16(_mm256_sub_epi16(c22_avx, res_avx1), res_avx5); + + c7_avx=_mm256_sub_epi16(_mm256_sub_epi16(c7_avx, res_avx2), res_avx6); + c23_avx=_mm256_sub_epi16(_mm256_sub_epi16(c23_avx, res_avx3), res_avx7); + + //loop5 + result_final3[0]=res_avx0; + result_final3[1]=res_avx1; + + result_final3[2]=_mm256_add_epi16(res_avx2, c6_avx); + result_final3[3]=_mm256_add_epi16(res_avx3, c22_avx); + + + result_final3[4]=_mm256_add_epi16(res_avx4, c7_avx); + result_final3[5]=_mm256_add_epi16(res_avx5, c23_avx); + + result_final3[6]=res_avx6; + result_final3[7]=res_avx7; + + + //------------------------AVX interpolation for 4th poly ends-------------- + + //------------------------AVX interpolation for 5th poly external------------------- + + //loop1 + res_avx0 = c_bucket[68]; + res_avx2 = c_bucket[69]; + res_avx4 = c_bucket[70]; + res_avx6 = c_bucket[71]; + + c6_avx=c_bucket[74]; + c7_avx=c_bucket[75]; + + c8_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[76], c6_avx), c7_avx); + + res_avx1 = c_bucket[84]; + res_avx3 = c_bucket[85]; + res_avx5 = c_bucket[86]; + res_avx7 = c_bucket[87]; + + c22_avx=c_bucket[90]; + c23_avx=c_bucket[91]; + + c21_avx=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[89], res_avx5),res_avx7); + + c24_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[92], c22_avx), c23_avx); + + c20_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[88], res_avx1), res_avx3); + + temp=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[73], res_avx4),res_avx6); + res_avx5 = _mm256_add_epi16(res_avx5, temp); + + temp = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[72], res_avx0), res_avx2); + res_avx1 = _mm256_add_epi16(res_avx1, temp); + + c22_avx=_mm256_add_epi16(c22_avx, c8_avx); + + res_avx6 = _mm256_add_epi16(res_avx6, c21_avx); + + res_avx2 = _mm256_add_epi16(res_avx2, c20_avx); + + c7_avx=_mm256_add_epi16(c7_avx, c24_avx); + + + //loop4 + + c6_avx=_mm256_sub_epi16(_mm256_sub_epi16(c6_avx, res_avx0), res_avx4); + c22_avx=_mm256_sub_epi16(_mm256_sub_epi16(c22_avx, res_avx1), res_avx5); + + c7_avx=_mm256_sub_epi16(_mm256_sub_epi16(c7_avx, res_avx2), res_avx6); + c23_avx=_mm256_sub_epi16(_mm256_sub_epi16(c23_avx, res_avx3), res_avx7); + + //loop5 + result_final4[0]=res_avx0; + result_final4[1]=res_avx1; + + result_final4[2]=_mm256_add_epi16(res_avx2, c6_avx); + result_final4[3]=_mm256_add_epi16(res_avx3, c22_avx); + + + result_final4[4]=_mm256_add_epi16(res_avx4, c7_avx); + result_final4[5]=_mm256_add_epi16(res_avx5, c23_avx); + + result_final4[6]=res_avx6; + result_final4[7]=res_avx7; + + + //------------------------AVX interpolation for 5th poly ends-------------- + + //------------------------AVX interpolation for 6th poly external------------------- + + //loop1 + res_avx0 = c_bucket[77]; + res_avx2 = c_bucket[78]; + res_avx4 = c_bucket[79]; + res_avx6 = c_bucket[96]; + + c6_avx=c_bucket[99]; + c7_avx=c_bucket[100]; + + c8_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[101], c6_avx), c7_avx); + + res_avx1 = c_bucket[93]; + res_avx3 = c_bucket[94]; + res_avx5 = c_bucket[95]; + res_avx7 = c_bucket[112]; + + c22_avx=c_bucket[115]; + c23_avx=c_bucket[116]; + + c21_avx=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[114], res_avx5),res_avx7); + + c24_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[117], c22_avx), c23_avx); + + c20_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[113], res_avx1), res_avx3); + + temp=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[98], res_avx4),res_avx6); + res_avx5 = _mm256_add_epi16(res_avx5, temp); + + temp = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[97], res_avx0), res_avx2); + res_avx1 = _mm256_add_epi16(res_avx1, temp); + + c22_avx=_mm256_add_epi16(c22_avx, c8_avx); + + res_avx6 = _mm256_add_epi16(res_avx6, c21_avx); + + res_avx2 = _mm256_add_epi16(res_avx2, c20_avx); + + c7_avx=_mm256_add_epi16(c7_avx, c24_avx); + + + //loop4 + + c6_avx=_mm256_sub_epi16(_mm256_sub_epi16(c6_avx, res_avx0), res_avx4); + c22_avx=_mm256_sub_epi16(_mm256_sub_epi16(c22_avx, res_avx1), res_avx5); + + c7_avx=_mm256_sub_epi16(_mm256_sub_epi16(c7_avx, res_avx2), res_avx6); + c23_avx=_mm256_sub_epi16(_mm256_sub_epi16(c23_avx, res_avx3), res_avx7); + + //loop5 + result_final5[0]=res_avx0; + result_final5[1]=res_avx1; + + result_final5[2]=_mm256_add_epi16(res_avx2, c6_avx); + result_final5[3]=_mm256_add_epi16(res_avx3, c22_avx); + + + result_final5[4]=_mm256_add_epi16(res_avx4, c7_avx); + result_final5[5]=_mm256_add_epi16(res_avx5, c23_avx); + + result_final5[6]=res_avx6; + result_final5[7]=res_avx7; + + + //------------------------AVX interpolation for 6th poly ends-------------- + + //------------------------AVX interpolation for 7th poly external------------------- + + //loop1 + res_avx0 = c_bucket[102]; + res_avx2 = c_bucket[103]; + res_avx4 = c_bucket[104]; + res_avx6 = c_bucket[105]; + + c6_avx=c_bucket[108]; + c7_avx=c_bucket[109]; + + c8_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[110], c6_avx), c7_avx); + + res_avx1 = c_bucket[118]; + res_avx3 = c_bucket[119]; + res_avx5 = c_bucket[120]; + res_avx7 = c_bucket[121]; + + c22_avx=c_bucket[124]; + c23_avx=c_bucket[125]; + + c21_avx=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[123], res_avx5),res_avx7); + + c24_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[126], c22_avx), c23_avx); + + c20_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[122], res_avx1), res_avx3); + + temp=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[107], res_avx4),res_avx6); + res_avx5 = _mm256_add_epi16(res_avx5, temp); + + temp = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[106], res_avx0), res_avx2); + res_avx1 = _mm256_add_epi16(res_avx1, temp); + + c22_avx=_mm256_add_epi16(c22_avx, c8_avx); + + res_avx6 = _mm256_add_epi16(res_avx6, c21_avx); + + res_avx2 = _mm256_add_epi16(res_avx2, c20_avx); + + c7_avx=_mm256_add_epi16(c7_avx, c24_avx); + + + //loop4 + + c6_avx=_mm256_sub_epi16(_mm256_sub_epi16(c6_avx, res_avx0), res_avx4); + c22_avx=_mm256_sub_epi16(_mm256_sub_epi16(c22_avx, res_avx1), res_avx5); + + c7_avx=_mm256_sub_epi16(_mm256_sub_epi16(c7_avx, res_avx2), res_avx6); + c23_avx=_mm256_sub_epi16(_mm256_sub_epi16(c23_avx, res_avx3), res_avx7); + + //loop5 + result_final6[0]=res_avx0; + result_final6[1]=res_avx1; + + result_final6[2]=_mm256_add_epi16(res_avx2, c6_avx); + result_final6[3]=_mm256_add_epi16(res_avx3, c22_avx); + + + result_final6[4]=_mm256_add_epi16(res_avx4, c7_avx); + result_final6[5]=_mm256_add_epi16(res_avx5, c23_avx); + + result_final6[6]=res_avx6; + result_final6[7]=res_avx7; + + + //------------------------AVX interpolation for 7th poly ends-------------- + + //CLOCK2=cpucycles(); + //CLOCK_INTER=CLOCK_INTER+(CLOCK2-CLOCK1); + //printf("\nTime for interpolation : %llu\n", CLOCK2-CLOCK1); + + + +} + +static void toom_cook_4way_avx_n1(__m256i* a_avx,__m256i* b_bucket, __m256i *c_bucket, int f){ + + int i; + +//---------------AVX data----------------------------- + + __m256i r0_avx, r1_avx, r2_avx, r3_avx, r4_avx, r5_avx, r6_avx; + __m256i aw_avx[7*small_len_avx]; + +//----------------AVX data---------------------------- + + +// EVALUATION + + //CLOCK1=cpucycles(); + + for (i=0; i>= 63; + return (uint8_t) r; +} + +/* b = 1 means mov, b = 0 means don't mov*/ +void PQCLEAN_LIGHTSABER_AVX2_cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b) { + size_t i; + + b = -b; + for (i = 0; i < len; i++) { + r[i] ^= b & (x[i] ^ r[i]); + } +} diff --git a/crypto_kem/lightsaber/avx2/verify.h b/crypto_kem/lightsaber/avx2/verify.h new file mode 100644 index 00000000..f57ee9bc --- /dev/null +++ b/crypto_kem/lightsaber/avx2/verify.h @@ -0,0 +1,22 @@ +#ifndef VERIFY_H +#define VERIFY_H +/*------------------------------------------------- +This file has been adapted from the implementation +(available at https://github.com/pq-crystals/kyber) of +"CRYSTALS – Kyber: a CCA-secure module-lattice-based KEM" + by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint, +Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle +----------------------------------------------------*/ + +#include +#include + +/* returns 0 for equal strings, 1 for non-equal strings */ +uint8_t PQCLEAN_LIGHTSABER_AVX2_verify(const uint8_t *a, const uint8_t *b, size_t len); + + +/* b = 1 means mov, b = 0 means don't mov*/ +void PQCLEAN_LIGHTSABER_AVX2_cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b); + + +#endif diff --git a/crypto_kem/lightsaber/clean/LICENSE b/crypto_kem/lightsaber/clean/LICENSE index 08c799e3..d5d21fff 100644 --- a/crypto_kem/lightsaber/clean/LICENSE +++ b/crypto_kem/lightsaber/clean/LICENSE @@ -1,8 +1 @@ ----------------------------------------------------------------------------------------- -SABER_v1.1 - -Public domain - -Authors: Jan-Pieter D'Anvers, Angshuman Karmakar, Sujoy Sinha Roy, -Frederik Vercauteren ----------------------------------------------------------------------------------------- +Public Domain diff --git a/crypto_kem/lightsaber/clean/Makefile b/crypto_kem/lightsaber/clean/Makefile index b1b532e4..160435dc 100644 --- a/crypto_kem/lightsaber/clean/Makefile +++ b/crypto_kem/lightsaber/clean/Makefile @@ -1,10 +1,10 @@ # This Makefile can be used with GNU Make or BSD Make LIB=liblightsaber_clean.a -HEADERS=api.h cbd.h poly.h poly_mul.h SABER_indcpa.h SABER_params.h verify.h pack_unpack.h +HEADERS=api.h cbd.h pack_unpack.h poly.h poly_mul.h SABER_indcpa.h SABER_params.h verify.h OBJECTS=cbd.o kem.o pack_unpack.o poly.o poly_mul.o SABER_indcpa.o verify.o -CFLAGS=-O3 -Wall -Wextra -Wpedantic -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wredundant-decls -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_kem/lightsaber/clean/SABER_indcpa.c b/crypto_kem/lightsaber/clean/SABER_indcpa.c index 20cf1de2..ccb72492 100644 --- a/crypto_kem/lightsaber/clean/SABER_indcpa.c +++ b/crypto_kem/lightsaber/clean/SABER_indcpa.c @@ -3,296 +3,90 @@ #include "fips202.h" #include "pack_unpack.h" #include "poly.h" -#include "poly_mul.h" #include "randombytes.h" #include #include +#define h1 (1 << (SABER_EQ - SABER_EP - 1)) +#define h2 ((1 << (SABER_EP - 2)) - (1 << (SABER_EP - SABER_ET - 1)) + (1 << (SABER_EQ - SABER_EP - 1))) +void PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_keypair(uint8_t pk[SABER_INDCPA_PUBLICKEYBYTES], uint8_t sk[SABER_INDCPA_SECRETKEYBYTES]) { + uint16_t A[SABER_L][SABER_L][SABER_N]; + uint16_t s[SABER_L][SABER_N]; + uint16_t b[SABER_L][SABER_N] = {0}; -/*----------------------------------------------------------------------------------- - This routine generates a=[Matrix K x K] of 256-coefficient polynomials --------------------------------------------------------------------------------------*/ + uint8_t seed_A[SABER_SEEDBYTES]; + uint8_t seed_s[SABER_NOISE_SEEDBYTES]; + int i, j; -#define h1 4 //2^(EQ-EP-1) + randombytes(seed_A, SABER_SEEDBYTES); + shake128(seed_A, SABER_SEEDBYTES, seed_A, SABER_SEEDBYTES); // for not revealing system RNG state + randombytes(seed_s, SABER_NOISE_SEEDBYTES); -#define h2 ( (1<<(SABER_EP-2)) - (1<<(SABER_EP-SABER_ET-1)) + (1<<(SABER_EQ-SABER_EP-1)) ) + PQCLEAN_LIGHTSABER_CLEAN_GenMatrix(A, seed_A); + PQCLEAN_LIGHTSABER_CLEAN_GenSecret(s, seed_s); + PQCLEAN_LIGHTSABER_CLEAN_MatrixVectorMul(b, (const uint16_t (*)[SABER_L][SABER_N])A, (const uint16_t (*)[SABER_N])s, 1); -static void InnerProd(uint16_t pkcl[SABER_K][SABER_N], uint16_t skpv[SABER_K][SABER_N], uint16_t mod, uint16_t res[SABER_N]); -static void MatrixVectorMul(polyvec *a, uint16_t skpv[SABER_K][SABER_N], uint16_t res[SABER_K][SABER_N], uint16_t mod, int16_t transpose); - -static void POL2MSG(const uint16_t *message_dec_unpacked, unsigned char *message_dec); - -static void GenMatrix(polyvec *a, const unsigned char *seed) { - unsigned char buf[SABER_K * SABER_K * (13 * SABER_N / 8)]; - - uint16_t temp_ar[SABER_N]; - - int i, j, k; - uint16_t mod = (SABER_Q - 1); - - shake128(buf, sizeof(buf), seed, SABER_SEEDBYTES); - - for (i = 0; i < SABER_K; i++) { - for (j = 0; j < SABER_K; j++) { - PQCLEAN_LIGHTSABER_CLEAN_BS2POL(buf + (i * SABER_K + j) * (13 * SABER_N / 8), temp_ar); - for (k = 0; k < SABER_N; k++) { - a[i].vec[j].coeffs[k] = (temp_ar[k])& mod ; - } + for (i = 0; i < SABER_L; i++) { + for (j = 0; j < SABER_N; j++) { + b[i][j] = (b[i][j] + h1) >> (SABER_EQ - SABER_EP); } } + + PQCLEAN_LIGHTSABER_CLEAN_POLVECq2BS(sk, (const uint16_t (*)[SABER_N])s); + PQCLEAN_LIGHTSABER_CLEAN_POLVECp2BS(pk, (const uint16_t (*)[SABER_N])b); + memcpy(pk + SABER_POLYVECCOMPRESSEDBYTES, seed_A, sizeof(seed_A)); } +void PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_enc(uint8_t ciphertext[SABER_BYTES_CCA_DEC], const uint8_t m[SABER_KEYBYTES], const uint8_t seed_sp[SABER_NOISE_SEEDBYTES], const uint8_t pk[SABER_INDCPA_PUBLICKEYBYTES]) { + uint16_t A[SABER_L][SABER_L][SABER_N]; + uint16_t sp[SABER_L][SABER_N]; + uint16_t bp[SABER_L][SABER_N] = {0}; + uint16_t vp[SABER_N] = {0}; + uint16_t mp[SABER_N]; + uint16_t b[SABER_L][SABER_N]; + int i, j; + const uint8_t *seed_A = pk + SABER_POLYVECCOMPRESSEDBYTES; -void PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_keypair(unsigned char *pk, unsigned char *sk) { - polyvec a[SABER_K]; + PQCLEAN_LIGHTSABER_CLEAN_GenMatrix(A, seed_A); + PQCLEAN_LIGHTSABER_CLEAN_GenSecret(sp, seed_sp); + PQCLEAN_LIGHTSABER_CLEAN_MatrixVectorMul(bp, (const uint16_t (*)[SABER_L][SABER_N])A, (const uint16_t (*)[SABER_N])sp, 0); - uint16_t skpv[SABER_K][SABER_N]; - - unsigned char seed[SABER_SEEDBYTES]; - unsigned char noiseseed[SABER_COINBYTES]; - int32_t i, j; - uint16_t mod_q = SABER_Q - 1; - - - uint16_t res[SABER_K][SABER_N]; - - randombytes(seed, SABER_SEEDBYTES); - - // for not revealing system RNG state - shake128(seed, SABER_SEEDBYTES, seed, SABER_SEEDBYTES); - randombytes(noiseseed, SABER_COINBYTES); - - GenMatrix(a, seed); //sample matrix A - - // generate secret from constant-time binomial distribution - PQCLEAN_LIGHTSABER_CLEAN_GenSecret(skpv, noiseseed); - - // do the matrix vector multiplication and rounding - for (i = 0; i < SABER_K; i++) { + for (i = 0; i < SABER_L; i++) { for (j = 0; j < SABER_N; j++) { - res[i][j] = 0; - } - } - MatrixVectorMul(a, skpv, res, SABER_Q - 1, 1); - - // now rounding - for (i = 0; i < SABER_K; i++) { - for (j = 0; j < SABER_N; j++) { - // shift right 3 bits - res[i][j] = (res[i][j] + h1) & (mod_q); - res[i][j] = (res[i][j] >> (SABER_EQ - SABER_EP)); + bp[i][j] = (bp[i][j] + h1) >> (SABER_EQ - SABER_EP); } } - // unload and pack sk=3 x (256 coefficients of 14 bits) - PQCLEAN_LIGHTSABER_CLEAN_POLVEC2BS(sk, skpv, SABER_Q); + PQCLEAN_LIGHTSABER_CLEAN_POLVECp2BS(ciphertext, (const uint16_t (*)[SABER_N])bp); + PQCLEAN_LIGHTSABER_CLEAN_BS2POLVECp(b, pk); + PQCLEAN_LIGHTSABER_CLEAN_InnerProd(vp, (const uint16_t (*)[SABER_N])b, (const uint16_t (*)[SABER_N])sp); - // unload and pack pk=256 bits seed and 3 x (256 coefficients of 11 bits) - // load the public-key coefficients - PQCLEAN_LIGHTSABER_CLEAN_POLVEC2BS(pk, res, SABER_P); + PQCLEAN_LIGHTSABER_CLEAN_BS2POLmsg(mp, m); - - // now load the seedbytes in PK. Easy since seed bytes are kept in byte format. - for (i = 0; i < SABER_SEEDBYTES; i++) { - pk[SABER_POLYVECCOMPRESSEDBYTES + i] = seed[i]; + for (j = 0; j < SABER_N; j++) { + vp[j] = (vp[j] - (mp[j] << (SABER_EP - 1)) + h1) >> (SABER_EP - SABER_ET); } + PQCLEAN_LIGHTSABER_CLEAN_POLT2BS(ciphertext + SABER_POLYVECCOMPRESSEDBYTES, vp); } +void PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_dec(uint8_t m[SABER_KEYBYTES], const uint8_t sk[SABER_INDCPA_SECRETKEYBYTES], const uint8_t ciphertext[SABER_BYTES_CCA_DEC]) { -void PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_enc(const unsigned char *message_received, unsigned char *noiseseed, const unsigned char *pk, unsigned char *ciphertext) { - uint32_t i, j, k; - polyvec a[SABER_K]; - unsigned char seed[SABER_SEEDBYTES]; - // public key of received by the client - uint16_t pkcl[SABER_K][SABER_N]; - uint16_t skpv1[SABER_K][SABER_N]; - uint16_t message[SABER_KEYBYTES * 8]; - uint16_t res[SABER_K][SABER_N]; - uint16_t mod_p = SABER_P - 1; - uint16_t mod_q = SABER_Q - 1; - uint16_t vprime[SABER_N]; - unsigned char msk_c[SABER_SCALEBYTES_KEM]; + uint16_t s[SABER_L][SABER_N]; + uint16_t b[SABER_L][SABER_N]; + uint16_t v[SABER_N] = {0}; + uint16_t cm[SABER_N]; + int i; - // extract the seedbytes from Public Key. - for (i = 0; i < SABER_SEEDBYTES; i++) { - seed[i] = pk[ SABER_POLYVECCOMPRESSEDBYTES + i]; - } + PQCLEAN_LIGHTSABER_CLEAN_BS2POLVECq(s, sk); + PQCLEAN_LIGHTSABER_CLEAN_BS2POLVECp(b, ciphertext); + PQCLEAN_LIGHTSABER_CLEAN_InnerProd(v, (const uint16_t (*)[SABER_N])b, (const uint16_t (*)[SABER_N])s); + PQCLEAN_LIGHTSABER_CLEAN_BS2POLT(cm, ciphertext + SABER_POLYVECCOMPRESSEDBYTES); - GenMatrix(a, seed); - - // generate secret from constant-time binomial distribution - PQCLEAN_LIGHTSABER_CLEAN_GenSecret(skpv1, noiseseed); - - // matrix-vector multiplication and rounding - for (i = 0; i < SABER_K; i++) { - for (j = 0; j < SABER_N; j++) { - res[i][j] = 0; - } - } - MatrixVectorMul(a, skpv1, res, SABER_Q - 1, 0); - - // now rounding - //shift right 3 bits - for (i = 0; i < SABER_K; i++) { - for (j = 0; j < SABER_N; j++) { - res[i][j] = ( res[i][j] + h1 ) & mod_q; - res[i][j] = (res[i][j] >> (SABER_EQ - SABER_EP) ); - } - } - - PQCLEAN_LIGHTSABER_CLEAN_POLVEC2BS(ciphertext, res, SABER_P); - - // ************client matrix-vector multiplication ends************ - - // now calculate the v' - // unpack the public_key - // pkcl is the b in the protocol - PQCLEAN_LIGHTSABER_CLEAN_BS2POLVEC(pk, pkcl, SABER_P); for (i = 0; i < SABER_N; i++) { - vprime[i] = 0; - } - for (i = 0; i < SABER_K; i++) { - for (j = 0; j < SABER_N; j++) { - skpv1[i][j] = skpv1[i][j] & (mod_p); - } + v[i] = (v[i] + h2 - (cm[i] << (SABER_EP - SABER_ET))) >> (SABER_EP - 1); } - // vector-vector scalar multiplication with mod p - InnerProd(pkcl, skpv1, mod_p, vprime); - - // addition of h1 to vprime - for (i = 0; i < SABER_N; i++) { - vprime[i] = vprime[i] + h1; - } - - // unpack message_received; - for (j = 0; j < SABER_KEYBYTES; j++) { - for (i = 0; i < 8; i++) { - message[8 * j + i] = ((message_received[j] >> i) & 0x01); - } - } - - // message encoding - for (i = 0; i < SABER_N; i++) { - message[i] = (message[i] << (SABER_EP - 1)); - } - - for (k = 0; k < SABER_N; k++) { - vprime[k] = ( (vprime[k] - message[k]) & (mod_p) ) >> (SABER_EP - SABER_ET); - } - - - PQCLEAN_LIGHTSABER_CLEAN_pack_3bit(msk_c, vprime); - - for (j = 0; j < SABER_SCALEBYTES_KEM; j++) { - ciphertext[SABER_POLYVECCOMPRESSEDBYTES + j] = msk_c[j]; - } -} - - -void PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_dec(const unsigned char *sk, const unsigned char *ciphertext, unsigned char message_dec[]) { - uint32_t i, j; - // secret key of the server - uint16_t sksv[SABER_K][SABER_N]; - uint16_t pksv[SABER_K][SABER_N]; - uint8_t scale_ar[SABER_SCALEBYTES_KEM]; - uint16_t mod_p = SABER_P - 1; - uint16_t v[SABER_N]; - uint16_t op[SABER_N]; - - // sksv is the secret-key - PQCLEAN_LIGHTSABER_CLEAN_BS2POLVEC(sk, sksv, SABER_Q); - // pksv is the ciphertext - PQCLEAN_LIGHTSABER_CLEAN_BS2POLVEC(ciphertext, pksv, SABER_P); - - // vector-vector scalar multiplication with mod p - for (i = 0; i < SABER_N; i++) { - v[i] = 0; - } - for (i = 0; i < SABER_K; i++) { - for (j = 0; j < SABER_N; j++) { - sksv[i][j] = sksv[i][j] & (mod_p); - } - } - InnerProd(pksv, sksv, mod_p, v); - - //Extraction - for (i = 0; i < SABER_SCALEBYTES_KEM; i++) { - scale_ar[i] = ciphertext[SABER_POLYVECCOMPRESSEDBYTES + i]; - } - - PQCLEAN_LIGHTSABER_CLEAN_un_pack3bit(scale_ar, op); - - //addition of h1 - for (i = 0; i < SABER_N; i++) { - v[i] = ( ( v[i] + h2 - (op[i] << (SABER_EP - SABER_ET)) ) & (mod_p) ) >> (SABER_EP - 1); - } - - // pack decrypted message - POL2MSG(v, message_dec); -} -static void MatrixVectorMul(polyvec *a, uint16_t skpv[SABER_K][SABER_N], uint16_t res[SABER_K][SABER_N], uint16_t mod, int16_t transpose) { - uint16_t acc[SABER_N]; - int32_t i, j, k; - - if (transpose == 1) { - for (i = 0; i < SABER_K; i++) { - for (j = 0; j < SABER_K; j++) { - PQCLEAN_LIGHTSABER_CLEAN_pol_mul((uint16_t *)&a[j].vec[i], skpv[j], acc, SABER_Q, SABER_N); - - for (k = 0; k < SABER_N; k++) { - res[i][k] = res[i][k] + acc[k]; - //reduction mod p - res[i][k] = (res[i][k] & mod); - //clear the accumulator - acc[k] = 0; - } - } - } - } else { - for (i = 0; i < SABER_K; i++) { - for (j = 0; j < SABER_K; j++) { - PQCLEAN_LIGHTSABER_CLEAN_pol_mul((uint16_t *)&a[i].vec[j], skpv[j], acc, SABER_Q, SABER_N); - for (k = 0; k < SABER_N; k++) { - res[i][k] = res[i][k] + acc[k]; - // reduction - res[i][k] = res[i][k] & mod; - // clear the accumulator - acc[k] = 0; - } - } - } - } -} - -static void POL2MSG(const uint16_t *message_dec_unpacked, unsigned char *message_dec) { - int32_t i, j; - - for (j = 0; j < SABER_KEYBYTES; j++) { - message_dec[j] = 0; - for (i = 0; i < 8; i++) { - message_dec[j] = message_dec[j] | (uint8_t) (message_dec_unpacked[j * 8 + i] << i); - } - } -} - - -static void InnerProd(uint16_t pkcl[SABER_K][SABER_N], uint16_t skpv[SABER_K][SABER_N], uint16_t mod, uint16_t res[SABER_N]) { - uint32_t j, k; - uint16_t acc[SABER_N]; - - // vector-vector scalar multiplication with mod p - for (j = 0; j < SABER_K; j++) { - PQCLEAN_LIGHTSABER_CLEAN_pol_mul(pkcl[j], skpv[j], acc, SABER_P, SABER_N); - - for (k = 0; k < SABER_N; k++) { - res[k] = res[k] + acc[k]; - // reduction - res[k] = res[k] & mod; - // clear the accumulator - acc[k] = 0; - } - } + PQCLEAN_LIGHTSABER_CLEAN_POLmsg2BS(m, v); } diff --git a/crypto_kem/lightsaber/clean/SABER_indcpa.h b/crypto_kem/lightsaber/clean/SABER_indcpa.h index 4f806c55..efccbf5e 100644 --- a/crypto_kem/lightsaber/clean/SABER_indcpa.h +++ b/crypto_kem/lightsaber/clean/SABER_indcpa.h @@ -1,9 +1,13 @@ #ifndef INDCPA_H #define INDCPA_H +#include "SABER_params.h" +#include + +void PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_keypair(uint8_t pk[SABER_INDCPA_PUBLICKEYBYTES], uint8_t sk[SABER_INDCPA_SECRETKEYBYTES]); + +void PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_enc(uint8_t ciphertext[SABER_BYTES_CCA_DEC], const uint8_t m[SABER_KEYBYTES], const uint8_t seed_sp[SABER_NOISE_SEEDBYTES], const uint8_t pk[SABER_INDCPA_PUBLICKEYBYTES]); + +void PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_dec(uint8_t m[SABER_KEYBYTES], const uint8_t sk[SABER_INDCPA_SECRETKEYBYTES], const uint8_t ciphertext[SABER_BYTES_CCA_DEC]); -void PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_keypair(unsigned char *pk, unsigned char *sk); -void PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_enc(const unsigned char *message, unsigned char *noiseseed, const unsigned char *pk, unsigned char *ciphertext); -void PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_dec(const unsigned char *sk, const unsigned char *ciphertext, unsigned char *message_dec); #endif - diff --git a/crypto_kem/lightsaber/clean/SABER_params.h b/crypto_kem/lightsaber/clean/SABER_params.h index eb3825f2..a6a9fc55 100644 --- a/crypto_kem/lightsaber/clean/SABER_params.h +++ b/crypto_kem/lightsaber/clean/SABER_params.h @@ -1,50 +1,39 @@ #ifndef PARAMS_H #define PARAMS_H -#include "api.h" -#define SABER_K 2 +/* Change this for different security strengths */ + +/* Don't change anything below this line */ +#define SABER_L 2 #define SABER_MU 10 #define SABER_ET 3 - #define SABER_EQ 13 #define SABER_EP 10 - #define SABER_N 256 -#define SABER_Q 8192 -#define SABER_P 1024 -#define SABER_SEEDBYTES 32 -#define SABER_NOISESEEDBYTES 32 -#define SABER_COINBYTES 32 -#define SABER_KEYBYTES 32 +#define SABER_SEEDBYTES 32 +#define SABER_NOISE_SEEDBYTES 32 +#define SABER_KEYBYTES 32 +#define SABER_HASHBYTES 32 -#define SABER_HASHBYTES 32 +#define SABER_POLYCOINBYTES (SABER_MU * SABER_N / 8) -#define SABER_POLYBYTES 416 //13*256/8 +#define SABER_POLYBYTES (SABER_EQ * SABER_N / 8) +#define SABER_POLYVECBYTES (SABER_L * SABER_POLYBYTES) -#define SABER_POLYVECBYTES (SABER_K * SABER_POLYBYTES) +#define SABER_POLYCOMPRESSEDBYTES (SABER_EP * SABER_N / 8) +#define SABER_POLYVECCOMPRESSEDBYTES (SABER_L * SABER_POLYCOMPRESSEDBYTES) -#define SABER_POLYVECCOMPRESSEDBYTES (SABER_K * 320) //10*256/8 NOTE : changed till here due to parameter adaptation - -#define SABER_CIPHERTEXTBYTES (SABER_POLYVECCOMPRESSEDBYTES) - -#define SABER_SCALEBYTES (SABER_DELTA*SABER_N/8) - -#define SABER_SCALEBYTES_KEM ((SABER_ET)*SABER_N/8) +#define SABER_SCALEBYTES_KEM (SABER_ET * SABER_N / 8) #define SABER_INDCPA_PUBLICKEYBYTES (SABER_POLYVECCOMPRESSEDBYTES + SABER_SEEDBYTES) #define SABER_INDCPA_SECRETKEYBYTES (SABER_POLYVECBYTES) #define SABER_PUBLICKEYBYTES (SABER_INDCPA_PUBLICKEYBYTES) +#define SABER_SECRETKEYBYTES (SABER_INDCPA_SECRETKEYBYTES + SABER_INDCPA_PUBLICKEYBYTES + SABER_HASHBYTES + SABER_KEYBYTES) -#define SABER_SECRETKEYBYTES (SABER_INDCPA_SECRETKEYBYTES + SABER_INDCPA_PUBLICKEYBYTES + SABER_HASHBYTES + SABER_KEYBYTES) - -#define SABER_BYTES_CCA_DEC (SABER_POLYVECCOMPRESSEDBYTES + SABER_SCALEBYTES_KEM) /* Second part is for Targhi-Unruh */ - - - +#define SABER_BYTES_CCA_DEC (SABER_POLYVECCOMPRESSEDBYTES + SABER_SCALEBYTES_KEM) #endif - diff --git a/crypto_kem/lightsaber/clean/api.h b/crypto_kem/lightsaber/clean/api.h index 4f73c035..f0fe63f1 100644 --- a/crypto_kem/lightsaber/clean/api.h +++ b/crypto_kem/lightsaber/clean/api.h @@ -1,14 +1,18 @@ #ifndef PQCLEAN_LIGHTSABER_CLEAN_API_H #define PQCLEAN_LIGHTSABER_CLEAN_API_H + #define PQCLEAN_LIGHTSABER_CLEAN_CRYPTO_ALGNAME "LightSaber" -#define PQCLEAN_LIGHTSABER_CLEAN_CRYPTO_SECRETKEYBYTES 1568 -#define PQCLEAN_LIGHTSABER_CLEAN_CRYPTO_PUBLICKEYBYTES (2*320+32) #define PQCLEAN_LIGHTSABER_CLEAN_CRYPTO_BYTES 32 #define PQCLEAN_LIGHTSABER_CLEAN_CRYPTO_CIPHERTEXTBYTES 736 +#define PQCLEAN_LIGHTSABER_CLEAN_CRYPTO_PUBLICKEYBYTES 672 +#define PQCLEAN_LIGHTSABER_CLEAN_CRYPTO_SECRETKEYBYTES 1568 int PQCLEAN_LIGHTSABER_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk); -int PQCLEAN_LIGHTSABER_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk); -int PQCLEAN_LIGHTSABER_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk); + +int PQCLEAN_LIGHTSABER_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *k, const unsigned char *pk); + +int PQCLEAN_LIGHTSABER_CLEAN_crypto_kem_dec(unsigned char *k, const unsigned char *ct, const unsigned char *sk); + #endif /* api_h */ diff --git a/crypto_kem/lightsaber/clean/cbd.c b/crypto_kem/lightsaber/clean/cbd.c index f6ebe4d7..7e3f2be2 100644 --- a/crypto_kem/lightsaber/clean/cbd.c +++ b/crypto_kem/lightsaber/clean/cbd.c @@ -1,3 +1,7 @@ +#include "SABER_params.h" +#include "api.h" +#include "cbd.h" +#include /*--------------------------------------------------------------------- This file has been adapted from the implementation (available at, Public Domain https://github.com/pq-crystals/kyber) @@ -6,12 +10,8 @@ by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint, Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle ----------------------------------------------------------------------*/ -#include "SABER_params.h" -#include "api.h" -#include "cbd.h" -#include -static uint64_t load_littleendian(const unsigned char *x, int bytes) { +static uint64_t load_littleendian(const uint8_t *x, int bytes) { int i; uint64_t r = x[0]; for (i = 1; i < bytes; i++) { @@ -20,10 +20,7 @@ static uint64_t load_littleendian(const unsigned char *x, int bytes) { return r; } - -void PQCLEAN_LIGHTSABER_CLEAN_cbd(uint16_t *r, const unsigned char *buf) { - uint16_t Qmod_minus1 = SABER_Q - 1; - +void PQCLEAN_LIGHTSABER_CLEAN_cbd(uint16_t s[SABER_N], const uint8_t buf[SABER_POLYCOINBYTES]) { uint64_t t, d, a[4], b[4]; int i, j; @@ -34,8 +31,8 @@ void PQCLEAN_LIGHTSABER_CLEAN_cbd(uint16_t *r, const unsigned char *buf) { d += (t >> j) & 0x0842108421UL; } - a[0] = d & 0x1f; - b[0] = (d >> 5) & 0x1f; + a[0] = d & 0x1f; + b[0] = (d >> 5) & 0x1f; a[1] = (d >> 10) & 0x1f; b[1] = (d >> 15) & 0x1f; a[2] = (d >> 20) & 0x1f; @@ -43,9 +40,9 @@ void PQCLEAN_LIGHTSABER_CLEAN_cbd(uint16_t *r, const unsigned char *buf) { a[3] = (d >> 30) & 0x1f; b[3] = (d >> 35); - r[4 * i + 0] = (uint16_t)(a[0] - b[0]) & Qmod_minus1; - r[4 * i + 1] = (uint16_t)(a[1] - b[1]) & Qmod_minus1; - r[4 * i + 2] = (uint16_t)(a[2] - b[2]) & Qmod_minus1; - r[4 * i + 3] = (uint16_t)(a[3] - b[3]) & Qmod_minus1; + s[4 * i + 0] = (uint16_t)(a[0] - b[0]); + s[4 * i + 1] = (uint16_t)(a[1] - b[1]); + s[4 * i + 2] = (uint16_t)(a[2] - b[2]); + s[4 * i + 3] = (uint16_t)(a[3] - b[3]); } } diff --git a/crypto_kem/lightsaber/clean/cbd.h b/crypto_kem/lightsaber/clean/cbd.h index 37553425..dffd4dc5 100644 --- a/crypto_kem/lightsaber/clean/cbd.h +++ b/crypto_kem/lightsaber/clean/cbd.h @@ -1,6 +1,5 @@ #ifndef CBD_H #define CBD_H - /*--------------------------------------------------------------------- This file has been adapted from the implementation (available at, Public Domain https://github.com/pq-crystals/kyber) @@ -8,10 +7,10 @@ of "CRYSTALS – Kyber: a CCA-secure module-lattice-based KEM" by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint, Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle ----------------------------------------------------------------------*/ - -#include "poly.h" +#include "SABER_params.h" #include -void PQCLEAN_LIGHTSABER_CLEAN_cbd(uint16_t *r, const unsigned char *buf); +void PQCLEAN_LIGHTSABER_CLEAN_cbd(uint16_t s[SABER_N], const uint8_t buf[SABER_POLYCOINBYTES]); + #endif diff --git a/crypto_kem/lightsaber/clean/kem.c b/crypto_kem/lightsaber/clean/kem.c index 8aad4302..eb9353b1 100644 --- a/crypto_kem/lightsaber/clean/kem.c +++ b/crypto_kem/lightsaber/clean/kem.c @@ -1,5 +1,6 @@ #include "SABER_indcpa.h" #include "SABER_params.h" +#include "api.h" #include "fips202.h" #include "randombytes.h" #include "verify.h" @@ -7,90 +8,71 @@ #include #include -int PQCLEAN_LIGHTSABER_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk) { + +int PQCLEAN_LIGHTSABER_CLEAN_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) { int i; - // sk[0:SABER_INDCPA_SECRETKEYBYTES-1] <-- sk - PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_keypair(pk, sk); - - // sk[SABER_INDCPA_SECRETKEYBYTES:SABER_INDCPA_SECRETKEYBYTES+SABER_INDCPA_SECRETKEYBYTES-1] <-- pk + PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_keypair(pk, sk); // sk[0:SABER_INDCPA_SECRETKEYBYTES-1] <-- sk for (i = 0; i < SABER_INDCPA_PUBLICKEYBYTES; i++) { - sk[i + SABER_INDCPA_SECRETKEYBYTES] = pk[i]; + sk[i + SABER_INDCPA_SECRETKEYBYTES] = pk[i]; // sk[SABER_INDCPA_SECRETKEYBYTES:SABER_INDCPA_SECRETKEYBYTES+SABER_INDCPA_SECRETKEYBYTES-1] <-- pk } - // Then hash(pk) is appended. - sha3_256(sk + SABER_SECRETKEYBYTES - 64, pk, SABER_INDCPA_PUBLICKEYBYTES); + sha3_256(sk + SABER_SECRETKEYBYTES - 64, pk, SABER_INDCPA_PUBLICKEYBYTES); // Then hash(pk) is appended. - // Remaining part of sk contains a pseudo-random number. - // This is output when check in crypto_kem_dec() fails. - randombytes(sk + SABER_SECRETKEYBYTES - SABER_KEYBYTES, SABER_KEYBYTES ); + randombytes(sk + SABER_SECRETKEYBYTES - SABER_KEYBYTES, SABER_KEYBYTES); // Remaining part of sk contains a pseudo-random number. + // This is output when check in PQCLEAN_LIGHTSABER_CLEAN_crypto_kem_dec() fails. return (0); } -int PQCLEAN_LIGHTSABER_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) { - // Will contain key, coins - unsigned char kr[64]; - unsigned char buf[64]; +int PQCLEAN_LIGHTSABER_CLEAN_crypto_kem_enc(uint8_t *c, uint8_t *k, const uint8_t *pk) { + + uint8_t kr[64]; // Will contain key, coins + uint8_t buf[64]; randombytes(buf, 32); - // BUF[0:31] <-- random message (will be used as the key for client) Note: hash doesnot release system RNG output - sha3_256(buf, buf, 32); + sha3_256(buf, buf, 32); // BUF[0:31] <-- random message (will be used as the key for client) Note: hash doesnot release system RNG output - // BUF[32:63] <-- Hash(public key); Multitarget countermeasure for coins + contributory KEM - sha3_256(buf + 32, pk, SABER_INDCPA_PUBLICKEYBYTES); - - // kr[0:63] <-- Hash(buf[0:63]); - sha3_512(kr, buf, 64); + sha3_256(buf + 32, pk, SABER_INDCPA_PUBLICKEYBYTES); // BUF[32:63] <-- Hash(public key); Multitarget countermeasure for coins + contributory KEM + sha3_512(kr, buf, 64); // kr[0:63] <-- Hash(buf[0:63]); // K^ <-- kr[0:31] // noiseseed (r) <-- kr[32:63]; - // buf[0:31] contains message; kr[32:63] contains randomness r; - PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_enc(buf, kr + 32, pk, ct); + PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_enc(c, buf, kr + 32, pk); // buf[0:31] contains message; kr[32:63] contains randomness r; - sha3_256(kr + 32, ct, SABER_BYTES_CCA_DEC); + sha3_256(kr + 32, c, SABER_BYTES_CCA_DEC); - // hash concatenation of pre-k and h(c) to k - sha3_256(ss, kr, 64); + sha3_256(k, kr, 64); // hash concatenation of pre-k and h(c) to k return (0); } - -int PQCLEAN_LIGHTSABER_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) { +int PQCLEAN_LIGHTSABER_CLEAN_crypto_kem_dec(uint8_t *k, const uint8_t *c, const uint8_t *sk) { int i; - unsigned char fail; - unsigned char cmp[SABER_BYTES_CCA_DEC]; - unsigned char buf[64]; - - // Will contain key, coins - unsigned char kr[64]; - const unsigned char *pk = sk + SABER_INDCPA_SECRETKEYBYTES; - - // buf[0:31] <-- message - PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_dec(sk, ct, buf); + uint8_t fail; + uint8_t cmp[SABER_BYTES_CCA_DEC]; + uint8_t buf[64]; + uint8_t kr[64]; // Will contain key, coins + const uint8_t *pk = sk + SABER_INDCPA_SECRETKEYBYTES; + PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_dec(buf, sk, c); // buf[0:31] <-- message // Multitarget countermeasure for coins + contributory KEM - // Save hash by storing h(pk) in sk - for (i = 0; i < 32; i++) { + for (i = 0; i < 32; i++) { // Save hash by storing h(pk) in sk buf[32 + i] = sk[SABER_SECRETKEYBYTES - 64 + i]; } sha3_512(kr, buf, 64); - PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_enc(buf, kr + 32, pk, cmp); + PQCLEAN_LIGHTSABER_CLEAN_indcpa_kem_enc(cmp, buf, kr + 32, pk); + fail = PQCLEAN_LIGHTSABER_CLEAN_verify(c, cmp, SABER_BYTES_CCA_DEC); - fail = PQCLEAN_LIGHTSABER_CLEAN_verify(ct, cmp, SABER_BYTES_CCA_DEC); - - // overwrite coins in kr with h(c) - sha3_256(kr + 32, ct, SABER_BYTES_CCA_DEC); + sha3_256(kr + 32, c, SABER_BYTES_CCA_DEC); // overwrite coins in kr with h(c) PQCLEAN_LIGHTSABER_CLEAN_cmov(kr, sk + SABER_SECRETKEYBYTES - SABER_KEYBYTES, SABER_KEYBYTES, fail); - // hash concatenation of pre-k and h(c) to k - sha3_256(ss, kr, 64); + sha3_256(k, kr, 64); // hash concatenation of pre-k and h(c) to k return (0); } diff --git a/crypto_kem/lightsaber/clean/pack_unpack.c b/crypto_kem/lightsaber/clean/pack_unpack.c index 4b1c409f..2a39a1d7 100644 --- a/crypto_kem/lightsaber/clean/pack_unpack.c +++ b/crypto_kem/lightsaber/clean/pack_unpack.c @@ -1,254 +1,140 @@ +#include "api.h" #include "pack_unpack.h" +#include -void PQCLEAN_LIGHTSABER_CLEAN_pack_3bit(uint8_t *bytes, const uint16_t *data) { - uint32_t j; - uint32_t offset_data, offset_byte; - +void PQCLEAN_LIGHTSABER_CLEAN_POLT2BS(uint8_t bytes[SABER_SCALEBYTES_KEM], const uint16_t data[SABER_N]) { + size_t j, offset_byte, offset_data; for (j = 0; j < SABER_N / 8; j++) { offset_byte = 3 * j; offset_data = 8 * j; - bytes[offset_byte + 0] = (data[offset_data + 0] & 0x7) | - ((data[offset_data + 1] & 0x7) << 3) | - ((data[offset_data + 2] & 0x3) << 6); - bytes[offset_byte + 1] = ((data[offset_data + 2] >> 2 ) & 0x01) | - ((data[offset_data + 3] & 0x7) << 1) | - ((data[offset_data + 4] & 0x7) << 4) | - (((data[offset_data + 5]) & 0x01) << 7); - bytes[offset_byte + 2] = ((data[offset_data + 5] >> 1 ) & 0x03) | - ((data[offset_data + 6] & 0x7) << 2) | - ((data[offset_data + 7] & 0x7) << 5); + bytes[offset_byte + 0] = (data[offset_data + 0] & 0x7) | ((data[offset_data + 1] & 0x7) << 3) | ((data[offset_data + 2] & 0x3) << 6); + bytes[offset_byte + 1] = ((data[offset_data + 2] >> 2) & 0x01) | ((data[offset_data + 3] & 0x7) << 1) | ((data[offset_data + 4] & 0x7) << 4) | (((data[offset_data + 5]) & 0x01) << 7); + bytes[offset_byte + 2] = ((data[offset_data + 5] >> 1) & 0x03) | ((data[offset_data + 6] & 0x7) << 2) | ((data[offset_data + 7] & 0x7) << 5); } } -void PQCLEAN_LIGHTSABER_CLEAN_un_pack3bit(const uint8_t *bytes, uint16_t *data) { - uint32_t j; - uint32_t offset_data, offset_byte; - +void PQCLEAN_LIGHTSABER_CLEAN_BS2POLT(uint16_t data[SABER_N], const uint8_t bytes[SABER_SCALEBYTES_KEM]) { + size_t j, offset_byte, offset_data; for (j = 0; j < SABER_N / 8; j++) { offset_byte = 3 * j; offset_data = 8 * j; data[offset_data + 0] = (bytes[offset_byte + 0]) & 0x07; - data[offset_data + 1] = ((bytes[offset_byte + 0]) >> 3 ) & 0x07; - data[offset_data + 2] = (((bytes[offset_byte + 0]) >> 6 ) & 0x03) | - (((bytes[offset_byte + 1]) & 0x01) << 2); - data[offset_data + 3] = ((bytes[offset_byte + 1]) >> 1 ) & 0x07; - data[offset_data + 4] = ((bytes[offset_byte + 1]) >> 4 ) & 0x07; - data[offset_data + 5] = (((bytes[offset_byte + 1]) >> 7 ) & 0x01) | - (((bytes[offset_byte + 2]) & 0x03) << 1); + data[offset_data + 1] = ((bytes[offset_byte + 0]) >> 3) & 0x07; + data[offset_data + 2] = (((bytes[offset_byte + 0]) >> 6) & 0x03) | (((bytes[offset_byte + 1]) & 0x01) << 2); + data[offset_data + 3] = ((bytes[offset_byte + 1]) >> 1) & 0x07; + data[offset_data + 4] = ((bytes[offset_byte + 1]) >> 4) & 0x07; + data[offset_data + 5] = (((bytes[offset_byte + 1]) >> 7) & 0x01) | (((bytes[offset_byte + 2]) & 0x03) << 1); data[offset_data + 6] = ((bytes[offset_byte + 2] >> 2) & 0x07); data[offset_data + 7] = ((bytes[offset_byte + 2] >> 5) & 0x07); } } -void PQCLEAN_LIGHTSABER_CLEAN_pack_4bit(uint8_t *bytes, const uint16_t *data) { - uint32_t j; - uint32_t offset_data; - - for (j = 0; j < SABER_N / 2; j++) { - offset_data = 2 * j; - bytes[j] = (data[offset_data] & 0x0f) | - ((data[offset_data + 1] & 0x0f) << 4); - } -} - -void PQCLEAN_LIGHTSABER_CLEAN_un_pack4bit(const unsigned char *bytes, uint16_t *ar) { - uint32_t j; - uint32_t offset_data; - - for (j = 0; j < SABER_N / 2; j++) { - offset_data = 2 * j; - ar[offset_data] = bytes[j] & 0x0f; - ar[offset_data + 1] = (bytes[j] >> 4) & 0x0f; - } -} - -void PQCLEAN_LIGHTSABER_CLEAN_pack_6bit(uint8_t *bytes, const uint16_t *data) { - uint32_t j; - uint32_t offset_data, offset_byte; - - for (j = 0; j < SABER_N / 4; j++) { - offset_byte = 3 * j; - offset_data = 4 * j; - bytes[offset_byte + 0] = (data[offset_data + 0] & 0x3f) | - ((data[offset_data + 1] & 0x03) << 6); - bytes[offset_byte + 1] = ((data[offset_data + 1] >> 2) & 0x0f) | - ((data[offset_data + 2] & 0x0f) << 4); - bytes[offset_byte + 2] = ((data[offset_data + 2] >> 4) & 0x03) | - ((data[offset_data + 3] & 0x3f) << 2); - } -} - - -void PQCLEAN_LIGHTSABER_CLEAN_un_pack6bit(const unsigned char *bytes, uint16_t *data) { - uint32_t j; - uint32_t offset_data, offset_byte; - - for (j = 0; j < SABER_N / 4; j++) { - offset_byte = 3 * j; - offset_data = 4 * j; - data[offset_data + 0] = bytes[offset_byte + 0] & 0x3f; - data[offset_data + 1] = ((bytes[offset_byte + 0] >> 6) & 0x03) | - ((bytes[offset_byte + 1] & 0x0f) << 2); - data[offset_data + 2] = ((bytes[offset_byte + 1] & 0xff) >> 4) | - ((bytes[offset_byte + 2] & 0x03) << 4); - data[offset_data + 3] = ((bytes[offset_byte + 2] & 0xff) >> 2); - } -} - - -static void POLVECp2BS(uint8_t *bytes, uint16_t data[SABER_K][SABER_N]) { - uint32_t i, j; - uint32_t offset_data, offset_byte, offset_byte1; - - for (i = 0; i < SABER_K; i++) { - offset_byte1 = i * (SABER_N * 10) / 8; - for (j = 0; j < SABER_N / 4; j++) { - offset_byte = offset_byte1 + 5 * j; - offset_data = 4 * j; - bytes[offset_byte + 0] = (data[i][offset_data + 0] & (0xff)); - bytes[offset_byte + 1] = ((data[i][offset_data + 0] >> 8) & 0x03) | - ((data[i][offset_data + 1] & 0x3f) << 2); - bytes[offset_byte + 2] = ((data[i][offset_data + 1] >> 6) & 0x0f) | - ((data[i][offset_data + 2] & 0x0f) << 4); - bytes[offset_byte + 3] = ((data[i][offset_data + 2] >> 4) & 0x3f) | - ((data[i][offset_data + 3] & 0x03) << 6); - bytes[offset_byte + 4] = ((data[i][offset_data + 3] >> 2) & 0xff); - } - } -} - -static void BS2POLVECp(const unsigned char *bytes, uint16_t data[SABER_K][SABER_N]) { - uint32_t i, j; - uint32_t offset_data, offset_byte, offset_byte1; - - for (i = 0; i < SABER_K; i++) { - offset_byte1 = i * (SABER_N * 10) / 8; - for (j = 0; j < SABER_N / 4; j++) { - offset_byte = offset_byte1 + 5 * j; - offset_data = 4 * j; - data[i][offset_data + 0] = (bytes[offset_byte + 0] & (0xff)) | - ((bytes[offset_byte + 1] & 0x03) << 8); - data[i][offset_data + 1] = ((bytes[offset_byte + 1] >> 2) & (0x3f)) | - ((bytes[offset_byte + 2] & 0x0f) << 6); - data[i][offset_data + 2] = ((bytes[offset_byte + 2] >> 4) & (0x0f)) | - ((bytes[offset_byte + 3] & 0x3f) << 4); - data[i][offset_data + 3] = ((bytes[offset_byte + 3] >> 6) & (0x03)) | - ((bytes[offset_byte + 4] & 0xff) << 2); - } - } -} - - - -static void POLVECq2BS(uint8_t *bytes, uint16_t data[SABER_K][SABER_N]) { - uint32_t i, j; - uint32_t offset_data, offset_byte, offset_byte1; - - for (i = 0; i < SABER_K; i++) { - offset_byte1 = i * (SABER_N * 13) / 8; - for (j = 0; j < SABER_N / 8; j++) { - offset_byte = offset_byte1 + 13 * j; - offset_data = 8 * j; - bytes[offset_byte + 0] = (data[i][offset_data + 0] & (0xff)); - bytes[offset_byte + 1] = ((data[i][offset_data + 0] >> 8) & 0x1f) | - ((data[i][offset_data + 1] & 0x07) << 5); - bytes[offset_byte + 2] = ((data[i][offset_data + 1] >> 3) & 0xff); - bytes[offset_byte + 3] = ((data[i][offset_data + 1] >> 11) & 0x03) | - ((data[i][offset_data + 2] & 0x3f) << 2); - bytes[offset_byte + 4] = ((data[i][offset_data + 2] >> 6) & 0x7f) | - ((data[i][offset_data + 3] & 0x01) << 7); - bytes[offset_byte + 5] = ((data[i][offset_data + 3] >> 1) & 0xff); - bytes[offset_byte + 6] = ((data[i][offset_data + 3] >> 9) & 0x0f) | - ((data[i][offset_data + 4] & 0x0f) << 4); - bytes[offset_byte + 7] = ((data[i][offset_data + 4] >> 4) & 0xff); - bytes[offset_byte + 8] = ((data[i][offset_data + 4] >> 12) & 0x01) | - ((data[i][offset_data + 5] & 0x7f) << 1); - bytes[offset_byte + 9] = ((data[i][offset_data + 5] >> 7) & 0x3f) | - ((data[i][offset_data + 6] & 0x03) << 6); - bytes[offset_byte + 10] = ((data[i][offset_data + 6] >> 2) & 0xff); - bytes[offset_byte + 11] = ((data[i][offset_data + 6] >> 10) & 0x07) | - ((data[i][offset_data + 7] & 0x1f) << 3); - bytes[offset_byte + 12] = ((data[i][offset_data + 7] >> 5) & 0xff); - } - } -} - -static void BS2POLVECq(const unsigned char *bytes, uint16_t data[SABER_K][SABER_N]) { - uint32_t i, j; - uint32_t offset_data, offset_byte, offset_byte1; - - for (i = 0; i < SABER_K; i++) { - offset_byte1 = i * (SABER_N * 13) / 8; - for (j = 0; j < SABER_N / 8; j++) { - offset_byte = offset_byte1 + 13 * j; - offset_data = 8 * j; - data[i][offset_data + 0] = (bytes[offset_byte + 0] & (0xff)) | - ((bytes[offset_byte + 1] & 0x1f) << 8); - data[i][offset_data + 1] = (bytes[offset_byte + 1] >> 5 & (0x07)) | - ((bytes[offset_byte + 2] & 0xff) << 3) | - ((bytes[offset_byte + 3] & 0x03) << 11); - data[i][offset_data + 2] = (bytes[offset_byte + 3] >> 2 & (0x3f)) | - ((bytes[offset_byte + 4] & 0x7f) << 6); - data[i][offset_data + 3] = (bytes[offset_byte + 4] >> 7 & (0x01)) | - ((bytes[offset_byte + 5] & 0xff) << 1) | - ((bytes[offset_byte + 6] & 0x0f) << 9); - data[i][offset_data + 4] = (bytes[offset_byte + 6] >> 4 & (0x0f)) | - ((bytes[offset_byte + 7] & 0xff) << 4) | - ((bytes[offset_byte + 8] & 0x01) << 12); - data[i][offset_data + 5] = (bytes[offset_byte + 8] >> 1 & (0x7f)) | - ((bytes[offset_byte + 9] & 0x3f) << 7); - data[i][offset_data + 6] = (bytes[offset_byte + 9] >> 6 & (0x03)) | - ((bytes[offset_byte + 10] & 0xff) << 2) | - ((bytes[offset_byte + 11] & 0x07) << 10); - data[i][offset_data + 7] = (bytes[offset_byte + 11] >> 3 & (0x1f)) | - ((bytes[offset_byte + 12] & 0xff) << 5); - } - } -} - -//only BS2POLq no BS2POLp -void PQCLEAN_LIGHTSABER_CLEAN_BS2POL(const unsigned char *bytes, uint16_t data[SABER_N]) { - uint32_t j; - uint32_t offset_data, offset_byte; - +static void POLq2BS(uint8_t bytes[SABER_POLYBYTES], const uint16_t data[SABER_N]) { + size_t j, offset_byte, offset_data; for (j = 0; j < SABER_N / 8; j++) { offset_byte = 13 * j; offset_data = 8 * j; - data[offset_data + 0] = (bytes[offset_byte + 0] & (0xff)) | - ((bytes[offset_byte + 1] & 0x1f) << 8); - data[offset_data + 1] = (bytes[offset_byte + 1] >> 5 & (0x07)) | - ((bytes[offset_byte + 2] & 0xff) << 3) | - ((bytes[offset_byte + 3] & 0x03) << 11); - data[offset_data + 2] = (bytes[offset_byte + 3] >> 2 & (0x3f)) | - ((bytes[offset_byte + 4] & 0x7f) << 6); - data[offset_data + 3] = (bytes[offset_byte + 4] >> 7 & (0x01)) | - ((bytes[offset_byte + 5] & 0xff) << 1) | - ((bytes[offset_byte + 6] & 0x0f) << 9); - data[offset_data + 4] = (bytes[offset_byte + 6] >> 4 & (0x0f)) | - ((bytes[offset_byte + 7] & 0xff) << 4) | - ((bytes[offset_byte + 8] & 0x01) << 12); - data[offset_data + 5] = (bytes[offset_byte + 8] >> 1 & (0x7f)) | - ((bytes[offset_byte + 9] & 0x3f) << 7); - data[offset_data + 6] = (bytes[offset_byte + 9] >> 6 & (0x03)) | - ((bytes[offset_byte + 10] & 0xff) << 2) | - ((bytes[offset_byte + 11] & 0x07) << 10); - data[offset_data + 7] = (bytes[offset_byte + 11] >> 3 & (0x1f)) | - ((bytes[offset_byte + 12] & 0xff) << 5); + bytes[offset_byte + 0] = (data[offset_data + 0] & (0xff)); + bytes[offset_byte + 1] = ((data[offset_data + 0] >> 8) & 0x1f) | ((data[offset_data + 1] & 0x07) << 5); + bytes[offset_byte + 2] = ((data[offset_data + 1] >> 3) & 0xff); + bytes[offset_byte + 3] = ((data[offset_data + 1] >> 11) & 0x03) | ((data[offset_data + 2] & 0x3f) << 2); + bytes[offset_byte + 4] = ((data[offset_data + 2] >> 6) & 0x7f) | ((data[offset_data + 3] & 0x01) << 7); + bytes[offset_byte + 5] = ((data[offset_data + 3] >> 1) & 0xff); + bytes[offset_byte + 6] = ((data[offset_data + 3] >> 9) & 0x0f) | ((data[offset_data + 4] & 0x0f) << 4); + bytes[offset_byte + 7] = ((data[offset_data + 4] >> 4) & 0xff); + bytes[offset_byte + 8] = ((data[offset_data + 4] >> 12) & 0x01) | ((data[offset_data + 5] & 0x7f) << 1); + bytes[offset_byte + 9] = ((data[offset_data + 5] >> 7) & 0x3f) | ((data[offset_data + 6] & 0x03) << 6); + bytes[offset_byte + 10] = ((data[offset_data + 6] >> 2) & 0xff); + bytes[offset_byte + 11] = ((data[offset_data + 6] >> 10) & 0x07) | ((data[offset_data + 7] & 0x1f) << 3); + bytes[offset_byte + 12] = ((data[offset_data + 7] >> 5) & 0xff); } } -void PQCLEAN_LIGHTSABER_CLEAN_POLVEC2BS(uint8_t *bytes, uint16_t data[SABER_K][SABER_N], uint16_t modulus) { - if (modulus == 1024) { - POLVECp2BS(bytes, data); - } else if (modulus == 8192) { - POLVECq2BS(bytes, data); +static void BS2POLq(uint16_t data[SABER_N], const uint8_t bytes[SABER_POLYBYTES]) { + size_t j, offset_byte, offset_data; + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = 13 * j; + offset_data = 8 * j; + data[offset_data + 0] = (bytes[offset_byte + 0] & (0xff)) | ((bytes[offset_byte + 1] & 0x1f) << 8); + data[offset_data + 1] = (bytes[offset_byte + 1] >> 5 & (0x07)) | ((bytes[offset_byte + 2] & 0xff) << 3) | ((bytes[offset_byte + 3] & 0x03) << 11); + data[offset_data + 2] = (bytes[offset_byte + 3] >> 2 & (0x3f)) | ((bytes[offset_byte + 4] & 0x7f) << 6); + data[offset_data + 3] = (bytes[offset_byte + 4] >> 7 & (0x01)) | ((bytes[offset_byte + 5] & 0xff) << 1) | ((bytes[offset_byte + 6] & 0x0f) << 9); + data[offset_data + 4] = (bytes[offset_byte + 6] >> 4 & (0x0f)) | ((bytes[offset_byte + 7] & 0xff) << 4) | ((bytes[offset_byte + 8] & 0x01) << 12); + data[offset_data + 5] = (bytes[offset_byte + 8] >> 1 & (0x7f)) | ((bytes[offset_byte + 9] & 0x3f) << 7); + data[offset_data + 6] = (bytes[offset_byte + 9] >> 6 & (0x03)) | ((bytes[offset_byte + 10] & 0xff) << 2) | ((bytes[offset_byte + 11] & 0x07) << 10); + data[offset_data + 7] = (bytes[offset_byte + 11] >> 3 & (0x1f)) | ((bytes[offset_byte + 12] & 0xff) << 5); } } -void PQCLEAN_LIGHTSABER_CLEAN_BS2POLVEC(const unsigned char *bytes, uint16_t data[SABER_K][SABER_N], uint16_t modulus) { - if (modulus == 1024) { - BS2POLVECp(bytes, data); - } else if (modulus == 8192) { - BS2POLVECq(bytes, data); +static void POLp2BS(uint8_t bytes[SABER_POLYCOMPRESSEDBYTES], const uint16_t data[SABER_N]) { + size_t j, offset_byte, offset_data; + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = 5 * j; + offset_data = 4 * j; + bytes[offset_byte + 0] = (data[offset_data + 0] & (0xff)); + bytes[offset_byte + 1] = ((data[offset_data + 0] >> 8) & 0x03) | ((data[offset_data + 1] & 0x3f) << 2); + bytes[offset_byte + 2] = ((data[offset_data + 1] >> 6) & 0x0f) | ((data[offset_data + 2] & 0x0f) << 4); + bytes[offset_byte + 3] = ((data[offset_data + 2] >> 4) & 0x3f) | ((data[offset_data + 3] & 0x03) << 6); + bytes[offset_byte + 4] = ((data[offset_data + 3] >> 2) & 0xff); + } +} + +static void BS2POLp(uint16_t data[SABER_N], const uint8_t bytes[SABER_POLYCOMPRESSEDBYTES]) { + size_t j, offset_byte, offset_data; + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = 5 * j; + offset_data = 4 * j; + data[offset_data + 0] = (bytes[offset_byte + 0] & (0xff)) | ((bytes[offset_byte + 1] & 0x03) << 8); + data[offset_data + 1] = ((bytes[offset_byte + 1] >> 2) & (0x3f)) | ((bytes[offset_byte + 2] & 0x0f) << 6); + data[offset_data + 2] = ((bytes[offset_byte + 2] >> 4) & (0x0f)) | ((bytes[offset_byte + 3] & 0x3f) << 4); + data[offset_data + 3] = ((bytes[offset_byte + 3] >> 6) & (0x03)) | ((bytes[offset_byte + 4] & 0xff) << 2); + } +} + +void PQCLEAN_LIGHTSABER_CLEAN_POLVECq2BS(uint8_t bytes[SABER_POLYVECBYTES], const uint16_t data[SABER_L][SABER_N]) { + size_t i; + for (i = 0; i < SABER_L; i++) { + POLq2BS(bytes + i * SABER_POLYBYTES, data[i]); + } +} + +void PQCLEAN_LIGHTSABER_CLEAN_BS2POLVECq(uint16_t data[SABER_L][SABER_N], const uint8_t bytes[SABER_POLYVECBYTES]) { + size_t i; + for (i = 0; i < SABER_L; i++) { + BS2POLq(data[i], bytes + i * SABER_POLYBYTES); + } +} + +void PQCLEAN_LIGHTSABER_CLEAN_POLVECp2BS(uint8_t bytes[SABER_POLYVECCOMPRESSEDBYTES], const uint16_t data[SABER_L][SABER_N]) { + size_t i; + for (i = 0; i < SABER_L; i++) { + POLp2BS(bytes + i * (SABER_EP * SABER_N / 8), data[i]); + } +} + +void PQCLEAN_LIGHTSABER_CLEAN_BS2POLVECp(uint16_t data[SABER_L][SABER_N], const uint8_t bytes[SABER_POLYVECCOMPRESSEDBYTES]) { + size_t i; + for (i = 0; i < SABER_L; i++) { + BS2POLp(data[i], bytes + i * (SABER_EP * SABER_N / 8)); + } +} + +void PQCLEAN_LIGHTSABER_CLEAN_BS2POLmsg(uint16_t data[SABER_N], const uint8_t bytes[SABER_KEYBYTES]) { + size_t i, j; + for (j = 0; j < SABER_KEYBYTES; j++) { + for (i = 0; i < 8; i++) { + data[j * 8 + i] = ((bytes[j] >> i) & 0x01); + } + } +} + +void PQCLEAN_LIGHTSABER_CLEAN_POLmsg2BS(uint8_t bytes[SABER_KEYBYTES], const uint16_t data[SABER_N]) { + size_t i, j; + memset(bytes, 0, SABER_KEYBYTES); + + for (j = 0; j < SABER_KEYBYTES; j++) { + for (i = 0; i < 8; i++) { + bytes[j] = bytes[j] | ((data[j * 8 + i] & 0x01) << i); + } } } diff --git a/crypto_kem/lightsaber/clean/pack_unpack.h b/crypto_kem/lightsaber/clean/pack_unpack.h index 86fd2fad..44ccf31a 100644 --- a/crypto_kem/lightsaber/clean/pack_unpack.h +++ b/crypto_kem/lightsaber/clean/pack_unpack.h @@ -1,28 +1,27 @@ #ifndef PACK_UNPACK_H #define PACK_UNPACK_H - #include "SABER_params.h" #include #include +void PQCLEAN_LIGHTSABER_CLEAN_POLT2BS(uint8_t bytes[SABER_SCALEBYTES_KEM], const uint16_t data[SABER_N]); -void PQCLEAN_LIGHTSABER_CLEAN_pack_3bit(uint8_t *bytes, const uint16_t *data); - -void PQCLEAN_LIGHTSABER_CLEAN_un_pack3bit(const uint8_t *bytes, uint16_t *data); - -void PQCLEAN_LIGHTSABER_CLEAN_pack_4bit(uint8_t *bytes, const uint16_t *data); - -void PQCLEAN_LIGHTSABER_CLEAN_un_pack4bit(const unsigned char *bytes, uint16_t *ar); - -void PQCLEAN_LIGHTSABER_CLEAN_pack_6bit(uint8_t *bytes, const uint16_t *data); - -void PQCLEAN_LIGHTSABER_CLEAN_un_pack6bit(const unsigned char *bytes, uint16_t *data); +void PQCLEAN_LIGHTSABER_CLEAN_BS2POLT(uint16_t data[SABER_N], const uint8_t bytes[SABER_SCALEBYTES_KEM]); -void PQCLEAN_LIGHTSABER_CLEAN_BS2POL(const unsigned char *bytes, uint16_t data[SABER_N]); +void PQCLEAN_LIGHTSABER_CLEAN_POLVECq2BS(uint8_t bytes[SABER_POLYVECBYTES], const uint16_t data[SABER_L][SABER_N]); -void PQCLEAN_LIGHTSABER_CLEAN_POLVEC2BS(uint8_t *bytes, uint16_t data[SABER_K][SABER_N], uint16_t modulus); +void PQCLEAN_LIGHTSABER_CLEAN_POLVECp2BS(uint8_t bytes[SABER_POLYVECCOMPRESSEDBYTES], const uint16_t data[SABER_L][SABER_N]); + + +void PQCLEAN_LIGHTSABER_CLEAN_BS2POLVECq(uint16_t data[SABER_L][SABER_N], const uint8_t bytes[SABER_POLYVECBYTES]); + +void PQCLEAN_LIGHTSABER_CLEAN_BS2POLVECp(uint16_t data[SABER_L][SABER_N], const uint8_t bytes[SABER_POLYVECCOMPRESSEDBYTES]); + + +void PQCLEAN_LIGHTSABER_CLEAN_BS2POLmsg(uint16_t data[SABER_N], const uint8_t bytes[SABER_KEYBYTES]); + +void PQCLEAN_LIGHTSABER_CLEAN_POLmsg2BS(uint8_t bytes[SABER_KEYBYTES], const uint16_t data[SABER_N]); -void PQCLEAN_LIGHTSABER_CLEAN_BS2POLVEC(const unsigned char *bytes, uint16_t data[SABER_K][SABER_N], uint16_t modulus); #endif diff --git a/crypto_kem/lightsaber/clean/poly.c b/crypto_kem/lightsaber/clean/poly.c index fc86ab3c..1c1e22cc 100644 --- a/crypto_kem/lightsaber/clean/poly.c +++ b/crypto_kem/lightsaber/clean/poly.c @@ -1,21 +1,49 @@ -/*--------------------------------------------------------------------- -This file has been adapted from the implementation -(available at, Public Domain https://github.com/pq-crystals/kyber) -of "CRYSTALS – Kyber: a CCA-secure module-lattice-based KEM" -by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint, -Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle -----------------------------------------------------------------------*/ -#include "SABER_params.h" +#include "api.h" #include "cbd.h" #include "fips202.h" +#include "pack_unpack.h" #include "poly.h" +#include "poly_mul.h" +#include -void PQCLEAN_LIGHTSABER_CLEAN_GenSecret(uint16_t r[SABER_K][SABER_N], const unsigned char *seed) { - uint8_t buf[SABER_MU * SABER_N * SABER_K / 8]; - - shake128(buf, sizeof(buf), seed, SABER_NOISESEEDBYTES); - - for (size_t i = 0; i < SABER_K; i++) { - PQCLEAN_LIGHTSABER_CLEAN_cbd(r[i], buf + i * SABER_MU * SABER_N / 8); +void PQCLEAN_LIGHTSABER_CLEAN_MatrixVectorMul(uint16_t res[SABER_L][SABER_N], const uint16_t A[SABER_L][SABER_L][SABER_N], const uint16_t s[SABER_L][SABER_N], int16_t transpose) { + int i, j; + for (i = 0; i < SABER_L; i++) { + for (j = 0; j < SABER_L; j++) { + if (transpose == 1) { + PQCLEAN_LIGHTSABER_CLEAN_poly_mul_acc(A[j][i], s[j], res[i]); + } else { + PQCLEAN_LIGHTSABER_CLEAN_poly_mul_acc(A[i][j], s[j], res[i]); + } + } + } +} + +void PQCLEAN_LIGHTSABER_CLEAN_InnerProd(uint16_t res[SABER_N], const uint16_t b[SABER_L][SABER_N], const uint16_t s[SABER_L][SABER_N]) { + int j; + for (j = 0; j < SABER_L; j++) { + PQCLEAN_LIGHTSABER_CLEAN_poly_mul_acc(b[j], s[j], res); + } +} + +void PQCLEAN_LIGHTSABER_CLEAN_GenMatrix(uint16_t A[SABER_L][SABER_L][SABER_N], const uint8_t seed[SABER_SEEDBYTES]) { + uint8_t buf[SABER_L * SABER_POLYVECBYTES]; + int i; + + shake128(buf, sizeof(buf), seed, SABER_SEEDBYTES); + + for (i = 0; i < SABER_L; i++) { + PQCLEAN_LIGHTSABER_CLEAN_BS2POLVECq(A[i], buf + i * SABER_POLYVECBYTES); + } +} + +void PQCLEAN_LIGHTSABER_CLEAN_GenSecret(uint16_t s[SABER_L][SABER_N], const uint8_t seed[SABER_NOISE_SEEDBYTES]) { + uint8_t buf[SABER_L * SABER_POLYCOINBYTES]; + size_t i; + + shake128(buf, sizeof(buf), seed, SABER_NOISE_SEEDBYTES); + + for (i = 0; i < SABER_L; i++) { + PQCLEAN_LIGHTSABER_CLEAN_cbd(s[i], buf + i * SABER_POLYCOINBYTES); } } diff --git a/crypto_kem/lightsaber/clean/poly.h b/crypto_kem/lightsaber/clean/poly.h index 47ceeebb..1f50c48e 100644 --- a/crypto_kem/lightsaber/clean/poly.h +++ b/crypto_kem/lightsaber/clean/poly.h @@ -1,26 +1,15 @@ #ifndef POLY_H #define POLY_H - -/*--------------------------------------------------------------------- -This file has been adapted from the implementation -(available at, Public Domain https://github.com/pq-crystals/kyber) -of "CRYSTALS – Kyber: a CCA-secure module-lattice-based KEM" -by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint, -Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle -----------------------------------------------------------------------*/ - - #include "SABER_params.h" #include -typedef struct { - uint16_t coeffs[SABER_N]; -} poly; +void PQCLEAN_LIGHTSABER_CLEAN_MatrixVectorMul(uint16_t res[SABER_L][SABER_N], const uint16_t a[SABER_L][SABER_L][SABER_N], const uint16_t s[SABER_L][SABER_N], int16_t transpose); -typedef struct { - poly vec[SABER_K]; -} polyvec; +void PQCLEAN_LIGHTSABER_CLEAN_InnerProd(uint16_t res[SABER_N], const uint16_t b[SABER_L][SABER_N], const uint16_t s[SABER_L][SABER_N]); + +void PQCLEAN_LIGHTSABER_CLEAN_GenMatrix(uint16_t a[SABER_L][SABER_L][SABER_N], const uint8_t seed[SABER_SEEDBYTES]); + +void PQCLEAN_LIGHTSABER_CLEAN_GenSecret(uint16_t s[SABER_L][SABER_N], const uint8_t seed[SABER_NOISE_SEEDBYTES]); -void PQCLEAN_LIGHTSABER_CLEAN_GenSecret(uint16_t r[SABER_K][SABER_N], const unsigned char *seed); #endif diff --git a/crypto_kem/lightsaber/clean/poly_mul.c b/crypto_kem/lightsaber/clean/poly_mul.c index 926910b5..5e37a024 100644 --- a/crypto_kem/lightsaber/clean/poly_mul.c +++ b/crypto_kem/lightsaber/clean/poly_mul.c @@ -228,19 +228,15 @@ static void toom_cook_4way (const uint16_t *a1, const uint16_t *b1, uint16_t *re } } -void PQCLEAN_LIGHTSABER_CLEAN_pol_mul(uint16_t *a, uint16_t *b, uint16_t *res, uint16_t p, uint32_t n) { - uint32_t i; - // normal multiplication - uint16_t c[512]; - - for (i = 0; i < 512; i++) { - c[i] = 0; - } +/* res += a*b */ +void PQCLEAN_LIGHTSABER_CLEAN_poly_mul_acc(const uint16_t a[SABER_N], const uint16_t b[SABER_N], uint16_t res[SABER_N]) { + uint16_t c[2 * SABER_N] = {0}; + int i; toom_cook_4way(a, b, c); - // reduction - for (i = n; i < 2 * n; i++) { - res[i - n] = (c[i - n] - c[i]) & (p - 1); + /* reduction */ + for (i = SABER_N; i < 2 * SABER_N; i++) { + res[i - SABER_N] += (c[i - SABER_N] - c[i]); } } diff --git a/crypto_kem/lightsaber/clean/poly_mul.h b/crypto_kem/lightsaber/clean/poly_mul.h index 8d634584..0d5cf6ed 100644 --- a/crypto_kem/lightsaber/clean/poly_mul.h +++ b/crypto_kem/lightsaber/clean/poly_mul.h @@ -1,9 +1,9 @@ -#ifndef POLYMUL_H -#define POLYMUL_H - +#ifndef POLY_MUL_H +#define POLY_MUL_H #include "SABER_params.h" #include -void PQCLEAN_LIGHTSABER_CLEAN_pol_mul(uint16_t *a, uint16_t *b, uint16_t *res, uint16_t p, uint32_t n); +void PQCLEAN_LIGHTSABER_CLEAN_poly_mul_acc(const uint16_t a[SABER_N], const uint16_t b[SABER_N], uint16_t res[SABER_N]); + #endif diff --git a/crypto_kem/lightsaber/clean/verify.c b/crypto_kem/lightsaber/clean/verify.c index 52c6969b..05e564da 100644 --- a/crypto_kem/lightsaber/clean/verify.c +++ b/crypto_kem/lightsaber/clean/verify.c @@ -1,3 +1,5 @@ +#include "verify.h" + /*------------------------------------------------- This file has been adapted from the implementation (available at https://github.com/pq-crystals/kyber) of @@ -5,26 +7,25 @@ This file has been adapted from the implementation by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint, Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle ----------------------------------------------------*/ -#include "verify.h" -#include + /* returns 0 for equal strings, 1 for non-equal strings */ -unsigned char PQCLEAN_LIGHTSABER_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len) { +uint8_t PQCLEAN_LIGHTSABER_CLEAN_verify(const uint8_t *a, const uint8_t *b, size_t len) { uint64_t r; size_t i; - r = 0; + for (i = 0; i < len; i++) { r |= a[i] ^ b[i]; } r = (~r + 1); // Two's complement r >>= 63; - return (unsigned char)r; + return (uint8_t) r; } /* b = 1 means mov, b = 0 means don't mov*/ -void PQCLEAN_LIGHTSABER_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b) { +void PQCLEAN_LIGHTSABER_CLEAN_cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b) { size_t i; b = -b; diff --git a/crypto_kem/lightsaber/clean/verify.h b/crypto_kem/lightsaber/clean/verify.h index 32c2adb5..4f538e6f 100644 --- a/crypto_kem/lightsaber/clean/verify.h +++ b/crypto_kem/lightsaber/clean/verify.h @@ -1,6 +1,5 @@ #ifndef VERIFY_H #define VERIFY_H - /*------------------------------------------------- This file has been adapted from the implementation (available at https://github.com/pq-crystals/kyber) of @@ -13,9 +12,11 @@ Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle #include /* returns 0 for equal strings, 1 for non-equal strings */ -unsigned char PQCLEAN_LIGHTSABER_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len); +uint8_t PQCLEAN_LIGHTSABER_CLEAN_verify(const uint8_t *a, const uint8_t *b, size_t len); + /* b = 1 means mov, b = 0 means don't mov*/ -void PQCLEAN_LIGHTSABER_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b); +void PQCLEAN_LIGHTSABER_CLEAN_cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b); + #endif diff --git a/crypto_kem/saber/META.yml b/crypto_kem/saber/META.yml index 4de4f1c8..50250180 100644 --- a/crypto_kem/saber/META.yml +++ b/crypto_kem/saber/META.yml @@ -14,4 +14,13 @@ principal-submitters: - Frederik Vercauteren implementations: - name: clean - version: https://github.com/KULeuven-COSIC/SABER/commit/14ede83f1ff3bcc41f0464543542366c68b55871 + version: https://github.com/KULeuven-COSIC/SABER/commit/509cc5ec3a7e12a751ccdd2ef5bd6e54e00bd350 + - name: avx2 + version: https://github.com/KULeuven-COSIC/SABER/commit/509cc5ec3a7e12a751ccdd2ef5bd6e54e00bd350 + supported_platforms: + - architecture: x86_64 + operating_systems: + - Linux + - Darwin + required_flags: + - avx2 diff --git a/crypto_kem/saber/avx2/LICENSE b/crypto_kem/saber/avx2/LICENSE new file mode 100644 index 00000000..d5d21fff --- /dev/null +++ b/crypto_kem/saber/avx2/LICENSE @@ -0,0 +1 @@ +Public Domain diff --git a/crypto_kem/saber/avx2/Makefile b/crypto_kem/saber/avx2/Makefile new file mode 100644 index 00000000..65cc21ef --- /dev/null +++ b/crypto_kem/saber/avx2/Makefile @@ -0,0 +1,22 @@ +# This Makefile can be used with GNU Make or BSD Make + +LIB=libsaber_avx2.a +HEADERS=api.h cbd.h kem.h pack_unpack.h poly.h SABER_indcpa.h SABER_params.h verify.h +OBJECTS=cbd.o kem.o pack_unpack.o SABER_indcpa.o verify.o + +CFLAGS=-O3 -mavx2 -Wall -Wextra -Wpedantic -Wvla -Werror -Wredundant-decls -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) + +all: $(LIB) + +%.o: %.s $(HEADERS) + $(AS) -o $@ $< + +%.o: %.c $(HEADERS) + $(CC) $(CFLAGS) -c -o $@ $< + +$(LIB): $(OBJECTS) + $(AR) -r $@ $(OBJECTS) + +clean: + $(RM) $(OBJECTS) + $(RM) $(LIB) diff --git a/crypto_kem/saber/avx2/SABER_indcpa.c b/crypto_kem/saber/avx2/SABER_indcpa.c new file mode 100644 index 00000000..d16a7a06 --- /dev/null +++ b/crypto_kem/saber/avx2/SABER_indcpa.c @@ -0,0 +1,416 @@ +#include "./polymul/toom-cook_4way.c" +#include "SABER_indcpa.h" +#include "SABER_params.h" +#include "api.h" +#include "cbd.h" +#include "fips202.h" +#include "pack_unpack.h" +#include "randombytes.h" +#include +#include +#include +//#include "randombytes.h" +//#include "./polymul/toom_cook_4/toom-cook_4way.c" + +#define h1 4 //2^(EQ-EP-1) + +#define h2 ( (1<<(SABER_EP-2)) - (1<<(SABER_EP-SABER_ET-1)) + (1<<(SABER_EQ-SABER_EP-1)) ) + + +static void POL2MSG(uint8_t *message_dec, const uint16_t *message_dec_unpacked) { + int32_t i, j; + + for (j = 0; j < SABER_KEYBYTES; j++) { + message_dec[j] = 0; + for (i = 0; i < 8; i++) { + message_dec[j] = message_dec[j] | (message_dec_unpacked[j * 8 + i] << i); + } + } +} + +/*----------------------------------------------------------------------------------- + This routine generates a=[Matrix K x K] of 256-coefficient polynomials +-------------------------------------------------------------------------------------*/ + +static void GenMatrix(polyvec *a, const uint8_t *seed) { + uint8_t buf[SABER_K * SABER_K * 13 * SABER_N / 8]; + + uint16_t temp_ar[SABER_N]; + + int i, j, k; + uint16_t mod = (SABER_Q - 1); + + shake128(buf, sizeof(buf), seed, SABER_SEEDBYTES); + + for (i = 0; i < SABER_K; i++) { + for (j = 0; j < SABER_K; j++) { + PQCLEAN_SABER_AVX2_BS2POLq(temp_ar, buf + (i * SABER_K + j) * 13 * SABER_N / 8); + for (k = 0; k < SABER_N; k++) { + a[i].vec[j].coeffs[k] = (temp_ar[k])& mod ; + } + } + } +} + +static void GenSecret(uint16_t r[SABER_K][SABER_N], const uint8_t *seed) { + + uint32_t i; + + uint8_t buf[SABER_MU * SABER_N * SABER_K / 8]; + + shake128(buf, sizeof(buf), seed, SABER_NOISESEEDBYTES); + + for (i = 0; i < SABER_K; i++) { + PQCLEAN_SABER_AVX2_cbd(r[i], buf + i * SABER_MU * SABER_N / 8); + } +} + +//********************************matrix-vector mul routines***************************************************** +static void matrix_vector_mul(__m256i a1_avx_combined[NUM_POLY][NUM_POLY][AVX_N1], __m256i b_bucket[NUM_POLY][SCHB_N * 4], __m256i res_avx[NUM_POLY][AVX_N1], int isTranspose) { + int64_t i, j; + + __m256i c_bucket[2 * SCM_SIZE * 4]; //Holds results for 9 Karatsuba at a time + + for (i = 0; i < NUM_POLY; i++) { + for (j = 0; j < NUM_POLY; j++) { + + if (isTranspose == 0) { + toom_cook_4way_avx_n1(a1_avx_combined[i][j], b_bucket[j], c_bucket, j); + } else { + toom_cook_4way_avx_n1(a1_avx_combined[j][i], b_bucket[j], c_bucket, j); + } + } + + TC_interpol(c_bucket, res_avx[i]); + } + +} + +static void vector_vector_mul(__m256i a_avx[NUM_POLY][AVX_N1], __m256i b_bucket[NUM_POLY][SCHB_N * 4], __m256i res_avx[AVX_N1]) { + + int64_t i; + + __m256i c_bucket[2 * SCM_SIZE * 4]; //Holds results for 9 Karatsuba at a time + + for (i = 0; i < NUM_POLY; i++) { + toom_cook_4way_avx_n1(a_avx[i], b_bucket[i], c_bucket, i); + } + TC_interpol(c_bucket, res_avx); +} + +//********************************matrix-vector mul routines***************************************************** + +void PQCLEAN_SABER_AVX2_indcpa_kem_keypair(uint8_t *pk, uint8_t *sk) { + + polyvec a[SABER_K]; + + uint16_t skpv1[SABER_K][SABER_N]; + + + + uint8_t seed[SABER_SEEDBYTES]; + uint8_t noiseseed[SABER_COINBYTES]; + int32_t i, j, k; + + +//--------------AVX declaration------------------ + + __m256i sk_avx[SABER_K][SABER_N / 16]; + __m256i mod; + __m256i res_avx[SABER_K][SABER_N / 16]; + __m256i a_avx[SABER_K][SABER_K][SABER_N / 16]; + //__m256i acc[2*SABER_N/16]; + + mod = _mm256_set1_epi16(SABER_Q - 1); + + __m256i b_bucket[NUM_POLY][SCHB_N * 4]; + +//--------------AVX declaration ends------------------ + + randombytes(seed, SABER_SEEDBYTES); + + shake128(seed, SABER_SEEDBYTES, seed, SABER_SEEDBYTES); // for not revealing system RNG state + randombytes(noiseseed, SABER_COINBYTES); + + + GenMatrix(a, seed); //sample matrix A + + GenSecret(skpv1, noiseseed); + + +// Load sk into avx vectors + for (i = 0; i < SABER_K; i++) { + for (j = 0; j < SABER_N / 16; j++) { + sk_avx[i][j] = _mm256_loadu_si256 ((__m256i const *) (&skpv1[i][j * 16])); + } + + } + + // Load a into avx vectors + for (i = 0; i < SABER_K; i++) { + for (j = 0; j < SABER_K; j++) { + for (k = 0; k < SABER_N / 16; k++) { + a_avx[i][j][k] = _mm256_loadu_si256 ((__m256i const *) (&a[i].vec[j].coeffs[k * 16])); + } + } + } + + + + //------------------------do the matrix vector multiplication and rounding------------ + + for (j = 0; j < NUM_POLY; j++) { + TC_eval(sk_avx[j], b_bucket[j]); + } + matrix_vector_mul(a_avx, b_bucket, res_avx, 1);// Matrix-vector multiplication; Matrix in transposed order + + // Now truncation + + + for (i = 0; i < SABER_K; i++) { //shift right EQ-EP bits + for (j = 0; j < SABER_N / 16; j++) { + res_avx[i][j] = _mm256_add_epi16 (res_avx[i][j], _mm256_set1_epi16(h1)); + res_avx[i][j] = _mm256_srli_epi16 (res_avx[i][j], (SABER_EQ - SABER_EP) ); + res_avx[i][j] = _mm256_and_si256 (res_avx[i][j], mod); + } + } + + //------------------Pack sk into byte string------- + + PQCLEAN_SABER_AVX2_POLVEC2BS(sk, (const uint16_t (*)[SABER_N])skpv1, SABER_Q); + + //------------------Pack pk into byte string------- + + for (i = 0; i < SABER_K; i++) { // reuses skpv1[] for unpacking avx of public-key + for (j = 0; j < SABER_N / 16; j++) { + _mm256_maskstore_epi32 ((int *) (skpv1[i] + j * 16), _mm256_set1_epi32(-1), res_avx[i][j]); + } + } + PQCLEAN_SABER_AVX2_POLVEC2BS(pk, (const uint16_t (*)[SABER_N])skpv1, SABER_P); // load the public-key into pk byte string + + + for (i = 0; i < SABER_SEEDBYTES; i++) { // now load the seedbytes in PK. Easy since seed bytes are kept in byte format. + pk[SABER_POLYVECCOMPRESSEDBYTES + i] = seed[i]; + } + +} + + +void PQCLEAN_SABER_AVX2_indcpa_kem_enc(uint8_t ciphertext[SABER_BYTES_CCA_DEC], const uint8_t m[SABER_KEYBYTES], const uint8_t noiseseed[SABER_NOISESEEDBYTES], const uint8_t pk[SABER_INDCPA_PUBLICKEYBYTES]) { + + + uint32_t i, j, k; + polyvec a[SABER_K]; // skpv; + uint8_t seed[SABER_SEEDBYTES]; + uint16_t pkcl[SABER_K][SABER_N]; //public key of received by the client + + + uint16_t skpv1[SABER_K][SABER_N]; + uint16_t temp[SABER_K][SABER_N]; + uint16_t message[SABER_KEYBYTES * 8]; + + uint8_t msk_c[SABER_SCALEBYTES_KEM]; + + //--------------AVX declaration------------------ + + __m256i sk_avx[SABER_K][SABER_N / 16]; + __m256i mod, mod_p; + __m256i res_avx[SABER_K][SABER_N / 16]; + __m256i vprime_avx[SABER_N / 16]; + __m256i a_avx[SABER_K][SABER_K][SABER_N / 16]; + //__m256i acc[2*SABER_N/16]; + + __m256i pkcl_avx[SABER_K][SABER_N / 16]; + + __m256i message_avx[SABER_N / 16]; + + mod = _mm256_set1_epi16(SABER_Q - 1); + mod_p = _mm256_set1_epi16(SABER_P - 1); + + + + __m256i b_bucket[NUM_POLY][SCHB_N * 4]; + + //--------------AVX declaration ends------------------ + for (i = 0; i < SABER_SEEDBYTES; i++) { // Load the seedbytes in the client seed from PK. + seed[i] = pk[ SABER_POLYVECCOMPRESSEDBYTES + i]; + } + + GenMatrix(a, seed); + GenSecret(skpv1, noiseseed); + + // ----------- Load skpv1 into avx vectors ---------- + for (i = 0; i < SABER_K; i++) { + for (j = 0; j < SABER_N / 16; j++) { + sk_avx[i][j] = _mm256_loadu_si256 ((__m256i const *) (&skpv1[i][j * 16])); + } + } + + // ----------- Load skpv1 into avx vectors ---------- + for (i = 0; i < SABER_K; i++) { + for (j = 0; j < SABER_K; j++) { + for (k = 0; k < SABER_N / 16; k++) { + a_avx[i][j][k] = _mm256_loadu_si256 ((__m256i const *) (&a[i].vec[j].coeffs[k * 16])); + } + } + } + //-----------------matrix-vector multiplication and rounding + + for (j = 0; j < NUM_POLY; j++) { + TC_eval(sk_avx[j], b_bucket[j]); + } + matrix_vector_mul(a_avx, b_bucket, res_avx, 0);// Matrix-vector multiplication; Matrix in normal order + + // Now truncation + + for (i = 0; i < SABER_K; i++) { //shift right EQ-EP bits + for (j = 0; j < SABER_N / 16; j++) { + res_avx[i][j] = _mm256_add_epi16 (res_avx[i][j], _mm256_set1_epi16(h1)); + res_avx[i][j] = _mm256_srli_epi16 (res_avx[i][j], (SABER_EQ - SABER_EP) ); + res_avx[i][j] = _mm256_and_si256 (res_avx[i][j], mod); + + } + } + + + //-----this result should be put in b_prime for later use in server. + for (i = 0; i < SABER_K; i++) { // first store in 16 bit arrays + for (j = 0; j < SABER_N / 16; j++) { + _mm256_maskstore_epi32 ((int *)(temp[i] + j * 16), _mm256_set1_epi32(-1), res_avx[i][j]); + } + } + + PQCLEAN_SABER_AVX2_POLVEC2BS(ciphertext, (const uint16_t (*)[SABER_N])temp, SABER_P); // Pack b_prime into ciphertext byte string + +//**************client matrix-vector multiplication ends******************// + + //------now calculate the v' + + //-------unpack the public_key + PQCLEAN_SABER_AVX2_BS2POLVEC(pkcl, pk, SABER_P); + + for (i = 0; i < SABER_K; i++) { + for (j = 0; j < SABER_N / 16; j++) { + pkcl_avx[i][j] = _mm256_loadu_si256 ((__m256i const *) (&pkcl[i][j * 16])); + } + } + + // InnerProduct + //for(k=0;k> i) & 0x01); + } + } + // message encoding + for (i = 0; i < SABER_N / 16; i++) { + message_avx[i] = _mm256_loadu_si256 ((__m256i const *) (&message[i * 16])); + message_avx[i] = _mm256_slli_epi16 (message_avx[i], (SABER_EP - 1) ); + } + + // SHIFTRIGHT(v'+h1-m mod p, EP-ET) + for (k = 0; k < SABER_N / 16; k++) { + vprime_avx[k] = _mm256_sub_epi16(vprime_avx[k], message_avx[k]); + vprime_avx[k] = _mm256_and_si256(vprime_avx[k], mod_p); + vprime_avx[k] = _mm256_srli_epi16 (vprime_avx[k], (SABER_EP - SABER_ET) ); + } + + // Unpack avx + for (j = 0; j < SABER_N / 16; j++) { + _mm256_maskstore_epi32 ((int *) (temp[0] + j * 16), _mm256_set1_epi32(-1), vprime_avx[j]); + } + + PQCLEAN_SABER_AVX2_SABER_pack_4bit(msk_c, temp[0]); + + + for (j = 0; j < SABER_SCALEBYTES_KEM; j++) { + ciphertext[SABER_CIPHERTEXTBYTES + j] = msk_c[j]; + } + +} + + +void PQCLEAN_SABER_AVX2_indcpa_kem_dec(uint8_t m[SABER_KEYBYTES], const uint8_t sk[SABER_INDCPA_SECRETKEYBYTES], const uint8_t ciphertext[SABER_BYTES_CCA_DEC]) { + + uint32_t i, j; + uint16_t sksv[SABER_K][SABER_N]; //secret key of the server + uint16_t pksv[SABER_K][SABER_N]; + uint16_t message_dec_unpacked[SABER_KEYBYTES * 8]; // one element containes on decrypted bit; + uint8_t scale_ar[SABER_SCALEBYTES_KEM]; + uint16_t op[SABER_N]; + + //--------------AVX declaration------------------ + + + //__m256i mod_p; + + __m256i v_avx[SABER_N / 16]; + + //__m256i acc[2*SABER_N/16]; + + __m256i sksv_avx[SABER_K][SABER_N / 16]; + __m256i pksv_avx[SABER_K][SABER_N / 16]; + + //mod_p=_mm256_set1_epi16(SABER_P-1); + + __m256i b_bucket[NUM_POLY][SCHB_N * 4]; + //--------------AVX declaration ends------------------ + + //-------unpack the public_key + + PQCLEAN_SABER_AVX2_BS2POLVEC(sksv, sk, SABER_Q); //sksv is the secret-key + PQCLEAN_SABER_AVX2_BS2POLVEC(pksv, ciphertext, SABER_P); //pksv is the ciphertext + + for (i = 0; i < SABER_K; i++) { + for (j = 0; j < SABER_N / 16; j++) { + sksv_avx[i][j] = _mm256_loadu_si256 ((__m256i const *) (&sksv[i][j * 16])); + pksv_avx[i][j] = _mm256_loadu_si256 ((__m256i const *) (&pksv[i][j * 16])); + } + } + + for (i = 0; i < SABER_N / 16; i++) { + v_avx[i] = _mm256_xor_si256(v_avx[i], v_avx[i]); + } + + + // InnerProduct(b', s, mod p) + + for (j = 0; j < NUM_POLY; j++) { + TC_eval(sksv_avx[j], b_bucket[j]); + } + + vector_vector_mul(pksv_avx, b_bucket, v_avx); + + for (i = 0; i < SABER_N / 16; i++) { + _mm256_maskstore_epi32 ((int *)(message_dec_unpacked + i * 16), _mm256_set1_epi32(-1), v_avx[i]); + } + + + for (i = 0; i < SABER_SCALEBYTES_KEM; i++) { + scale_ar[i] = ciphertext[SABER_CIPHERTEXTBYTES + i]; + } + + PQCLEAN_SABER_AVX2_SABER_un_pack4bit(op, scale_ar); + + + //addition of h2 + for (i = 0; i < SABER_N; i++) { + message_dec_unpacked[i] = ( ( message_dec_unpacked[i] + h2 - (op[i] << (SABER_EP - SABER_ET)) ) & (SABER_P - 1) ) >> (SABER_EP - 1); + } + + + POL2MSG(m, message_dec_unpacked); +} diff --git a/crypto_kem/saber/avx2/SABER_indcpa.h b/crypto_kem/saber/avx2/SABER_indcpa.h new file mode 100644 index 00000000..acdda606 --- /dev/null +++ b/crypto_kem/saber/avx2/SABER_indcpa.h @@ -0,0 +1,13 @@ +#ifndef INDCPA_H +#define INDCPA_H +#include "SABER_params.h" +#include + +void PQCLEAN_SABER_AVX2_indcpa_kem_keypair(uint8_t pk[SABER_INDCPA_PUBLICKEYBYTES], uint8_t sk[SABER_INDCPA_SECRETKEYBYTES]); + +void PQCLEAN_SABER_AVX2_indcpa_kem_enc(uint8_t ciphertext[SABER_BYTES_CCA_DEC], const uint8_t m[SABER_KEYBYTES], const uint8_t noiseseed[SABER_NOISESEEDBYTES], const uint8_t pk[SABER_INDCPA_PUBLICKEYBYTES]); + +void PQCLEAN_SABER_AVX2_indcpa_kem_dec(uint8_t m[SABER_KEYBYTES], const uint8_t sk[SABER_INDCPA_SECRETKEYBYTES], const uint8_t ciphertext[SABER_BYTES_CCA_DEC]); + + +#endif diff --git a/crypto_kem/saber/avx2/SABER_params.h b/crypto_kem/saber/avx2/SABER_params.h new file mode 100644 index 00000000..9b0edafe --- /dev/null +++ b/crypto_kem/saber/avx2/SABER_params.h @@ -0,0 +1,46 @@ +#ifndef PARAMS_H +#define PARAMS_H +#include "api.h" + + + + +#define SABER_K 3 +#define SABER_MU 8 +#define SABER_ET 4 + + +#define SABER_EQ 13 +#define SABER_EP 10 + +#define SABER_N 256 +#define SABER_Q 8192 //2^13 +#define SABER_P 1024 + +#define SABER_SEEDBYTES 32 +#define SABER_NOISESEEDBYTES 32 +#define SABER_COINBYTES 32 +#define SABER_KEYBYTES 32 + +#define SABER_HASHBYTES 32 + +#define SABER_POLYBYTES 416 //13*256/8 + +#define SABER_POLYVECBYTES (SABER_K * SABER_POLYBYTES) + +#define SABER_POLYVECCOMPRESSEDBYTES (SABER_K * 320) //10*256/8 NOTE : changed till here due to parameter adaptation + +#define SABER_CIPHERTEXTBYTES (SABER_POLYVECCOMPRESSEDBYTES) + +#define SABER_SCALEBYTES_KEM ((SABER_ET)*SABER_N/8) + +#define SABER_INDCPA_PUBLICKEYBYTES (SABER_POLYVECCOMPRESSEDBYTES + SABER_SEEDBYTES) +#define SABER_INDCPA_SECRETKEYBYTES (SABER_POLYVECBYTES) + +#define SABER_PUBLICKEYBYTES (SABER_INDCPA_PUBLICKEYBYTES) + +#define SABER_SECRETKEYBYTES (SABER_INDCPA_SECRETKEYBYTES + SABER_INDCPA_PUBLICKEYBYTES + SABER_HASHBYTES + SABER_KEYBYTES) + +#define SABER_BYTES_CCA_DEC (SABER_POLYVECCOMPRESSEDBYTES + SABER_SCALEBYTES_KEM) /* Second part is for Targhi-Unruh */ + +#endif diff --git a/crypto_kem/saber/avx2/api.h b/crypto_kem/saber/avx2/api.h new file mode 100644 index 00000000..20bf0df3 --- /dev/null +++ b/crypto_kem/saber/avx2/api.h @@ -0,0 +1,18 @@ +#ifndef PQCLEAN_SABER_AVX2_API_H +#define PQCLEAN_SABER_AVX2_API_H + + +#define PQCLEAN_SABER_AVX2_CRYPTO_ALGNAME "Saber" +#define PQCLEAN_SABER_AVX2_CRYPTO_BYTES 32 +#define PQCLEAN_SABER_AVX2_CRYPTO_CIPHERTEXTBYTES 1088 +#define PQCLEAN_SABER_AVX2_CRYPTO_PUBLICKEYBYTES 992 +#define PQCLEAN_SABER_AVX2_CRYPTO_SECRETKEYBYTES 2304 + +int PQCLEAN_SABER_AVX2_crypto_kem_keypair(unsigned char *pk, unsigned char *sk); + +int PQCLEAN_SABER_AVX2_crypto_kem_enc(unsigned char *ct, unsigned char *k, const unsigned char *pk); + +int PQCLEAN_SABER_AVX2_crypto_kem_dec(unsigned char *k, const unsigned char *ct, const unsigned char *sk); + + +#endif /* PQCLEAN_SABER_AVX2_API_H */ diff --git a/crypto_kem/saber/avx2/cbd.c b/crypto_kem/saber/avx2/cbd.c new file mode 100644 index 00000000..7639d7d2 --- /dev/null +++ b/crypto_kem/saber/avx2/cbd.c @@ -0,0 +1,51 @@ +#include "SABER_params.h" +#include "api.h" +#include "cbd.h" +#include +/*--------------------------------------------------------------------- +This file has been adapted from the implementation +(available at, Public Domain https://github.com/pq-crystals/kyber) +of "CRYSTALS – Kyber: a CCA-secure module-lattice-based KEM" +by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint, +Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle +----------------------------------------------------------------------*/ + + +static uint64_t load_littleendian(const unsigned char *x, int bytes) { + int i; + uint64_t r = x[0]; + for (i = 1; i < bytes; i++) { + r |= (uint64_t)x[i] << (8 * i); + } + return r; +} + + +void PQCLEAN_SABER_AVX2_cbd(uint16_t *r, const unsigned char *buf) { + uint16_t Qmod_minus1 = SABER_Q - 1; + + uint32_t t, d, a[4], b[4]; + int i, j; + + for (i = 0; i < SABER_N / 4; i++) { + t = load_littleendian(buf + 4 * i, 4); + d = 0; + for (j = 0; j < 4; j++) { + d += (t >> j) & 0x11111111; + } + + a[0] = d & 0xf; + b[0] = (d >> 4) & 0xf; + a[1] = (d >> 8) & 0xf; + b[1] = (d >> 12) & 0xf; + a[2] = (d >> 16) & 0xf; + b[2] = (d >> 20) & 0xf; + a[3] = (d >> 24) & 0xf; + b[3] = (d >> 28); + + r[4 * i + 0] = (uint16_t)(a[0] - b[0]) & Qmod_minus1; + r[4 * i + 1] = (uint16_t)(a[1] - b[1]) & Qmod_minus1; + r[4 * i + 2] = (uint16_t)(a[2] - b[2]) & Qmod_minus1; + r[4 * i + 3] = (uint16_t)(a[3] - b[3]) & Qmod_minus1; + } +} diff --git a/crypto_kem/saber/avx2/cbd.h b/crypto_kem/saber/avx2/cbd.h new file mode 100644 index 00000000..e80ffc75 --- /dev/null +++ b/crypto_kem/saber/avx2/cbd.h @@ -0,0 +1,16 @@ +#ifndef CBD_H +#define CBD_H +/*--------------------------------------------------------------------- +This file has been adapted from the implementation +(available at, Public Domain https://github.com/pq-crystals/kyber) +of "CRYSTALS – Kyber: a CCA-secure module-lattice-based KEM" +by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint, +Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle +----------------------------------------------------------------------*/ +#include "poly.h" +#include + +void PQCLEAN_SABER_AVX2_cbd(uint16_t *r, const unsigned char *buf); + + +#endif diff --git a/crypto_kem/saber/avx2/kem.c b/crypto_kem/saber/avx2/kem.c new file mode 100644 index 00000000..c88bb315 --- /dev/null +++ b/crypto_kem/saber/avx2/kem.c @@ -0,0 +1,79 @@ +#include "SABER_indcpa.h" +#include "SABER_params.h" +#include "api.h" +#include "fips202.h" +#include "randombytes.h" +#include "verify.h" +#include +#include +#include +#include + + +int PQCLEAN_SABER_AVX2_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) { + int i; + + PQCLEAN_SABER_AVX2_indcpa_kem_keypair(pk, sk); // sk[0:SABER_INDCPA_SECRETKEYBYTES-1] <-- sk + for (i = 0; i < SABER_INDCPA_PUBLICKEYBYTES; i++) { + sk[i + SABER_INDCPA_SECRETKEYBYTES] = pk[i]; // sk[SABER_INDCPA_SECRETKEYBYTES:SABER_INDCPA_SECRETKEYBYTES+SABER_INDCPA_SECRETKEYBYTES-1] <-- pk + } + + sha3_256(sk + SABER_SECRETKEYBYTES - 64, pk, SABER_INDCPA_PUBLICKEYBYTES); // Then hash(pk) is appended. + + randombytes(sk + SABER_SECRETKEYBYTES - SABER_KEYBYTES, SABER_KEYBYTES); // Remaining part of sk contains a pseudo-random number. + // This is output when check in PQCLEAN_SABER_AVX2_crypto_kem_dec() fails. + return (0); +} + +int PQCLEAN_SABER_AVX2_crypto_kem_enc(uint8_t *c, uint8_t *k, const uint8_t *pk) { + + uint8_t kr[64]; // Will contain key, coins + uint8_t buf[64]; + + randombytes(buf, 32); + + sha3_256(buf, buf, 32); // BUF[0:31] <-- random message (will be used as the key for client) Note: hash doesnot release system RNG output + + sha3_256(buf + 32, pk, SABER_INDCPA_PUBLICKEYBYTES); // BUF[32:63] <-- Hash(public key); Multitarget countermeasure for coins + contributory KEM + + sha3_512(kr, buf, 64); // kr[0:63] <-- Hash(buf[0:63]); + // K^ <-- kr[0:31] + // noiseseed (r) <-- kr[32:63]; + PQCLEAN_SABER_AVX2_indcpa_kem_enc(c, buf, (const uint8_t *) (kr + 32), pk); // buf[0:31] contains message; kr[32:63] contains randomness r; + + sha3_256(kr + 32, c, SABER_BYTES_CCA_DEC); + + sha3_256(k, kr, 64); // hash concatenation of pre-k and h(c) to k + + return (0); +} + +int PQCLEAN_SABER_AVX2_crypto_kem_dec(uint8_t *k, const uint8_t *c, const uint8_t *sk) { + int i; + uint8_t fail; + uint8_t cmp[SABER_BYTES_CCA_DEC]; + uint8_t buf[64]; + uint8_t kr[64]; // Will contain key, coins + const uint8_t *pk = sk + SABER_INDCPA_SECRETKEYBYTES; + + PQCLEAN_SABER_AVX2_indcpa_kem_dec(buf, sk, c); // buf[0:31] <-- message + + // Multitarget countermeasure for coins + contributory KEM + for (i = 0; i < 32; i++) { // Save hash by storing h(pk) in sk + buf[32 + i] = sk[SABER_SECRETKEYBYTES - 64 + i]; + } + + sha3_512(kr, buf, 64); + + PQCLEAN_SABER_AVX2_indcpa_kem_enc(cmp, buf, (const uint8_t *) (kr + 32), pk); + + fail = PQCLEAN_SABER_AVX2_verify(c, cmp, SABER_BYTES_CCA_DEC); + + sha3_256(kr + 32, c, SABER_BYTES_CCA_DEC); // overwrite coins in kr with h(c) + + PQCLEAN_SABER_AVX2_cmov(kr, sk + SABER_SECRETKEYBYTES - SABER_KEYBYTES, SABER_KEYBYTES, fail); + + sha3_256(k, kr, 64); // hash concatenation of pre-k and h(c) to k + + return (0); +} diff --git a/crypto_kem/saber/avx2/kem.h b/crypto_kem/saber/avx2/kem.h new file mode 100644 index 00000000..612ff4ff --- /dev/null +++ b/crypto_kem/saber/avx2/kem.h @@ -0,0 +1,35 @@ +#ifndef INDCPA_H +#define INDCPA_H + +#include + +void PQCLEAN_SABER_AVX2_indcpa_keypair(uint8_t *pk, uint8_t *sk); + + +void PQCLEAN_SABER_AVX2_indcpa_client(uint8_t *pk, uint8_t *b_prime, uint8_t *c, uint8_t *key); + + +void PQCLEAN_SABER_AVX2_indcpa_server(uint8_t *pk, uint8_t *b_prime, uint8_t *c, uint8_t *key); + + +void PQCLEAN_SABER_AVX2_indcpa_kem_keypair(uint8_t *pk, uint8_t *sk); + +void PQCLEAN_SABER_AVX2_indcpa_kem_enc(uint8_t *message, uint8_t *noiseseed, uint8_t *pk, uint8_t *ciphertext); + +void PQCLEAN_SABER_AVX2_indcpa_kem_dec(uint8_t *sk, uint8_t *ciphertext, uint8_t message_dec[]); + + +int PQCLEAN_SABER_AVX2_crypto_kem_keypair(unsigned char *pk, unsigned char *sk); + +int PQCLEAN_SABER_AVX2_crypto_kem_enc(unsigned char *c, unsigned char *k, const unsigned char *pk); + +int PQCLEAN_SABER_AVX2_crypto_kem_dec(unsigned char *k, const unsigned char *c, const unsigned char *sk); + + + +//uint64_t clock1,clock2; + +//uint64_t clock_kp_kex, clock_enc_kex, clock_dec_kex; + + +#endif diff --git a/crypto_kem/saber/avx2/pack_unpack.c b/crypto_kem/saber/avx2/pack_unpack.c new file mode 100644 index 00000000..00bf9c08 --- /dev/null +++ b/crypto_kem/saber/avx2/pack_unpack.c @@ -0,0 +1,502 @@ +#include "pack_unpack.h" + + +void PQCLEAN_SABER_AVX2_SABER_pack_3bit(uint8_t *bytes, const uint16_t *data) { + + uint32_t j; + uint32_t offset_data = 0, offset_byte = 0; + + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = 3 * j; + offset_data = 8 * j; + bytes[offset_byte + 0] = (data[offset_data + 0] & 0x7) | ( (data[offset_data + 1] & 0x7) << 3 ) | ((data[offset_data + 2] & 0x3) << 6); + bytes[offset_byte + 1] = ((data[offset_data + 2] >> 2 ) & 0x01) | ( (data[offset_data + 3] & 0x7) << 1 ) | ( (data[offset_data + 4] & 0x7) << 4 ) | (((data[offset_data + 5]) & 0x01) << 7); + bytes[offset_byte + 2] = ((data[offset_data + 5] >> 1 ) & 0x03) | ( (data[offset_data + 6] & 0x7) << 2 ) | ( (data[offset_data + 7] & 0x7) << 5 ); + } +} + +void PQCLEAN_SABER_AVX2_SABER_un_pack3bit(uint16_t *data, const uint8_t *bytes) { + + uint32_t j; + uint32_t offset_data = 0, offset_byte = 0; + + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = 3 * j; + offset_data = 8 * j; + data[offset_data + 0] = (bytes[offset_byte + 0]) & 0x07; + data[offset_data + 1] = ( (bytes[offset_byte + 0]) >> 3 ) & 0x07; + data[offset_data + 2] = ( ( (bytes[offset_byte + 0]) >> 6 ) & 0x03) | ( ( (bytes[offset_byte + 1]) & 0x01) << 2 ); + data[offset_data + 3] = ( (bytes[offset_byte + 1]) >> 1 ) & 0x07; + data[offset_data + 4] = ( (bytes[offset_byte + 1]) >> 4 ) & 0x07; + data[offset_data + 5] = ( ( (bytes[offset_byte + 1]) >> 7 ) & 0x01) | ( ( (bytes[offset_byte + 2]) & 0x03) << 1 ); + data[offset_data + 6] = ( (bytes[offset_byte + 2] >> 2) & 0x07 ); + data[offset_data + 7] = ( (bytes[offset_byte + 2] >> 5) & 0x07 ); + } + +} + +void PQCLEAN_SABER_AVX2_SABER_pack_4bit(uint8_t *bytes, const uint16_t *data) { + + uint32_t j; + uint32_t offset_data = 0; + + for (j = 0; j < SABER_N / 2; j++) { + offset_data = 2 * j; + bytes[j] = (data[offset_data] & 0x0f) | ( (data[offset_data + 1] & 0x0f) << 4 ); + } +} + +void PQCLEAN_SABER_AVX2_SABER_un_pack4bit(uint16_t *data, const uint8_t *bytes) { + + uint32_t j; + uint32_t offset_data = 0; + + for (j = 0; j < SABER_N / 2; j++) { + offset_data = 2 * j; + data[offset_data] = bytes[j] & 0x0f; + data[offset_data + 1] = (bytes[j] >> 4) & 0x0f; + } +} + +void PQCLEAN_SABER_AVX2_SABER_pack_6bit(uint8_t *bytes, const uint16_t *data) { + + uint32_t j; + uint32_t offset_data = 0, offset_byte = 0; + + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = 3 * j; + offset_data = 4 * j; + bytes[offset_byte + 0] = (data[offset_data + 0] & 0x3f) | ((data[offset_data + 1] & 0x03) << 6); + bytes[offset_byte + 1] = ((data[offset_data + 1] >> 2) & 0x0f) | ((data[offset_data + 2] & 0x0f) << 4); + bytes[offset_byte + 2] = ((data[offset_data + 2] >> 4) & 0x03) | ((data[offset_data + 3] & 0x3f) << 2); + } +} + + +void PQCLEAN_SABER_AVX2_SABER_un_pack6bit(uint16_t *data, const uint8_t *bytes) { + + uint32_t j; + uint32_t offset_data = 0, offset_byte = 0; + + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = 3 * j; + offset_data = 4 * j; + data[offset_data + 0] = bytes[offset_byte + 0] & 0x3f; + data[offset_data + 1] = ((bytes[offset_byte + 0] >> 6) & 0x03) | ((bytes[offset_byte + 1] & 0x0f) << 2) ; + data[offset_data + 2] = ((bytes[offset_byte + 1] & 0xff) >> 4) | ((bytes[offset_byte + 2] & 0x03) << 4) ; + data[offset_data + 3] = ((bytes[offset_byte + 2] & 0xff) >> 2); + } + +} + +void PQCLEAN_SABER_AVX2_SABER_pack10bit(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 10) / 8; + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = offset_byte1 + 5 * j; + offset_data = 4 * j; + bytes[offset_byte + 0] = ( data[i][ offset_data + 0 ] & (0xff)); + + bytes[offset_byte + 1] = ( (data[i][ offset_data + 0 ] >> 8) & 0x03 ) | ((data[i][ offset_data + 1 ] & 0x3f) << 2); + + bytes[offset_byte + 2] = ( (data[i][ offset_data + 1 ] >> 6) & 0x0f ) | ( (data[i][ offset_data + 2 ] & 0x0f) << 4); + + bytes[offset_byte + 3] = ( (data[i][ offset_data + 2 ] >> 4) & 0x3f ) | ((data[i][ offset_data + 3 ] & 0x03) << 6); + + bytes[offset_byte + 4] = ( (data[i][ offset_data + 3 ] >> 2) & 0xff ); + } + } +} + +void PQCLEAN_SABER_AVX2_POLVECp2BS(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 10) / 8; + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = offset_byte1 + 5 * j; + offset_data = 4 * j; + bytes[offset_byte + 0] = ( data[i][ offset_data + 0 ] & (0xff)); + + bytes[offset_byte + 1] = ( (data[i][ offset_data + 0 ] >> 8) & 0x03 ) | ((data[i][ offset_data + 1 ] & 0x3f) << 2); + + bytes[offset_byte + 2] = ( (data[i][ offset_data + 1 ] >> 6) & 0x0f ) | ( (data[i][ offset_data + 2 ] & 0x0f) << 4); + + bytes[offset_byte + 3] = ( (data[i][ offset_data + 2 ] >> 4) & 0x3f ) | ((data[i][ offset_data + 3 ] & 0x03) << 6); + + bytes[offset_byte + 4] = ( (data[i][ offset_data + 3 ] >> 2) & 0xff ); + } + } +} + +void PQCLEAN_SABER_AVX2_POLVECq2BS(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 13) / 8; + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = offset_byte1 + 13 * j; + offset_data = 8 * j; + bytes[offset_byte + 0] = ( data[i][ offset_data + 0 ] & (0xff)); + + bytes[offset_byte + 1] = ( (data[i][ offset_data + 0 ] >> 8) & 0x1f ) | ((data[i][ offset_data + 1 ] & 0x07) << 5); + + bytes[offset_byte + 2] = ( (data[i][ offset_data + 1 ] >> 3) & 0xff ); + + bytes[offset_byte + 3] = ( (data[i][ offset_data + 1 ] >> 11) & 0x03 ) | ((data[i][ offset_data + 2 ] & 0x3f) << 2); + + bytes[offset_byte + 4] = ( (data[i][ offset_data + 2 ] >> 6) & 0x7f ) | ( (data[i][ offset_data + 3 ] & 0x01) << 7 ); + + bytes[offset_byte + 5] = ( (data[i][ offset_data + 3 ] >> 1) & 0xff ); + + bytes[offset_byte + 6] = ( (data[i][ offset_data + 3 ] >> 9) & 0x0f ) | ( (data[i][ offset_data + 4 ] & 0x0f) << 4 ); + + bytes[offset_byte + 7] = ( (data[i][ offset_data + 4] >> 4) & 0xff ); + + bytes[offset_byte + 8] = ( (data[i][ offset_data + 4 ] >> 12) & 0x01 ) | ( (data[i][ offset_data + 5 ] & 0x7f) << 1 ); + + bytes[offset_byte + 9] = ( (data[i][ offset_data + 5 ] >> 7) & 0x3f ) | ( (data[i][ offset_data + 6 ] & 0x03) << 6 ); + + bytes[offset_byte + 10] = ( (data[i][ offset_data + 6 ] >> 2) & 0xff ); + + bytes[offset_byte + 11] = ( (data[i][ offset_data + 6 ] >> 10) & 0x07 ) | ( (data[i][ offset_data + 7 ] & 0x1f) << 3 ); + + bytes[offset_byte + 12] = ( (data[i][ offset_data + 7 ] >> 5) & 0xff ); + + } + } + + +} + +void PQCLEAN_SABER_AVX2_BS2POLq(uint16_t data[SABER_N], const uint8_t *bytes) { + + uint32_t j; + uint32_t offset_data = 0, offset_byte = 0; + + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = 13 * j; + offset_data = 8 * j; + data[offset_data + 0] = ( bytes[ offset_byte + 0 ] & (0xff)) | ((bytes[offset_byte + 1] & 0x1f) << 8); + data[offset_data + 1] = ( bytes[ offset_byte + 1 ] >> 5 & (0x07)) | ((bytes[offset_byte + 2] & 0xff) << 3) | ((bytes[offset_byte + 3] & 0x03) << 11); + data[offset_data + 2] = ( bytes[ offset_byte + 3 ] >> 2 & (0x3f)) | ((bytes[offset_byte + 4] & 0x7f) << 6); + data[offset_data + 3] = ( bytes[ offset_byte + 4 ] >> 7 & (0x01)) | ((bytes[offset_byte + 5] & 0xff) << 1) | ((bytes[offset_byte + 6] & 0x0f) << 9); + data[offset_data + 4] = ( bytes[ offset_byte + 6 ] >> 4 & (0x0f)) | ((bytes[offset_byte + 7] & 0xff) << 4) | ((bytes[offset_byte + 8] & 0x01) << 12); + data[offset_data + 5] = ( bytes[ offset_byte + 8] >> 1 & (0x7f)) | ((bytes[offset_byte + 9] & 0x3f) << 7); + data[offset_data + 6] = ( bytes[ offset_byte + 9] >> 6 & (0x03)) | ((bytes[offset_byte + 10] & 0xff) << 2) | ((bytes[offset_byte + 11] & 0x07) << 10); + data[offset_data + 7] = ( bytes[ offset_byte + 11] >> 3 & (0x1f)) | ((bytes[offset_byte + 12] & 0xff) << 5); + } +} + + + +void PQCLEAN_SABER_AVX2_BS2POLVECp(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 10) / 8; + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = offset_byte1 + 5 * j; + offset_data = 4 * j; + data[i][offset_data + 0] = ( bytes[ offset_byte + 0 ] & (0xff)) | ((bytes[ offset_byte + 1 ] & 0x03) << 8); + data[i][offset_data + 1] = ( (bytes[ offset_byte + 1 ] >> 2) & (0x3f)) | ((bytes[ offset_byte + 2 ] & 0x0f) << 6); + data[i][offset_data + 2] = ( (bytes[ offset_byte + 2 ] >> 4) & (0x0f)) | ((bytes[ offset_byte + 3 ] & 0x3f) << 4); + data[i][offset_data + 3] = ( (bytes[ offset_byte + 3 ] >> 6) & (0x03)) | ((bytes[ offset_byte + 4 ] & 0xff) << 2); + + } + } +} + +void PQCLEAN_SABER_AVX2_BS2POLVECq(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 13) / 8; + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = offset_byte1 + 13 * j; + offset_data = 8 * j; + data[i][offset_data + 0] = ( bytes[ offset_byte + 0 ] & (0xff)) | ((bytes[offset_byte + 1] & 0x1f) << 8); + data[i][offset_data + 1] = ( bytes[ offset_byte + 1 ] >> 5 & (0x07)) | ((bytes[offset_byte + 2] & 0xff) << 3) | ((bytes[offset_byte + 3] & 0x03) << 11); + data[i][offset_data + 2] = ( bytes[ offset_byte + 3 ] >> 2 & (0x3f)) | ((bytes[offset_byte + 4] & 0x7f) << 6); + data[i][offset_data + 3] = ( bytes[ offset_byte + 4 ] >> 7 & (0x01)) | ((bytes[offset_byte + 5] & 0xff) << 1) | ((bytes[offset_byte + 6] & 0x0f) << 9); + data[i][offset_data + 4] = ( bytes[ offset_byte + 6 ] >> 4 & (0x0f)) | ((bytes[offset_byte + 7] & 0xff) << 4) | ((bytes[offset_byte + 8] & 0x01) << 12); + data[i][offset_data + 5] = ( bytes[ offset_byte + 8] >> 1 & (0x7f)) | ((bytes[offset_byte + 9] & 0x3f) << 7); + data[i][offset_data + 6] = ( bytes[ offset_byte + 9] >> 6 & (0x03)) | ((bytes[offset_byte + 10] & 0xff) << 2) | ((bytes[offset_byte + 11] & 0x07) << 10); + data[i][offset_data + 7] = ( bytes[ offset_byte + 11] >> 3 & (0x1f)) | ((bytes[offset_byte + 12] & 0xff) << 5); + } + } + + +} + + + +void PQCLEAN_SABER_AVX2_SABER_un_pack10bit(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 10) / 8; + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = offset_byte1 + 5 * j; + offset_data = 4 * j; + data[i][offset_data + 0] = ( bytes[ offset_byte + 0 ] & (0xff)) | ((bytes[ offset_byte + 1 ] & 0x03) << 8); + data[i][offset_data + 1] = ( (bytes[ offset_byte + 1 ] >> 2) & (0x3f)) | ((bytes[ offset_byte + 2 ] & 0x0f) << 6); + data[i][offset_data + 2] = ( (bytes[ offset_byte + 2 ] >> 4) & (0x0f)) | ((bytes[ offset_byte + 3 ] & 0x3f) << 4); + data[i][offset_data + 3] = ( (bytes[ offset_byte + 3 ] >> 6) & (0x03)) | ((bytes[ offset_byte + 4 ] & 0xff) << 2); + + } + } + + +} + + +void PQCLEAN_SABER_AVX2_SABER_pack13bit(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 13) / 8; + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = offset_byte1 + 13 * j; + offset_data = 8 * j; + bytes[offset_byte + 0] = ( data[i][ offset_data + 0 ] & (0xff)); + + bytes[offset_byte + 1] = ( (data[i][ offset_data + 0 ] >> 8) & 0x1f ) | ((data[i][ offset_data + 1 ] & 0x07) << 5); + + bytes[offset_byte + 2] = ( (data[i][ offset_data + 1 ] >> 3) & 0xff ); + + bytes[offset_byte + 3] = ( (data[i][ offset_data + 1 ] >> 11) & 0x03 ) | ((data[i][ offset_data + 2 ] & 0x3f) << 2); + + bytes[offset_byte + 4] = ( (data[i][ offset_data + 2 ] >> 6) & 0x7f ) | ( (data[i][ offset_data + 3 ] & 0x01) << 7 ); + + bytes[offset_byte + 5] = ( (data[i][ offset_data + 3 ] >> 1) & 0xff ); + + bytes[offset_byte + 6] = ( (data[i][ offset_data + 3 ] >> 9) & 0x0f ) | ( (data[i][ offset_data + 4 ] & 0x0f) << 4 ); + + bytes[offset_byte + 7] = ( (data[i][ offset_data + 4] >> 4) & 0xff ); + + bytes[offset_byte + 8] = ( (data[i][ offset_data + 4 ] >> 12) & 0x01 ) | ( (data[i][ offset_data + 5 ] & 0x7f) << 1 ); + + bytes[offset_byte + 9] = ( (data[i][ offset_data + 5 ] >> 7) & 0x3f ) | ( (data[i][ offset_data + 6 ] & 0x03) << 6 ); + + bytes[offset_byte + 10] = ( (data[i][ offset_data + 6 ] >> 2) & 0xff ); + + bytes[offset_byte + 11] = ( (data[i][ offset_data + 6 ] >> 10) & 0x07 ) | ( (data[i][ offset_data + 7 ] & 0x1f) << 3 ); + + bytes[offset_byte + 12] = ( (data[i][ offset_data + 7 ] >> 5) & 0xff ); + + } + } + + +} + +void PQCLEAN_SABER_AVX2_SABER_un_pack13bit(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 13) / 8; + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = offset_byte1 + 13 * j; + offset_data = 8 * j; + data[i][offset_data + 0] = ( bytes[ offset_byte + 0 ] & (0xff)) | ((bytes[offset_byte + 1] & 0x1f) << 8); + data[i][offset_data + 1] = ( bytes[ offset_byte + 1 ] >> 5 & (0x07)) | ((bytes[offset_byte + 2] & 0xff) << 3) | ((bytes[offset_byte + 3] & 0x03) << 11); + data[i][offset_data + 2] = ( bytes[ offset_byte + 3 ] >> 2 & (0x3f)) | ((bytes[offset_byte + 4] & 0x7f) << 6); + data[i][offset_data + 3] = ( bytes[ offset_byte + 4 ] >> 7 & (0x01)) | ((bytes[offset_byte + 5] & 0xff) << 1) | ((bytes[offset_byte + 6] & 0x0f) << 9); + data[i][offset_data + 4] = ( bytes[ offset_byte + 6 ] >> 4 & (0x0f)) | ((bytes[offset_byte + 7] & 0xff) << 4) | ((bytes[offset_byte + 8] & 0x01) << 12); + data[i][offset_data + 5] = ( bytes[ offset_byte + 8] >> 1 & (0x7f)) | ((bytes[offset_byte + 9] & 0x3f) << 7); + data[i][offset_data + 6] = ( bytes[ offset_byte + 9] >> 6 & (0x03)) | ((bytes[offset_byte + 10] & 0xff) << 2) | ((bytes[offset_byte + 11] & 0x07) << 10); + data[i][offset_data + 7] = ( bytes[ offset_byte + 11] >> 3 & (0x1f)) | ((bytes[offset_byte + 12] & 0xff) << 5); + } + } + + +} + +void PQCLEAN_SABER_AVX2_SABER_poly_un_pack13bit(uint16_t data[SABER_N], const uint8_t *bytes) { + + uint32_t j; + uint32_t offset_data = 0, offset_byte = 0; + + //for(i=0;i> 5 & (0x07)) | ((bytes[offset_byte + 2] & 0xff) << 3) | ((bytes[offset_byte + 3] & 0x03) << 11); + data[offset_data + 2] = ( bytes[ offset_byte + 3 ] >> 2 & (0x3f)) | ((bytes[offset_byte + 4] & 0x7f) << 6); + data[offset_data + 3] = ( bytes[ offset_byte + 4 ] >> 7 & (0x01)) | ((bytes[offset_byte + 5] & 0xff) << 1) | ((bytes[offset_byte + 6] & 0x0f) << 9); + data[offset_data + 4] = ( bytes[ offset_byte + 6 ] >> 4 & (0x0f)) | ((bytes[offset_byte + 7] & 0xff) << 4) | ((bytes[offset_byte + 8] & 0x01) << 12); + data[offset_data + 5] = ( bytes[ offset_byte + 8] >> 1 & (0x7f)) | ((bytes[offset_byte + 9] & 0x3f) << 7); + data[offset_data + 6] = ( bytes[ offset_byte + 9] >> 6 & (0x03)) | ((bytes[offset_byte + 10] & 0xff) << 2) | ((bytes[offset_byte + 11] & 0x07) << 10); + data[offset_data + 7] = ( bytes[ offset_byte + 11] >> 3 & (0x1f)) | ((bytes[offset_byte + 12] & 0xff) << 5); + } + //} + + +} + + +void PQCLEAN_SABER_AVX2_SABER_pack11bit(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]) { + /*This function packs 11 bit data stream into 8 bits of data. + */ + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 11) / 8; + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = offset_byte1 + 11 * j; + offset_data = 8 * j; + bytes[offset_byte + 0] = ( data[i][ offset_data + 0 ] & (0xff)); + + bytes[offset_byte + 1] = ( (data[i][ offset_data + 0 ] >> 8) & 0x07 ) | ((data[i][ offset_data + 1 ] & 0x1f) << 3); + + bytes[offset_byte + 2] = ( (data[i][ offset_data + 1 ] >> 5) & 0x3f ) | ((data[i][ offset_data + 2 ] & 0x03) << 6); + + bytes[offset_byte + 3] = ( (data[i][ offset_data + 2 ] >> 2) & 0xff ); + + bytes[offset_byte + 4] = ( (data[i][ offset_data + 2 ] >> 10) & 0x01 ) | ((data[i][ offset_data + 3 ] & 0x7f) << 1); + + bytes[offset_byte + 5] = ( (data[i][ offset_data + 3 ] >> 7) & 0x0f ) | ((data[i][ offset_data + 4 ] & 0x0f) << 4); + + bytes[offset_byte + 6] = ( (data[i][ offset_data + 4 ] >> 4) & 0x7f ) | ((data[i][ offset_data + 5 ] & 0x01) << 7); + + bytes[offset_byte + 7] = ( (data[i][ offset_data + 5 ] >> 1) & 0xff ); + + bytes[offset_byte + 8] = ( (data[i][ offset_data + 5 ] >> 9) & 0x03 ) | ((data[i][ offset_data + 6 ] & 0x3f) << 2); + + bytes[offset_byte + 9] = ( (data[i][ offset_data + 6 ] >> 6) & 0x1f ) | ((data[i][ offset_data + 7 ] & 0x07) << 5); + + bytes[offset_byte + 10] = ( (data[i][ offset_data + 7 ] >> 3) & 0xff ); + + } + } + +} + +void PQCLEAN_SABER_AVX2_SABER_un_pack11bit(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 11) / 8; + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = offset_byte1 + 11 * j; + offset_data = 8 * j; + + data[i][offset_data + 0] = (bytes[offset_byte + 0]) | ( (bytes[offset_byte + 1] & 0x07) << 8 ); + + data[i][offset_data + 1] = ( (bytes[offset_byte + 1] >> 3) & 0x1f) | ( (bytes[offset_byte + 2] & 0x3f) << 5 ); + + data[i][offset_data + 2] = ( (bytes[offset_byte + 2] >> 6) & 0x03) | ( (bytes[offset_byte + 3] & 0xff) << 2 ) | ( (bytes[offset_byte + 4] & 0x01) << 10 ); + + data[i][offset_data + 3] = ( (bytes[offset_byte + 4] >> 1) & 0x7f) | ( (bytes[offset_byte + 5] & 0x0f) << 7 ); + + data[i][offset_data + 4] = ( (bytes[offset_byte + 5] >> 4) & 0x0f) | ( (bytes[offset_byte + 6] & 0x7f) << 4 ); + + data[i][offset_data + 5] = ( (bytes[offset_byte + 6] >> 7) & 0x01) | ( (bytes[offset_byte + 7] & 0xff) << 1 ) | ( (bytes[offset_byte + 8] & 0x03) << 9 ); + + data[i][offset_data + 6] = ( (bytes[offset_byte + 8] >> 2) & 0x3f) | ( (bytes[offset_byte + 9] & 0x1f) << 6 ); + + data[i][offset_data + 7] = ( (bytes[offset_byte + 9] >> 5) & 0x07) | ( (bytes[offset_byte + 10] & 0xff) << 3 ); + } + } + + +} + +void PQCLEAN_SABER_AVX2_SABER_pack14bit(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 14) / 8; + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = offset_byte1 + 7 * j; + offset_data = 4 * j; + bytes[offset_byte + 0] = ( data[i][ offset_data + 0 ] & (0xff)); + + bytes[offset_byte + 1] = ( (data[i][ offset_data + 0 ] >> 8) & 0x3f ) | ((data[i][ offset_data + 1 ] & 0x03) << 6); + + bytes[offset_byte + 2] = ( (data[i][ offset_data + 1 ] >> 2) & 0xff ); + + bytes[offset_byte + 3] = ( (data[i][ offset_data + 1 ] >> 10) & 0x0f ) | ((data[i][ offset_data + 2 ] & 0x0f) << 4); + + bytes[offset_byte + 4] = ( (data[i][ offset_data + 2 ] >> 4) & 0xff ); + + bytes[offset_byte + 5] = ( (data[i][ offset_data + 2 ] >> 12) & 0x03 ) | ((data[i][ offset_data + 3 ] & 0x3f) << 2); + + bytes[offset_byte + 6] = ( (data[i][ offset_data + 3 ] >> 6) & 0xff ); + } + } + + +} + + +void PQCLEAN_SABER_AVX2_SABER_un_pack14bit(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes) { + + uint32_t i, j; + uint32_t offset_data = 0, offset_byte = 0, offset_byte1 = 0; + + for (i = 0; i < SABER_K; i++) { + offset_byte1 = i * (SABER_N * 14) / 8; + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = offset_byte1 + 7 * j; + offset_data = 4 * j; + data[i][offset_data + 0] = (bytes[offset_byte + 0] & 0xff) | ( (bytes[offset_byte + 1] & 0x3f) << 8 ); + + data[i][offset_data + 1] = ( (bytes[offset_byte + 1] >> 6) & 0x03) | ((bytes[offset_byte + 2] & 0xff) << 2 ) | ( (bytes[offset_byte + 3] & 0x0f) << 10 ); + + data[i][offset_data + 2] = ( (bytes[offset_byte + 3] >> 4) & 0x0f) | ( (bytes[offset_byte + 4] ) << 4 ) | ( (bytes[offset_byte + 5] & 0x03) << 12 ); + + data[i][offset_data + 3] = ( (bytes[offset_byte + 5] >> 2) & 0x3f) | ( (bytes[offset_byte + 6] ) << 6 ); + } + } + + +} + +void PQCLEAN_SABER_AVX2_POLVEC2BS(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N], uint16_t modulus) { + + if (modulus == 1024) { + PQCLEAN_SABER_AVX2_POLVECp2BS(bytes, data); + } else if (modulus == 8192) { + PQCLEAN_SABER_AVX2_POLVECq2BS(bytes, data); + } +} + +void PQCLEAN_SABER_AVX2_BS2POLVEC(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes, uint16_t modulus) { + + if (modulus == 1024) { + PQCLEAN_SABER_AVX2_BS2POLVECp(data, bytes); + } else if (modulus == 8192) { + PQCLEAN_SABER_AVX2_BS2POLVECq(data, bytes); + } + +} diff --git a/crypto_kem/saber/avx2/pack_unpack.h b/crypto_kem/saber/avx2/pack_unpack.h new file mode 100644 index 00000000..e1608d4c --- /dev/null +++ b/crypto_kem/saber/avx2/pack_unpack.h @@ -0,0 +1,56 @@ +#ifndef PACK_UNPACK_H +#define PACK_UNPACK_H +#include "SABER_params.h" +#include +#include + +void PQCLEAN_SABER_AVX2_BS2POLq(uint16_t data[SABER_N], const uint8_t *bytes); + +void PQCLEAN_SABER_AVX2_BS2POLVEC(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes, uint16_t modulus); + +void PQCLEAN_SABER_AVX2_BS2POLVECq(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes); + +void PQCLEAN_SABER_AVX2_BS2POLVECp(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes); + + +void PQCLEAN_SABER_AVX2_POLVEC2BS(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N], uint16_t modulus); + +void PQCLEAN_SABER_AVX2_POLVECq2BS(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]); + +void PQCLEAN_SABER_AVX2_POLVECp2BS(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]); + + +void PQCLEAN_SABER_AVX2_SABER_pack_3bit(uint8_t *bytes, const uint16_t *data); + +void PQCLEAN_SABER_AVX2_SABER_pack_4bit(uint8_t *bytes, const uint16_t *data); + +void PQCLEAN_SABER_AVX2_SABER_pack_6bit(uint8_t *bytes, const uint16_t *data); + +void PQCLEAN_SABER_AVX2_SABER_pack10bit(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]); + +void PQCLEAN_SABER_AVX2_SABER_pack11bit(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]); + +void PQCLEAN_SABER_AVX2_SABER_pack13bit(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]); + +void PQCLEAN_SABER_AVX2_SABER_pack14bit(uint8_t *bytes, const uint16_t data[SABER_K][SABER_N]); + + +void PQCLEAN_SABER_AVX2_SABER_poly_un_pack13bit(uint16_t data[SABER_N], const uint8_t *bytes); + + +void PQCLEAN_SABER_AVX2_SABER_un_pack3bit(uint16_t *data, const uint8_t *bytes); + +void PQCLEAN_SABER_AVX2_SABER_un_pack4bit(uint16_t *data, const uint8_t *bytes); + +void PQCLEAN_SABER_AVX2_SABER_un_pack6bit(uint16_t *data, const uint8_t *bytes); + +void PQCLEAN_SABER_AVX2_SABER_un_pack10bit(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes); + +void PQCLEAN_SABER_AVX2_SABER_un_pack11bit(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes); + +void PQCLEAN_SABER_AVX2_SABER_un_pack13bit(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes); + +void PQCLEAN_SABER_AVX2_SABER_un_pack14bit(uint16_t data[SABER_K][SABER_N], const uint8_t *bytes); + + +#endif diff --git a/crypto_kem/saber/avx2/poly.h b/crypto_kem/saber/avx2/poly.h new file mode 100644 index 00000000..2978d0d8 --- /dev/null +++ b/crypto_kem/saber/avx2/poly.h @@ -0,0 +1,27 @@ +#ifndef POLY_H +#define POLY_H +/*--------------------------------------------------------------------- +This file has been adapted from the implementation +(available at, Public Domain https://github.com/pq-crystals/kyber) +of "CRYSTALS – Kyber: a CCA-secure module-lattice-based KEM" +by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint, +Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle +----------------------------------------------------------------------*/ +#include "SABER_params.h" +#include + +typedef struct { + uint16_t coeffs[SABER_N]; +} poly; + +typedef struct { + poly vec[SABER_K]; +} polyvec; + +void PQCLEAN_SABER_AVX2_poly_getnoise(uint16_t *r, const unsigned char *seed, unsigned char nonce); + + +void PQCLEAN_SABER_AVX2_poly_getnoise4x(uint16_t *r0, uint16_t *r1, uint16_t *r2, const unsigned char *seed, unsigned char nonce0, unsigned char nonce1, unsigned char nonce2, unsigned char nonce3); + + +#endif diff --git a/crypto_kem/saber/avx2/polymul/consts.h b/crypto_kem/saber/avx2/polymul/consts.h new file mode 100644 index 00000000..40826398 --- /dev/null +++ b/crypto_kem/saber/avx2/polymul/consts.h @@ -0,0 +1,20 @@ +#include "../SABER_params.h" + +#define AVX_N (SABER_N >> 4) +#define small_len_avx (AVX_N >> 2) + +#define SCHB_N 16 + +#define N_SB (SABER_N >> 2) +#define N_SB_RES (2*N_SB-1) + +#define N_SB_16 (N_SB >> 2) +#define N_SB_16_RES (2*N_SB_16-1) + +#define AVX_N1 16 /*N/16*/ + +#define SCM_SIZE 16 + +// The dimension of a vector. i.e vector has NUM_POLY elements and Matrix has NUM_POLY X NUM_POLY elements +#define NUM_POLY SABER_K +//int NUM_POLY=2; diff --git a/crypto_kem/saber/avx2/polymul/matrix.c b/crypto_kem/saber/avx2/polymul/matrix.c new file mode 100644 index 00000000..5fa35783 --- /dev/null +++ b/crypto_kem/saber/avx2/polymul/matrix.c @@ -0,0 +1,303 @@ +#include + +static void transpose_n1(__m256i *M) +{ + //int i; + register __m256i r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11; + register __m256i temp, temp0, temp1, temp2; + + //for(i=0; i<8; i=i+1) + //{ + r0 = _mm256_unpacklo_epi16(M[0], M[1]); + r1 = _mm256_unpacklo_epi16(M[2], M[3]); + r2 = _mm256_unpacklo_epi16(M[4], M[5]); + r3 = _mm256_unpacklo_epi16(M[6], M[7]); + r4 = _mm256_unpacklo_epi16(M[8], M[9]); + r5 = _mm256_unpacklo_epi16(M[10], M[11]); + r6 = _mm256_unpacklo_epi16(M[12], M[13]); + r7 = _mm256_unpacklo_epi16(M[14], M[15]); + + + temp = _mm256_unpacklo_epi32(r0, r1); + temp0 = _mm256_unpacklo_epi32(r2, r3); + temp1 = _mm256_unpacklo_epi32(r4, r5); + temp2 = _mm256_unpacklo_epi32(r6, r7); + + r8 = _mm256_unpackhi_epi32(r0, r1); + r9 = _mm256_unpackhi_epi32(r2, r3); + r10 = _mm256_unpackhi_epi32(r4, r5); + r11 = _mm256_unpackhi_epi32(r6, r7); + + r0 = _mm256_unpacklo_epi64(temp, temp0); + r2 = _mm256_unpackhi_epi64(temp, temp0); + + r1 = _mm256_unpacklo_epi64(temp1, temp2); + r3 = _mm256_unpackhi_epi64(temp1, temp2); + + temp = _mm256_unpackhi_epi16(M[0], M[1]); + temp0 = _mm256_unpackhi_epi16(M[2], M[3]); + temp1 = _mm256_unpackhi_epi16(M[4], M[5]); + temp2 = _mm256_unpackhi_epi16(M[6], M[7]); + r4 = _mm256_unpackhi_epi16(M[8], M[9]); + + M[0] = _mm256_permute2f128_si256(r0, r1, 0x20); + M[8] = _mm256_permute2f128_si256(r0, r1, 0x31); + M[1] = _mm256_permute2f128_si256(r2, r3, 0x20); + M[9] = _mm256_permute2f128_si256(r2, r3, 0x31); + + + r5 = _mm256_unpackhi_epi16(M[10], M[11]); + r6 = _mm256_unpackhi_epi16(M[12], M[13]); + r7 = _mm256_unpackhi_epi16(M[14], M[15]); + + + + r0 = _mm256_unpacklo_epi64(r8, r9); + r1 = _mm256_unpacklo_epi64(r10, r11); + + r2 = _mm256_unpackhi_epi64(r8, r9); + r3 = _mm256_unpackhi_epi64(r10, r11); + + + + M[3] = _mm256_permute2f128_si256(r2, r3, 0x20); + M[11] = _mm256_permute2f128_si256(r2, r3, 0x31); + M[2] = _mm256_permute2f128_si256(r0, r1, 0x20); + M[10] = _mm256_permute2f128_si256(r0, r1, 0x31); + + + //for(i=0; i<4; i=i+1) + //{ + r0 = _mm256_unpacklo_epi32(temp, temp0); + r1 = _mm256_unpacklo_epi32(temp1, temp2); + r2 = _mm256_unpacklo_epi32(r4, r5); + r3 = _mm256_unpacklo_epi32(r6, r7); + + //} + + + //for(i=0; i<2; i=i+1) + //{ + r8 = _mm256_unpacklo_epi64(r0, r1); + r10 = _mm256_unpackhi_epi64(r0, r1); + + r9 = _mm256_unpacklo_epi64(r2, r3); + r11 = _mm256_unpackhi_epi64(r2, r3); + + M[4] = _mm256_permute2f128_si256(r8, r9, 0x20); + M[12] = _mm256_permute2f128_si256(r8, r9, 0x31); + M[5] = _mm256_permute2f128_si256(r10, r11, 0x20); + M[13] = _mm256_permute2f128_si256(r10, r11, 0x31); + + r0 = _mm256_unpackhi_epi32(temp, temp0); + r1 = _mm256_unpackhi_epi32(temp1, temp2); + r2 = _mm256_unpackhi_epi32(r4, r5); + r3 = _mm256_unpackhi_epi32(r6, r7); + + //} +// for(i=0; i<2; i=i+1) +// { + r4 = _mm256_unpacklo_epi64(r0, r1); + r6 = _mm256_unpackhi_epi64(r0, r1); + + r5 = _mm256_unpacklo_epi64(r2, r3); + r7 = _mm256_unpackhi_epi64(r2, r3); + +// } + + //------------------------------------------------------- + + M[6] = _mm256_permute2f128_si256(r4, r5, 0x20); + M[14] = _mm256_permute2f128_si256(r4, r5, 0x31); + M[7] = _mm256_permute2f128_si256(r6, r7, 0x20); + M[15] = _mm256_permute2f128_si256(r6, r7, 0x31); +} + +/* +void transpose_unrolled(__m256i *M) +{ + int i; + __m256i tL[8], tH[8]; + __m256i bL[4], bH[4], cL[4], cH[4]; + __m256i dL[2], dH[2], eL[2], eH[2], fL[2], fH[2], gL[2], gH[2]; + + __m256i r0, r1, r2, r3, r4, r5, r6, r7; + + //for(i=0; i<8; i=i+1) + //{ + tL[0] = _mm256_unpacklo_epi16(M[0], M[1]); + tH[0] = _mm256_unpackhi_epi16(M[0], M[1]); + + tL[1] = _mm256_unpacklo_epi16(M[2], M[3]); + tH[1] = _mm256_unpackhi_epi16(M[2], M[3]); + + tL[2] = _mm256_unpacklo_epi16(M[4], M[5]); + tH[2] = _mm256_unpackhi_epi16(M[4], M[5]); + + tL[3] = _mm256_unpacklo_epi16(M[6], M[7]); + tH[3] = _mm256_unpackhi_epi16(M[6], M[7]); + + tL[4] = _mm256_unpacklo_epi16(M[8], M[9]); + tH[4] = _mm256_unpackhi_epi16(M[8], M[9]); + + tL[5] = _mm256_unpacklo_epi16(M[10], M[11]); + tH[5] = _mm256_unpackhi_epi16(M[10], M[11]); + + tL[6] = _mm256_unpacklo_epi16(M[12], M[13]); + tH[6] = _mm256_unpackhi_epi16(M[12], M[13]); + + tL[7] = _mm256_unpacklo_epi16(M[14], M[15]); + tH[7] = _mm256_unpackhi_epi16(M[14], M[15]); + + //} + + //------------------------------------------------------- + //for(i=0; i<4; i=i+1) + //{ + bL[0] = _mm256_unpacklo_epi32(tL[0], tL[1]); + bH[0] = _mm256_unpackhi_epi32(tL[0], tL[1]); + + bL[1] = _mm256_unpacklo_epi32(tL[2], tL[3]); + bH[1] = _mm256_unpackhi_epi32(tL[2], tL[3]); + + bL[2] = _mm256_unpacklo_epi32(tL[4], tL[5]); + bH[2] = _mm256_unpackhi_epi32(tL[4], tL[5]); + + bL[3] = _mm256_unpacklo_epi32(tL[6], tL[7]); + bH[3] = _mm256_unpackhi_epi32(tL[6], tL[7]); + + //} + + //for(i=0; i<2; i=i+1) + //{ + dL[0] = _mm256_unpacklo_epi64(bL[0], bL[1]); + dH[0] = _mm256_unpackhi_epi64(bL[0], bL[1]); + + dL[1] = _mm256_unpacklo_epi64(bL[2], bL[3]); + dH[1] = _mm256_unpackhi_epi64(bL[2], bL[3]); + + M[0] = _mm256_permute2f128_si256(dL[0], dL[1], 0x20); + M[8] = _mm256_permute2f128_si256(dL[0], dL[1], 0x31); + M[1] = _mm256_permute2f128_si256(dH[0], dH[1], 0x20); + M[9] = _mm256_permute2f128_si256(dH[0], dH[1], 0x31); + + //} + //for(i=0; i<2; i=i+1) + //{ + eL[0] = _mm256_unpacklo_epi64(bH[0], bH[1]); + eH[0] = _mm256_unpackhi_epi64(bH[0], bH[1]); + + eL[1] = _mm256_unpacklo_epi64(bH[2], bH[3]); + eH[1] = _mm256_unpackhi_epi64(bH[2], bH[3]); + + //} + + //------------------------------------------------------- + + //------------------------------------------------------- + for(i=0; i<4; i=i+1) + { + cL[i] = _mm256_unpacklo_epi32(tH[2*i], tH[2*i+1]); + cH[i] = _mm256_unpackhi_epi32(tH[2*i], tH[2*i+1]); + } + + + for(i=0; i<2; i=i+1) + { + fL[i] = _mm256_unpacklo_epi64(cL[2*i], cL[2*i+1]); + fH[i] = _mm256_unpackhi_epi64(cL[2*i], cL[2*i+1]); + } + for(i=0; i<2; i=i+1) + { + gL[i] = _mm256_unpacklo_epi64(cH[2*i], cH[2*i+1]); + gH[i] = _mm256_unpackhi_epi64(cH[2*i], cH[2*i+1]); + } + + //------------------------------------------------------- + + + + M[2] = _mm256_permute2f128_si256(eL[0], eL[1], 0x20); + M[10] = _mm256_permute2f128_si256(eL[0], eL[1], 0x31); + M[3] = _mm256_permute2f128_si256(eH[0], eH[1], 0x20); + M[11] = _mm256_permute2f128_si256(eH[0], eH[1], 0x31); + + M[4] = _mm256_permute2f128_si256(fL[0], fL[1], 0x20); + M[12] = _mm256_permute2f128_si256(fL[0], fL[1], 0x31); + M[5] = _mm256_permute2f128_si256(fH[0], fH[1], 0x20); + M[13] = _mm256_permute2f128_si256(fH[0], fH[1], 0x31); + + M[6] = _mm256_permute2f128_si256(gL[0], gL[1], 0x20); + M[14] = _mm256_permute2f128_si256(gL[0], gL[1], 0x31); + M[7] = _mm256_permute2f128_si256(gH[0], gH[1], 0x20); + M[15] = _mm256_permute2f128_si256(gH[0], gH[1], 0x31); +} + + +void transpose1(__m256i *M) +{ + int i; + __m256i tL[8], tH[8]; + __m256i bL[4], bH[4], cL[4], cH[4]; + __m256i dL[2], dH[2], eL[2], eH[2], fL[2], fH[2], gL[2], gH[2]; + + for(i=0; i<8; i=i+1) + { + tL[i] = _mm256_unpacklo_epi16(M[2*i], M[2*i+1]); + tH[i] = _mm256_unpackhi_epi16(M[2*i], M[2*i+1]); + } + + for(i=0; i<4; i=i+1) + { + bL[i] = _mm256_unpacklo_epi32(tL[2*i], tL[2*i+1]); + bH[i] = _mm256_unpackhi_epi32(tL[2*i], tL[2*i+1]); + } + for(i=0; i<4; i=i+1) + { + cL[i] = _mm256_unpacklo_epi32(tH[2*i], tH[2*i+1]); + cH[i] = _mm256_unpackhi_epi32(tH[2*i], tH[2*i+1]); + } + + for(i=0; i<2; i=i+1) + { + dL[i] = _mm256_unpacklo_epi64(bL[2*i], bL[2*i+1]); + dH[i] = _mm256_unpackhi_epi64(bL[2*i], bL[2*i+1]); + } + for(i=0; i<2; i=i+1) + { + eL[i] = _mm256_unpacklo_epi64(bH[2*i], bH[2*i+1]); + eH[i] = _mm256_unpackhi_epi64(bH[2*i], bH[2*i+1]); + } + + for(i=0; i<2; i=i+1) + { + fL[i] = _mm256_unpacklo_epi64(cL[2*i], cL[2*i+1]); + fH[i] = _mm256_unpackhi_epi64(cL[2*i], cL[2*i+1]); + } + for(i=0; i<2; i=i+1) + { + gL[i] = _mm256_unpacklo_epi64(cH[2*i], cH[2*i+1]); + gH[i] = _mm256_unpackhi_epi64(cH[2*i], cH[2*i+1]); + } + + M[0] = _mm256_permute2f128_si256(dL[0], dL[1], 0x20); + M[8] = _mm256_permute2f128_si256(dL[0], dL[1], 0x31); + M[1] = _mm256_permute2f128_si256(dH[0], dH[1], 0x20); + M[9] = _mm256_permute2f128_si256(dH[0], dH[1], 0x31); + + M[2] = _mm256_permute2f128_si256(eL[0], eL[1], 0x20); + M[10] = _mm256_permute2f128_si256(eL[0], eL[1], 0x31); + M[3] = _mm256_permute2f128_si256(eH[0], eH[1], 0x20); + M[11] = _mm256_permute2f128_si256(eH[0], eH[1], 0x31); + + M[4] = _mm256_permute2f128_si256(fL[0], fL[1], 0x20); + M[12] = _mm256_permute2f128_si256(fL[0], fL[1], 0x31); + M[5] = _mm256_permute2f128_si256(fH[0], fH[1], 0x20); + M[13] = _mm256_permute2f128_si256(fH[0], fH[1], 0x31); + + M[6] = _mm256_permute2f128_si256(gL[0], gL[1], 0x20); + M[14] = _mm256_permute2f128_si256(gL[0], gL[1], 0x31); + M[7] = _mm256_permute2f128_si256(gH[0], gH[1], 0x20); + M[15] = _mm256_permute2f128_si256(gH[0], gH[1], 0x31); +} +*/ diff --git a/crypto_kem/saber/avx2/polymul/scm_avx.c b/crypto_kem/saber/avx2/polymul/scm_avx.c new file mode 100644 index 00000000..4e4f11f8 --- /dev/null +++ b/crypto_kem/saber/avx2/polymul/scm_avx.c @@ -0,0 +1,753 @@ +//#define SCM_SIZE 16 + +//#pragma STDC FP_CONTRACT ON + +#include + +inline __m256i mul_add(__m256i a, __m256i b, __m256i c) { + return _mm256_add_epi16(_mm256_mullo_epi16(a, b), c); +} + + +static void schoolbook_avx_new3_acc(__m256i* a, __m256i* b, __m256i* c_avx) ////8 coefficients of a and b has been prefetched + //the c_avx are added cummulatively +{ + + register __m256i a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7; + register __m256i temp; + + + a0=a[0]; + a1=a[1]; + a2=a[2]; + a3=a[3]; + a4=a[4]; + a5=a[5]; + a6=a[6]; + a7=a[7]; + + b0=b[0]; + b1=b[1]; + b2=b[2]; + b3=b[3]; + b4=b[4]; + b5=b[5]; + b6=b[6]; + b7=b[7]; + + // New Unrolled first triangle + + //otherwise accumulate + c_avx[0] = mul_add(a0, b0, c_avx[0]); + + + temp = _mm256_mullo_epi16 (a0, b1); + temp=mul_add(a1, b0, temp); + c_avx[1] = _mm256_add_epi16(temp, c_avx[1]); + + + temp = _mm256_mullo_epi16 (a0, b2); + temp = mul_add(a1, b1, temp); + temp=mul_add(a2, b0, temp); + c_avx[2] = _mm256_add_epi16(temp, c_avx[2]); + + + temp = _mm256_mullo_epi16 (a0, b3); + temp = mul_add(a1, b2, temp); + temp = mul_add(a2, b1, temp); + temp=mul_add(a3, b0, temp); + c_avx[3] = _mm256_add_epi16(temp, c_avx[3]); + + temp = _mm256_mullo_epi16 (a0, b4); + temp = mul_add(a1, b3, temp); + temp = mul_add(a3, b1, temp); + temp = mul_add(a4, b0, temp); + temp=mul_add(a2, b2, temp); + c_avx[4] = _mm256_add_epi16(temp, c_avx[4]); + + + temp = _mm256_mullo_epi16 (a0, b5); + temp = mul_add(a1, b4 , temp); + temp = mul_add(a2, b3, temp); + temp = mul_add(a3, b2, temp); + temp = mul_add( a4, b1, temp); + temp=mul_add(a5, b0, temp); + c_avx[5] = _mm256_add_epi16(temp, c_avx[5]); + + temp = _mm256_mullo_epi16 (a0, b6); + temp = mul_add(a1, b5, temp); + temp = mul_add(a5, b1, temp); + temp = mul_add(a6, b0, temp); + temp = mul_add(a2, b4, temp); + temp = mul_add(a3, b3, temp); + temp=mul_add(a4, b2, temp); + c_avx[6] = _mm256_add_epi16(temp, c_avx[6]); + + + temp = _mm256_mullo_epi16 (a0, b7); + temp = mul_add(a1, b6, temp); + temp = mul_add (a6, b1, temp); + temp = mul_add (a7, b0, temp); + temp = mul_add(a2, b5, temp); + temp = mul_add (a3, b4, temp); + temp = mul_add (a4, b3, temp); + temp=mul_add(a5, b2, temp); + c_avx[7] = _mm256_add_epi16(temp, c_avx[7]); + + temp = _mm256_mullo_epi16 (a0, b[8]); + temp = mul_add (a1, b7, temp); + temp = mul_add (a7, b1, temp); + temp = mul_add (a[8], b0, temp); + temp = mul_add (a2, b6,temp); + temp = mul_add(a3, b5, temp); + temp = mul_add (a4, b4,temp); + temp = mul_add (a5, b3, temp); + + temp=mul_add(a6, b2, temp); + c_avx[8] = _mm256_add_epi16(temp, c_avx[8]); + + + temp = _mm256_mullo_epi16 (a0, b[9]); + temp = mul_add (a1, b[8], temp); + temp = mul_add (a[8], b1, temp); + temp = mul_add (a[9], b0, temp); + temp = mul_add (a2, b7, temp); + temp = mul_add (a3, b6, temp); + temp = mul_add (a4, b5, temp); + temp = mul_add (a5, b4, temp); + temp = mul_add (a6, b3, temp); + temp=mul_add(a7, b2, temp); + c_avx[9] = _mm256_add_epi16(temp, c_avx[9]); + + + temp= _mm256_mullo_epi16 (a0, b[10]); + temp = mul_add (a1, b[9], temp); + temp = mul_add (a[9], b1, temp); + temp = mul_add (a[10], b0, temp); + temp = mul_add (a2, b[8], temp); + temp = mul_add (a3, b7, temp); + temp = mul_add (a4, b6, temp); + temp = mul_add (a5, b5, temp); + temp = mul_add (a6, b4, temp); + temp = mul_add (a7, b3, temp); + temp=mul_add(a[8], b2, temp); + c_avx[10] = _mm256_add_epi16(temp, c_avx[10]); + + + temp = _mm256_mullo_epi16 (a0, b[11]); + temp = mul_add (a1, b[10], temp ); + temp = mul_add (a[10], b1, temp ); + temp = mul_add (a[11], b0, temp ); + temp = mul_add (a2, b[9], temp ); + temp = mul_add (a3, b[8], temp ); + temp = mul_add (a4, b7, temp ); + temp = mul_add (a5, b6, temp ); + temp = mul_add (a6, b5, temp ); + temp = mul_add (a7, b4, temp ); + temp = mul_add (a[8], b3, temp ); + temp=mul_add(a[9], b2, temp); + c_avx[11] = _mm256_add_epi16(temp, c_avx[11]); + + + temp = _mm256_mullo_epi16 (a0, b[12]); + temp = mul_add (a1, b[11], temp); + temp = mul_add (a[11], b1, temp); + temp = mul_add (a[12], b0, temp); + temp = mul_add (a2, b[10], temp); + temp = mul_add (a3, b[9], temp); + temp = mul_add (a4, b[8], temp); + temp = mul_add (a5, b7, temp); + temp = mul_add (a6, b6, temp); + temp = mul_add (a7, b5, temp); + temp = mul_add (a[8], b4, temp); + temp = mul_add (a[9], b3, temp); + temp=mul_add(a[10], b2, temp); + c_avx[12] = _mm256_add_epi16(temp, c_avx[12]); + + + temp = _mm256_mullo_epi16 (a0, b[13]); + temp = mul_add (a1, b[12], temp ); + temp = mul_add (a[12], b1, temp ); + temp = mul_add (a[13], b0, temp ); + temp = mul_add (a2, b[11], temp ); + temp = mul_add (a3, b[10], temp ); + temp = mul_add (a4, b[9], temp ); + temp = mul_add (a5, b[8], temp ); + temp = mul_add (a6, b7, temp ); + temp = mul_add (a7, b6, temp ); + temp = mul_add (a[8], b5, temp ); + temp = mul_add (a[9], b4, temp ); + temp = mul_add (a[10], b3, temp ); + temp=mul_add(a[11], b2, temp); + c_avx[13] = _mm256_add_epi16(temp, c_avx[13]); + + + + temp = _mm256_mullo_epi16 (a0, b[14]); + temp = mul_add (a1, b[13], temp ); + temp = mul_add (a[13], b1, temp ); + temp = mul_add (a[14], b0, temp ); + temp = mul_add (a2, b[12], temp ); + temp = mul_add (a3, b[11], temp ); + temp = mul_add (a4, b[10], temp ); + temp = mul_add (a5, b[9], temp ); + temp = mul_add (a6, b[8], temp ); + temp = mul_add (a7, b7, temp ); + temp = mul_add (a[8], b6, temp ); + temp = mul_add (a[9], b5, temp ); + temp = mul_add (a[10], b4, temp ); + temp = mul_add (a[11], b3, temp ); + temp=mul_add(a[12], b2, temp); + c_avx[14] = _mm256_add_epi16(temp, c_avx[14]); + + + temp = _mm256_mullo_epi16 (a0, b[15]); + temp = mul_add (a1, b[14], temp ); + temp = mul_add (a[14], b1, temp ); + temp = mul_add (a[15], b0, temp ); + temp = mul_add (a2, b[13], temp ); + temp = mul_add (a3, b[12], temp ); + temp = mul_add (a4, b[11], temp ); + temp = mul_add (a5, b[10], temp ); + temp = mul_add (a6, b[9], temp ); + temp = mul_add (a7, b[8], temp ); + temp = mul_add (a[8], b7, temp ); + temp = mul_add (a[9], b6, temp ); + temp = mul_add (a[10], b5, temp ); + temp = mul_add (a[11], b4, temp ); + temp = mul_add (a[12], b3, temp ); + temp=mul_add(a[13], b2, temp); + c_avx[15] = _mm256_add_epi16(temp, c_avx[15]); + + + // unrolled second triangle + a0=a[14]; + a1=a[15]; + a2=a[13]; + a3=a[12]; + a4=a[11]; + a5=a[10]; + a6=a[9]; + a7=a[8]; + + b0=b[14]; + b1=b[15]; + b2=b[13]; + b3=b[12]; + b4=b[11]; + b5=b[10]; + b6=b[9]; + b7=b[8]; + + temp = _mm256_mullo_epi16 (a[1], b1); + temp = mul_add (a[2], b0, temp ); + temp = mul_add (a[3], b2, temp ); + temp = mul_add (a[4], b3, temp ); + temp = mul_add (a[5], b4, temp ); + temp = mul_add (a[6], b5, temp ); + temp = mul_add (a[7], b6, temp ); + temp = mul_add (a7, b7, temp ); + temp = mul_add (a6, b[7], temp ); + temp = mul_add (a5, b[6], temp ); + temp = mul_add (a4, b[5], temp ); + temp = mul_add (a3, b[4], temp ); + temp = mul_add (a2, b[3], temp ); + temp = mul_add (a0, b[2], temp ); + temp=mul_add(a1, b[1], temp); + c_avx[16] = _mm256_add_epi16(temp, c_avx[16]); + + + temp = _mm256_mullo_epi16 (a[2], b1); + temp = mul_add (a[3], b0, temp ); + temp = mul_add (a[4], b2, temp ); + temp = mul_add (a[5], b3, temp ); + temp = mul_add (a[6], b4, temp ); + temp = mul_add (a[7], b5, temp ); + temp = mul_add (a7, b6, temp ); + temp = mul_add (a6, b7, temp ); + temp = mul_add (a5, b[7], temp ); + temp = mul_add (a4, b[6], temp ); + temp = mul_add (a3, b[5], temp ); + temp = mul_add (a2, b[4], temp ); + temp = mul_add (a0, b[3], temp ); + temp=mul_add(a1, b[2], temp); + c_avx[17] = _mm256_add_epi16(temp, c_avx[17]); + + + temp = _mm256_mullo_epi16 (a[3], b1); + temp = mul_add (a[4], b0, temp ); + temp = mul_add (a[5], b2, temp ); + temp = mul_add (a[6], b3, temp ); + temp = mul_add (a[7], b4, temp ); + temp = mul_add (a7, b5, temp ); + temp = mul_add (a6, b6, temp ); + temp = mul_add (a5, b7, temp ); + temp = mul_add (a4, b[7], temp ); + temp = mul_add (a3, b[6], temp ); + temp = mul_add (a2, b[5], temp ); + temp = mul_add (a0, b[4], temp ); + temp=mul_add(a1, b[3], temp); + c_avx[18] = _mm256_add_epi16(temp, c_avx[18]); + + + temp = _mm256_mullo_epi16 (a[4], b1); + temp = mul_add (a[5], b0, temp ); + temp = mul_add (a[6], b2, temp ); + temp = mul_add (a[7], b3, temp ); + temp = mul_add (a7, b4, temp ); + temp = mul_add (a6, b5, temp ); + temp = mul_add (a5, b6, temp ); + temp = mul_add (a4, b7, temp ); + temp = mul_add (a3, b[7], temp ); + temp = mul_add (a2, b[6], temp ); + temp = mul_add (a0, b[5], temp ); + temp=mul_add(a1, b[4], temp); + c_avx[19] = _mm256_add_epi16(temp, c_avx[19]); + + + temp = _mm256_mullo_epi16 (a[5], b1); + temp = mul_add (a[6], b0, temp ); + temp = mul_add (a[7], b2, temp ); + temp = mul_add (a7, b3, temp ); + temp = mul_add (a6, b4, temp ); + temp = mul_add (a5, b5, temp ); + temp = mul_add (a4, b6, temp ); + temp = mul_add (a3, b7, temp ); + temp = mul_add (a2, b[7], temp ); + temp = mul_add (a0, b[6], temp ); + temp=mul_add(a1, b[5], temp); + c_avx[20] = _mm256_add_epi16(temp, c_avx[20]); + + + temp = _mm256_mullo_epi16 (a[6], b1); + temp = mul_add (a[7], b0, temp ); + temp = mul_add (a7, b2, temp ); + temp = mul_add (a6, b3, temp ); + temp = mul_add (a5, b4, temp ); + temp = mul_add (a4, b5, temp ); + temp = mul_add (a3, b6, temp ); + temp = mul_add (a2, b7, temp ); + temp = mul_add (a0, b[7], temp ); + temp=mul_add(a1, b[6], temp); + c_avx[21] = _mm256_add_epi16(temp, c_avx[21]); + + + temp = _mm256_mullo_epi16 (a[7], b1); + temp = mul_add (a7, b0, temp ); + temp = mul_add (a6, b2, temp ); + temp = mul_add (a5, b3, temp ); + temp = mul_add (a4, b4, temp ); + temp = mul_add (a3, b5, temp ); + temp = mul_add (a2, b6, temp ); + temp = mul_add (a0, b7, temp ); + temp=mul_add(a1, b[7], temp); + c_avx[22] = _mm256_add_epi16(temp, c_avx[22]); + + + temp = _mm256_mullo_epi16 (a7, b1); + temp = mul_add (a6, b0, temp ); + temp = mul_add (a5, b2, temp ); + temp = mul_add (a4, b3, temp ); + temp = mul_add (a3, b4, temp ); + temp = mul_add (a2, b5, temp ); + temp = mul_add (a0, b6, temp ); + temp=mul_add(a1, b7, temp); + c_avx[23] = _mm256_add_epi16(temp, c_avx[23]); + + + temp = _mm256_mullo_epi16 (a6, b1); + temp = mul_add (a5, b0, temp ); + temp = mul_add (a4, b2, temp ); + temp = mul_add (a3, b3, temp ); + temp = mul_add (a2, b4, temp ); + temp = mul_add (a0, b5, temp ); + temp=mul_add(a1, b6, temp); + c_avx[24] = _mm256_add_epi16(temp, c_avx[24]); + + + temp = _mm256_mullo_epi16 (a5, b1); + temp = mul_add (a4, b0, temp ); + temp = mul_add (a3, b2, temp ); + temp = mul_add (a2, b3, temp ); + temp = mul_add (a0, b4, temp ); + temp=mul_add(a1, b5, temp); + c_avx[25] = _mm256_add_epi16(temp, c_avx[25]); + + + temp = _mm256_mullo_epi16 (a4, b1); + temp = mul_add (a3, b0, temp ); + temp = mul_add (a2, b2, temp ); + temp = mul_add (a0, b3, temp ); + temp=mul_add(a1, b4, temp); + c_avx[26] = _mm256_add_epi16(temp, c_avx[26]); + + + temp = _mm256_mullo_epi16 (a3, b1); + temp = mul_add (a2, b0, temp ); + temp = mul_add (a0, b2, temp ); + temp=mul_add(a1, b3, temp); + c_avx[27] = _mm256_add_epi16(temp, c_avx[27]); + + + temp = _mm256_mullo_epi16 (a2, b1); + temp = mul_add (a0, b0, temp ); + temp=mul_add(a1, b2, temp); + c_avx[28] = _mm256_add_epi16(temp, c_avx[28]); + + + temp = _mm256_mullo_epi16 (a0, b1); + temp=mul_add(a1, b0, temp); + c_avx[29] = _mm256_add_epi16(temp, c_avx[29]); + + + c_avx[30] = mul_add(a1, b1, c_avx[30]); + + + + c_avx[2*SCM_SIZE-1] = _mm256_set_epi64x(0, 0, 0, 0); + + +} + + + +static void schoolbook_avx_new2(__m256i* a, __m256i* b, __m256i* c_avx) ////8 coefficients of a and b has been prefetched + //the c_avx are not added cummulatively +{ + + __m256i a0, a1, a2, a3, a4, a5, a6, a7, b0, b1, b2, b3, b4, b5, b6, b7; + __m256i temp; + + + a0=a[0]; + a1=a[1]; + a2=a[2]; + a3=a[3]; + a4=a[4]; + a5=a[5]; + a6=a[6]; + a7=a[7]; + + b0=b[0]; + b1=b[1]; + b2=b[2]; + b3=b[3]; + b4=b[4]; + b5=b[5]; + b6=b[6]; + b7=b[7]; + + // New Unrolled first triangle + c_avx[0] = _mm256_mullo_epi16 (a0, b0); + + temp = _mm256_mullo_epi16 (a0, b1); + c_avx[1]=mul_add(a1, b0, temp); + + temp = _mm256_mullo_epi16 (a0, b2); + + temp = mul_add(a1, b1, temp); + c_avx[2]= mul_add(a2, b0, temp); + + temp = _mm256_mullo_epi16 (a0, b3); + temp = mul_add(a1, b2, temp); + temp = mul_add(a2, b1, temp); + c_avx[3]= mul_add(a3, b0, temp); + + temp = _mm256_mullo_epi16 (a0, b4); + temp = mul_add(a1, b3, temp); + temp = mul_add(a3, b1, temp); + temp = mul_add(a4, b0, temp); + c_avx[4]= mul_add(a2, b2, temp); + + temp = _mm256_mullo_epi16 (a0, b5); + temp = mul_add(a1, b4 , temp); + temp = mul_add(a2, b3, temp); + temp = mul_add(a3, b2, temp); + temp = mul_add( a4, b1, temp); + c_avx[5] = mul_add(a5, b0, temp); + + temp = _mm256_mullo_epi16 (a0, b6); + temp = mul_add(a1, b5, temp); + temp = mul_add(a5, b1, temp); + temp = mul_add(a6, b0, temp); + temp = mul_add(a2, b4, temp); + temp = mul_add(a3, b3, temp); + c_avx[6] = mul_add(a4, b2, temp); + + temp = _mm256_mullo_epi16 (a0, b7); + temp = mul_add(a1, b6, temp); + temp = mul_add (a6, b1, temp); + temp = mul_add (a7, b0, temp); + temp = mul_add(a2, b5, temp); + temp = mul_add (a3, b4, temp); + temp = mul_add (a4, b3, temp); + c_avx[7] = mul_add (a5, b2, temp); + + temp = _mm256_mullo_epi16 (a0, b[8]); + temp = mul_add (a1, b7, temp); + temp = mul_add (a7, b1, temp); + temp = mul_add (a[8], b0, temp); + temp = mul_add (a2, b6,temp); + temp = mul_add(a3, b5, temp); + temp = mul_add (a4, b4,temp); + temp = mul_add (a5, b3, temp); + c_avx[8] = mul_add (a6, b2, temp); + + temp = _mm256_mullo_epi16 (a0, b[9]); + temp = mul_add (a1, b[8], temp); + temp = mul_add (a[8], b1, temp); + temp = mul_add (a[9], b0, temp); + temp = mul_add (a2, b7, temp); + temp = mul_add (a3, b6, temp); + temp = mul_add (a4, b5, temp); + temp = mul_add (a5, b4, temp); + temp = mul_add (a6, b3, temp); + c_avx[9] = mul_add (a7, b2, temp); + + temp= _mm256_mullo_epi16 (a0, b[10]); + temp = mul_add (a1, b[9], temp); + temp = mul_add (a[9], b1, temp); + temp = mul_add (a[10], b0, temp); + temp = mul_add (a2, b[8], temp); + temp = mul_add (a3, b7, temp); + temp = mul_add (a4, b6, temp); + temp = mul_add (a5, b5, temp); + temp = mul_add (a6, b4, temp); + temp = mul_add (a7, b3, temp); + c_avx[10] = mul_add (a[8], b2, temp); + + temp = _mm256_mullo_epi16 (a0, b[11]); + temp = mul_add (a1, b[10], temp ); + temp = mul_add (a[10], b1, temp ); + temp = mul_add (a[11], b0, temp ); + temp = mul_add (a2, b[9], temp ); + temp = mul_add (a3, b[8], temp ); + temp = mul_add (a4, b7, temp ); + temp = mul_add (a5, b6, temp ); + temp = mul_add (a6, b5, temp ); + temp = mul_add (a7, b4, temp ); + temp = mul_add (a[8], b3, temp ); + c_avx[11] = mul_add (a[9], b2, temp ); + + temp = _mm256_mullo_epi16 (a0, b[12]); + temp = mul_add (a1, b[11], temp); + temp = mul_add (a[11], b1, temp); + temp = mul_add (a[12], b0, temp); + temp = mul_add (a2, b[10], temp); + temp = mul_add (a3, b[9], temp); + temp = mul_add (a4, b[8], temp); + temp = mul_add (a5, b7, temp); + temp = mul_add (a6, b6, temp); + temp = mul_add (a7, b5, temp); + temp = mul_add (a[8], b4, temp); + temp = mul_add (a[9], b3, temp); + c_avx[12] = mul_add (a[10], b2, temp); + + temp = _mm256_mullo_epi16 (a0, b[13]); + temp = mul_add (a1, b[12], temp ); + temp = mul_add (a[12], b1, temp ); + temp = mul_add (a[13], b0, temp ); + temp = mul_add (a2, b[11], temp ); + temp = mul_add (a3, b[10], temp ); + temp = mul_add (a4, b[9], temp ); + temp = mul_add (a5, b[8], temp ); + temp = mul_add (a6, b7, temp ); + temp = mul_add (a7, b6, temp ); + temp = mul_add (a[8], b5, temp ); + temp = mul_add (a[9], b4, temp ); + temp = mul_add (a[10], b3, temp ); + c_avx[13] = mul_add (a[11], b2, temp ); + + temp = _mm256_mullo_epi16 (a0, b[14]); + temp = mul_add (a1, b[13], temp ); + temp = mul_add (a[13], b1, temp ); + temp = mul_add (a[14], b0, temp ); + temp = mul_add (a2, b[12], temp ); + temp = mul_add (a3, b[11], temp ); + temp = mul_add (a4, b[10], temp ); + temp = mul_add (a5, b[9], temp ); + temp = mul_add (a6, b[8], temp ); + temp = mul_add (a7, b7, temp ); + temp = mul_add (a[8], b6, temp ); + temp = mul_add (a[9], b5, temp ); + temp = mul_add (a[10], b4, temp ); + temp = mul_add (a[11], b3, temp ); + c_avx[14] = mul_add (a[12], b2, temp ); + + temp = _mm256_mullo_epi16 (a0, b[15]); + temp = mul_add (a1, b[14], temp ); + temp = mul_add (a[14], b1, temp ); + temp = mul_add (a[15], b0, temp ); + temp = mul_add (a2, b[13], temp ); + temp = mul_add (a3, b[12], temp ); + temp = mul_add (a4, b[11], temp ); + temp = mul_add (a5, b[10], temp ); + temp = mul_add (a6, b[9], temp ); + temp = mul_add (a7, b[8], temp ); + temp = mul_add (a[8], b7, temp ); + temp = mul_add (a[9], b6, temp ); + temp = mul_add (a[10], b5, temp ); + temp = mul_add (a[11], b4, temp ); + temp = mul_add (a[12], b3, temp ); + c_avx[15] = mul_add (a[13], b2, temp ); + + + // unrolled second triangle + a0=a[14]; + a1=a[15]; + a2=a[13]; + a3=a[12]; + a4=a[11]; + a5=a[10]; + a6=a[9]; + a7=a[8]; + + b0=b[14]; + b1=b[15]; + b2=b[13]; + b3=b[12]; + b4=b[11]; + b5=b[10]; + b6=b[9]; + b7=b[8]; + + + temp = _mm256_mullo_epi16 (a[1], b1); + temp = mul_add (a[2], b0, temp ); + temp = mul_add (a[3], b2, temp ); + temp = mul_add (a[4], b3, temp ); + temp = mul_add (a[5], b4, temp ); + temp = mul_add (a[6], b5, temp ); + temp = mul_add (a[7], b6, temp ); + temp = mul_add (a7, b7, temp ); + temp = mul_add (a6, b[7], temp ); + temp = mul_add (a5, b[6], temp ); + temp = mul_add (a4, b[5], temp ); + temp = mul_add (a3, b[4], temp ); + temp = mul_add (a2, b[3], temp ); + temp = mul_add (a0, b[2], temp ); + c_avx[16] = mul_add (a1, b[1], temp ); + + temp = _mm256_mullo_epi16 (a[2], b1); + temp = mul_add (a[3], b0, temp ); + temp = mul_add (a[4], b2, temp ); + temp = mul_add (a[5], b3, temp ); + temp = mul_add (a[6], b4, temp ); + temp = mul_add (a[7], b5, temp ); + temp = mul_add (a7, b6, temp ); + temp = mul_add (a6, b7, temp ); + temp = mul_add (a5, b[7], temp ); + temp = mul_add (a4, b[6], temp ); + temp = mul_add (a3, b[5], temp ); + temp = mul_add (a2, b[4], temp ); + temp = mul_add (a0, b[3], temp ); + c_avx[17] = mul_add (a1, b[2], temp ); + + temp = _mm256_mullo_epi16 (a[3], b1); + temp = mul_add (a[4], b0, temp ); + temp = mul_add (a[5], b2, temp ); + temp = mul_add (a[6], b3, temp ); + temp = mul_add (a[7], b4, temp ); + temp = mul_add (a7, b5, temp ); + temp = mul_add (a6, b6, temp ); + temp = mul_add (a5, b7, temp ); + temp = mul_add (a4, b[7], temp ); + temp = mul_add (a3, b[6], temp ); + temp = mul_add (a2, b[5], temp ); + temp = mul_add (a0, b[4], temp ); + c_avx[18] = mul_add (a1, b[3], temp ); + + temp = _mm256_mullo_epi16 (a[4], b1); + temp = mul_add (a[5], b0, temp ); + temp = mul_add (a[6], b2, temp ); + temp = mul_add (a[7], b3, temp ); + temp = mul_add (a7, b4, temp ); + temp = mul_add (a6, b5, temp ); + temp = mul_add (a5, b6, temp ); + temp = mul_add (a4, b7, temp ); + temp = mul_add (a3, b[7], temp ); + temp = mul_add (a2, b[6], temp ); + temp = mul_add (a0, b[5], temp ); + c_avx[19] = mul_add (a1, b[4], temp ); + + temp = _mm256_mullo_epi16 (a[5], b1); + temp = mul_add (a[6], b0, temp ); + temp = mul_add (a[7], b2, temp ); + temp = mul_add (a7, b3, temp ); + temp = mul_add (a6, b4, temp ); + temp = mul_add (a5, b5, temp ); + temp = mul_add (a4, b6, temp ); + temp = mul_add (a3, b7, temp ); + temp = mul_add (a2, b[7], temp ); + temp = mul_add (a0, b[6], temp ); + c_avx[20] = mul_add (a1, b[5], temp ); + + temp = _mm256_mullo_epi16 (a[6], b1); + temp = mul_add (a[7], b0, temp ); + temp = mul_add (a7, b2, temp ); + temp = mul_add (a6, b3, temp ); + temp = mul_add (a5, b4, temp ); + temp = mul_add (a4, b5, temp ); + temp = mul_add (a3, b6, temp ); + temp = mul_add (a2, b7, temp ); + temp = mul_add (a0, b[7], temp ); + c_avx[21] = mul_add (a1, b[6], temp ); + + temp = _mm256_mullo_epi16 (a[7], b1); + temp = mul_add (a7, b0, temp ); + temp = mul_add (a6, b2, temp ); + temp = mul_add (a5, b3, temp ); + temp = mul_add (a4, b4, temp ); + temp = mul_add (a3, b5, temp ); + temp = mul_add (a2, b6, temp ); + temp = mul_add (a0, b7, temp ); + c_avx[22] = mul_add (a1, b[7], temp ); + + temp = _mm256_mullo_epi16 (a7, b1); + temp = mul_add (a6, b0, temp ); + temp = mul_add (a5, b2, temp ); + temp = mul_add (a4, b3, temp ); + temp = mul_add (a3, b4, temp ); + temp = mul_add (a2, b5, temp ); + temp = mul_add (a0, b6, temp ); + c_avx[23] = mul_add (a1, b7, temp ); + + temp = _mm256_mullo_epi16 (a6, b1); + temp = mul_add (a5, b0, temp ); + temp = mul_add (a4, b2, temp ); + temp = mul_add (a3, b3, temp ); + temp = mul_add (a2, b4, temp ); + temp = mul_add (a0, b5, temp ); + c_avx[24] = mul_add (a1, b6, temp ); + + temp = _mm256_mullo_epi16 (a5, b1); + temp = mul_add (a4, b0, temp ); + temp = mul_add (a3, b2, temp ); + temp = mul_add (a2, b3, temp ); + temp = mul_add (a0, b4, temp ); + c_avx[25] = mul_add (a1, b5, temp ); + + temp = _mm256_mullo_epi16 (a4, b1); + temp = mul_add (a3, b0, temp ); + temp = mul_add (a2, b2, temp ); + temp = mul_add (a0, b3, temp ); + c_avx[26] = mul_add (a1, b4, temp ); + + temp = _mm256_mullo_epi16 (a3, b1); + temp = mul_add (a2, b0, temp ); + temp = mul_add (a0, b2, temp ); + c_avx[27] = mul_add (a1, b3, temp ); + + temp = _mm256_mullo_epi16 (a2, b1); + temp = mul_add (a0, b0, temp ); + c_avx[28] = mul_add (a1, b2, temp ); + + temp = _mm256_mullo_epi16 (a0, b1); + c_avx[29] = mul_add (a1, b0, temp); + + c_avx[30] = _mm256_mullo_epi16 (a1, b1); + + + c_avx[2*SCM_SIZE-1] = _mm256_set_epi64x(0, 0, 0, 0); + +} diff --git a/crypto_kem/saber/avx2/polymul/toom-cook_4way.c b/crypto_kem/saber/avx2/polymul/toom-cook_4way.c new file mode 100644 index 00000000..78fb86c2 --- /dev/null +++ b/crypto_kem/saber/avx2/polymul/toom-cook_4way.c @@ -0,0 +1,1010 @@ +/* +Cleaned version for step by step approach look into the _debug file +*/ +//#include "timing.c" +#include "consts.h" +#include "matrix.c" +#include "scm_avx.c" + +static void batch_64coefficient_multiplications_new(__m256i* a, __m256i* b_bucket, __m256i* c_bucket, int f)//all 7 Karatsuba evaluation and interpolation are done in AVX. +{ + __m256i a_bucket[SCM_SIZE*4]; //SCM_SIZE = 16; Holds evaluation (a & b) for 7 Karatsuba at a time + + //uint16_t i; + + register __m256i r0_avx, r1_avx, r2_avx, r3_avx; + + + + //CLOCK1=cpucycles(); + + //------------------AVX evaluation for 1st poly----------------------- + + r0_avx=a[0]; + r1_avx=a[1]; + r2_avx=a[2]; + r3_avx=a[3]; + a_bucket[0]=r0_avx; + a_bucket[1]=r1_avx; + a_bucket[2]=r2_avx; + a_bucket[3]=r3_avx; + a_bucket[4]= _mm256_add_epi16(r0_avx, r1_avx); + a_bucket[5]= _mm256_add_epi16(r2_avx, r3_avx); + a_bucket[6]= _mm256_add_epi16(r0_avx, r2_avx); + a_bucket[7]= _mm256_add_epi16(r1_avx, r3_avx); + a_bucket[8]= _mm256_add_epi16(a_bucket[6],a_bucket[7]); + + + //------------------AVX evaluation for 1st poly ends------------------ + + + //------------------AVX evaluation for 2nd poly----------------------- + r0_avx=a[small_len_avx]; + r1_avx=a[small_len_avx+1]; + r2_avx=a[small_len_avx+2]; + r3_avx=a[small_len_avx+3]; + a_bucket[0+9]=r0_avx; + a_bucket[1+9]=r1_avx; + a_bucket[2+9]=r2_avx; + a_bucket[3+9]=r3_avx; + a_bucket[4+9]= _mm256_add_epi16(r0_avx, r1_avx); + a_bucket[5+9]= _mm256_add_epi16(r2_avx, r3_avx); + a_bucket[6+9]= _mm256_add_epi16(r0_avx, r2_avx); + a_bucket[7+9]= _mm256_add_epi16(r1_avx, r3_avx); + a_bucket[8+9]= _mm256_add_epi16(a_bucket[6+9],a_bucket[7+9]); + + + //------------------AVX evaluation for 2nd poly ends------------------ + + + //------------------AVX evaluation for 3rd poly----------------------- + r0_avx=a[2*small_len_avx]; + r1_avx=a[2*small_len_avx+1]; + r2_avx=a[2*small_len_avx+2]; + r3_avx=a[2*small_len_avx+3]; + a_bucket[0+18]=r0_avx; + a_bucket[1+18]=r1_avx; + a_bucket[2+18]=r2_avx; + a_bucket[3+18]=r3_avx; + a_bucket[4+18]= _mm256_add_epi16(r0_avx, r1_avx); + a_bucket[5+18]= _mm256_add_epi16(r2_avx, r3_avx); + a_bucket[6+18]= _mm256_add_epi16(r0_avx, r2_avx); + a_bucket[7+18]= _mm256_add_epi16(r1_avx, r3_avx); + a_bucket[8+18]= _mm256_add_epi16(a_bucket[6+18],a_bucket[7+18]); + + //------------------AVX evaluation for 3rd poly ends------------------ + + + //------------------AVX evaluation for 4th poly----------------------- + + r0_avx=a[3*small_len_avx]; + r1_avx=a[3*small_len_avx+1]; + r2_avx=a[3*small_len_avx+2]; + r3_avx=a[3*small_len_avx+3]; + a_bucket[0+27]=r0_avx; + a_bucket[1+27]=r1_avx; + a_bucket[2+27]=r2_avx; + a_bucket[3+27]=r3_avx; + a_bucket[4+27]= _mm256_add_epi16(r0_avx, r1_avx); + a_bucket[5+27]= _mm256_add_epi16(r2_avx, r3_avx); + a_bucket[6+27]= _mm256_add_epi16(r0_avx, r2_avx); + a_bucket[7+27]= _mm256_add_epi16(r1_avx, r3_avx); + a_bucket[8+27]= _mm256_add_epi16(a_bucket[6+27],a_bucket[7+27]); + + //------------------AVX evaluation for 4th poly ends------------------ + + //------------------AVX evaluation for 5th poly----------------------- + + r0_avx=a[4*small_len_avx+0]; + r1_avx=a[4*small_len_avx+1]; + r2_avx=a[4*small_len_avx+2]; + r3_avx=a[4*small_len_avx+3]; + a_bucket[0+36]=r0_avx; + a_bucket[1+36]=r1_avx; + a_bucket[2+36]=r2_avx; + a_bucket[3+36]=r3_avx; + a_bucket[4+36]= _mm256_add_epi16(r0_avx, r1_avx); + a_bucket[5+36]= _mm256_add_epi16(r2_avx, r3_avx); + a_bucket[6+36]= _mm256_add_epi16(r0_avx, r2_avx); + a_bucket[7+36]= _mm256_add_epi16(r1_avx, r3_avx); + a_bucket[8+36]= _mm256_add_epi16(a_bucket[6+36],a_bucket[7+36]); + + //------------------AVX evaluation for 5th poly ends------------------ + + + //------------------AVX evaluation for 6th poly----------------------- + r0_avx=a[5*small_len_avx]; + r1_avx=a[5*small_len_avx+1]; + r2_avx=a[5*small_len_avx+2]; + r3_avx=a[5*small_len_avx+3]; + a_bucket[0+45]=r0_avx; + a_bucket[1+45]=r1_avx; + a_bucket[2+45]=r2_avx; + a_bucket[3+45]=r3_avx; + a_bucket[4+45]= _mm256_add_epi16(r0_avx, r1_avx); + a_bucket[5+45]= _mm256_add_epi16(r2_avx, r3_avx); + a_bucket[6+45]= _mm256_add_epi16(r0_avx, r2_avx); + a_bucket[7+45]= _mm256_add_epi16(r1_avx, r3_avx); + a_bucket[8+45]= _mm256_add_epi16(a_bucket[6+45],a_bucket[7+45]); + + //------------------AVX evaluation for 6th poly ends------------------ + + //------------------AVX evaluation for 7th poly----------------------- + + r0_avx=a[6*small_len_avx]; + r1_avx=a[6*small_len_avx+1]; + r2_avx=a[6*small_len_avx+2]; + r3_avx=a[6*small_len_avx+3]; + a_bucket[0+54]=r0_avx; + a_bucket[1+54]=r1_avx; + a_bucket[2+54]=r2_avx; + a_bucket[3+54]=r3_avx; + a_bucket[4+54]= _mm256_add_epi16(r0_avx, r1_avx); + a_bucket[5+54]= _mm256_add_epi16(r2_avx, r3_avx); + a_bucket[6+54]= _mm256_add_epi16(r0_avx, r2_avx); + a_bucket[7+54]= _mm256_add_epi16(r1_avx, r3_avx); + a_bucket[8+54]= _mm256_add_epi16(a_bucket[6+54],a_bucket[7+54]); + + //------------------AVX evaluation for 7th poly ends------------------ + + + + //CLOCK2=cpucycles(); + //CLOCK_EVAL=CLOCK_EVAL+(CLOCK2-CLOCK1); + //printf("\nTime for multiplication : %llu\n", CLOCK2-CLOCK1); + + + //CLOCK1=cpucycles(); + //-----------------Forward transposes-------------------------------------- + transpose_n1(a_bucket); + transpose_n1(a_bucket+16); + transpose_n1(a_bucket+32); + transpose_n1(a_bucket+48); + + //-----------------Forwatrd transposes ends--------------------------------- + + //----------------------all multiplications--------------------------------- + if(f==0){ + schoolbook_avx_new2(a_bucket, b_bucket, c_bucket); + schoolbook_avx_new2(a_bucket+16, b_bucket+16, c_bucket+2*SCM_SIZE); + schoolbook_avx_new2(a_bucket+32, b_bucket+32, c_bucket+4*SCM_SIZE); + schoolbook_avx_new2(a_bucket+48, b_bucket+48, c_bucket+6*SCM_SIZE); + } + else{ + schoolbook_avx_new3_acc(a_bucket, b_bucket, c_bucket); + schoolbook_avx_new3_acc(a_bucket+16, b_bucket+16, c_bucket+2*SCM_SIZE); + //schoolbook_avx_new3_acc_fused(a_bucket, b_bucket, c_bucket); + schoolbook_avx_new3_acc(a_bucket+32, b_bucket+32, c_bucket+4*SCM_SIZE); + schoolbook_avx_new3_acc(a_bucket+48, b_bucket+48, c_bucket+6*SCM_SIZE); + } + /* + schoolbook_avx_new2_acc(a_bucket, b_bucket, c_bucket, f); + schoolbook_avx_new2_acc(a_bucket+16, b_bucket+16, c_bucket+2*SCM_SIZE, f); + schoolbook_avx_new2_acc(a_bucket+32, b_bucket+32, c_bucket+4*SCM_SIZE, f); + schoolbook_avx_new2_acc(a_bucket+48, b_bucket+48, c_bucket+6*SCM_SIZE, f); + */ + + + //----------------------all multiplications ends----------------------------- + + + //-----------------Reverse transposes-------------------------------------- + + /* + transpose(c_bucket); + transpose(c_bucket+16); + + transpose(c_bucket+2*SCM_SIZE); + transpose(c_bucket+16+2*SCM_SIZE); + + transpose(c_bucket+4*SCM_SIZE); + transpose(c_bucket+16+4*SCM_SIZE); + + transpose(c_bucket+6*SCM_SIZE); + transpose(c_bucket+16+6*SCM_SIZE); + */ + //-----------------Reverse transposes ends--------------------------------- + + //CLOCK2=cpucycles(); + //CLOCK_MULT=CLOCK_MULT+(CLOCK2-CLOCK1); + + //KARA_interpol(c_bucket, result_final0, result_final1, result_final2, result_final3, result_final4, result_final5, result_final6); + +} + +static void KARA_eval(__m256i* b, __m256i *b_bucket){ + + __m256i r0_avx, r1_avx, r2_avx, r3_avx; + + + //-------1st poly---------------------------------------------------- + r0_avx=b[0]; + r1_avx=b[1]; + r2_avx=b[2]; + r3_avx=b[3]; + b_bucket[0]=r0_avx; + b_bucket[1]=r1_avx; + b_bucket[2]=r2_avx; + b_bucket[3]=r3_avx; + b_bucket[4]= _mm256_add_epi16(r0_avx, r1_avx); + b_bucket[5]= _mm256_add_epi16(r2_avx, r3_avx); + b_bucket[6]= _mm256_add_epi16(r0_avx, r2_avx); + b_bucket[7]= _mm256_add_epi16(r1_avx, r3_avx); + b_bucket[8]= _mm256_add_epi16(b_bucket[6],b_bucket[7]); + //-------2nd poly---------------------------------------------------- + + r0_avx=b[small_len_avx]; + r1_avx=b[small_len_avx+1]; + r2_avx=b[small_len_avx+2]; + r3_avx=b[small_len_avx+3]; + b_bucket[0+9]=r0_avx; + b_bucket[1+9]=r1_avx; + b_bucket[2+9]=r2_avx; + b_bucket[3+9]=r3_avx; + b_bucket[4+9]= _mm256_add_epi16(r0_avx, r1_avx); + b_bucket[5+9]= _mm256_add_epi16(r2_avx, r3_avx); + b_bucket[6+9]= _mm256_add_epi16(r0_avx, r2_avx); + b_bucket[7+9]= _mm256_add_epi16(r1_avx, r3_avx); + b_bucket[8+9]= _mm256_add_epi16(b_bucket[6+9],b_bucket[7+9]); + + //-------3rd poly---------------------------------------------------- + + r0_avx=b[2*small_len_avx+0]; + r1_avx=b[2*small_len_avx+1]; + r2_avx=b[2*small_len_avx+2]; + r3_avx=b[2*small_len_avx+3]; + b_bucket[0+18]=r0_avx; + b_bucket[1+18]=r1_avx; + b_bucket[2+18]=r2_avx; + b_bucket[3+18]=r3_avx; + b_bucket[4+18]= _mm256_add_epi16(r0_avx, r1_avx); + b_bucket[5+18]= _mm256_add_epi16(r2_avx, r3_avx); + b_bucket[6+18]= _mm256_add_epi16(r0_avx, r2_avx); + b_bucket[7+18]= _mm256_add_epi16(r1_avx, r3_avx); + b_bucket[8+18]= _mm256_add_epi16(b_bucket[6+18],b_bucket[7+18]); + + //-------4th poly---------------------------------------------------- + r0_avx=b[3*small_len_avx]; + r1_avx=b[3*small_len_avx+1]; + r2_avx=b[3*small_len_avx+2]; + r3_avx=b[3*small_len_avx+3]; + b_bucket[0+27]=r0_avx; + b_bucket[1+27]=r1_avx; + b_bucket[2+27]=r2_avx; + b_bucket[3+27]=r3_avx; + b_bucket[4+27]= _mm256_add_epi16(r0_avx, r1_avx); + b_bucket[5+27]= _mm256_add_epi16(r2_avx, r3_avx); + b_bucket[6+27]= _mm256_add_epi16(r0_avx, r2_avx); + b_bucket[7+27]= _mm256_add_epi16(r1_avx, r3_avx); + b_bucket[8+27]= _mm256_add_epi16(b_bucket[6+27],b_bucket[7+27]); + + //-------5th poly---------------------------------------------------- + + r0_avx=b[4*small_len_avx]; + r1_avx=b[4*small_len_avx+1]; + r2_avx=b[4*small_len_avx+2]; + r3_avx=b[4*small_len_avx+3]; + b_bucket[0+36]=r0_avx; + b_bucket[1+36]=r1_avx; + b_bucket[2+36]=r2_avx; + b_bucket[3+36]=r3_avx; + b_bucket[4+36]= _mm256_add_epi16(r0_avx, r1_avx); + b_bucket[5+36]= _mm256_add_epi16(r2_avx, r3_avx); + b_bucket[6+36]= _mm256_add_epi16(r0_avx, r2_avx); + b_bucket[7+36]= _mm256_add_epi16(r1_avx, r3_avx); + b_bucket[8+36]= _mm256_add_epi16(b_bucket[6+36],b_bucket[7+36]); + + //-------6th poly---------------------------------------------------- + + r0_avx=b[5*small_len_avx]; + r1_avx=b[5*small_len_avx+1]; + r2_avx=b[5*small_len_avx+2]; + r3_avx=b[5*small_len_avx+3]; + b_bucket[0+45]=r0_avx; + b_bucket[1+45]=r1_avx; + b_bucket[2+45]=r2_avx; + b_bucket[3+45]=r3_avx; + b_bucket[4+45]= _mm256_add_epi16(r0_avx, r1_avx); + b_bucket[5+45]= _mm256_add_epi16(r2_avx, r3_avx); + b_bucket[6+45]= _mm256_add_epi16(r0_avx, r2_avx); + b_bucket[7+45]= _mm256_add_epi16(r1_avx, r3_avx); + b_bucket[8+45]= _mm256_add_epi16(b_bucket[6+45],b_bucket[7+45]); + + //-------7th poly---------------------------------------------------- + + r0_avx=b[6*small_len_avx]; + r1_avx=b[6*small_len_avx+1]; + r2_avx=b[6*small_len_avx+2]; + r3_avx=b[6*small_len_avx+3]; + b_bucket[0+54]=r0_avx; + b_bucket[1+54]=r1_avx; + b_bucket[2+54]=r2_avx; + b_bucket[3+54]=r3_avx; + b_bucket[4+54]= _mm256_add_epi16(r0_avx, r1_avx); + b_bucket[5+54]= _mm256_add_epi16(r2_avx, r3_avx); + b_bucket[6+54]= _mm256_add_epi16(r0_avx, r2_avx); + b_bucket[7+54]= _mm256_add_epi16(r1_avx, r3_avx); + b_bucket[8+54]= _mm256_add_epi16(b_bucket[6+54],b_bucket[7+54]); + + //--------------Evaluating B poly ends------------------------------- + + transpose_n1(b_bucket); + transpose_n1(b_bucket+16); + transpose_n1(b_bucket+32); + transpose_n1(b_bucket+48); +} + +static void KARA_interpol(__m256i *c_bucket, __m256i* result_final0, __m256i* result_final1, __m256i* result_final2, __m256i* result_final3, __m256i* result_final4, __m256i* result_final5, __m256i* result_final6){ + + //int64_t i; + register __m256i res_avx0, res_avx1, res_avx2, res_avx3, res_avx4, res_avx5, res_avx6, res_avx7; // to hold each 64X64 poly mul results + + __m256i temp, c6_avx, c7_avx, c8_avx, c20_avx, c21_avx, c22_avx, c23_avx, c24_avx; + + //CLOCK1=cpucycles(); + + //------------------------AVX interpolation for 1st poly external------------------- + + //loop1 + res_avx0 = c_bucket[0]; + res_avx2 = c_bucket[1]; + res_avx4 = c_bucket[2]; + res_avx6 = c_bucket[3]; + + c6_avx=c_bucket[6]; + c7_avx=c_bucket[7]; + + c8_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[8], c6_avx), c7_avx); + + res_avx1 = c_bucket[16]; + res_avx3 = c_bucket[17]; + res_avx5 = c_bucket[18]; + res_avx7 = c_bucket[19]; + + c22_avx=c_bucket[22]; + c23_avx=c_bucket[23]; + + c21_avx=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[21], res_avx5),res_avx7); + + c24_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[24], c22_avx), c23_avx); + + c20_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[20], res_avx1), res_avx3); + + temp=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[5], res_avx4),res_avx6); + res_avx5 = _mm256_add_epi16(res_avx5, temp); + + temp = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[4], res_avx0), res_avx2); + res_avx1 = _mm256_add_epi16(res_avx1, temp); + + c22_avx=_mm256_add_epi16(c22_avx, c8_avx); + + res_avx6 = _mm256_add_epi16(res_avx6, c21_avx); + + res_avx2 = _mm256_add_epi16(res_avx2, c20_avx); + + c7_avx=_mm256_add_epi16(c7_avx, c24_avx); + + + //loop4 + + c6_avx=_mm256_sub_epi16(_mm256_sub_epi16(c6_avx, res_avx0), res_avx4); + c22_avx=_mm256_sub_epi16(_mm256_sub_epi16(c22_avx, res_avx1), res_avx5); + + c7_avx=_mm256_sub_epi16(_mm256_sub_epi16(c7_avx, res_avx2), res_avx6); + c23_avx=_mm256_sub_epi16(_mm256_sub_epi16(c23_avx, res_avx3), res_avx7); + + //loop5 + result_final0[0]=res_avx0; + result_final0[1]=res_avx1; + + result_final0[2]=_mm256_add_epi16(res_avx2, c6_avx); + result_final0[3]=_mm256_add_epi16(res_avx3, c22_avx); + + + result_final0[4]=_mm256_add_epi16(res_avx4, c7_avx); + result_final0[5]=_mm256_add_epi16(res_avx5, c23_avx); + + result_final0[6]=res_avx6; + result_final0[7]=res_avx7; + + + //------------------------AVX interpolation for 1st poly ends-------------- + + + //------------------------AVX interpolation for 2nd poly external------------------- + + //loop1 + res_avx0 = c_bucket[9]; //c_bucket0 + res_avx2 = c_bucket[10]; //c_bucket1 + res_avx4 = c_bucket[11]; //c_bucket2 + res_avx6 = c_bucket[12]; //c_bucket3 + + c6_avx=c_bucket[15]; //c_bucket6 + c7_avx=c_bucket[32]; //c_bucket7 + + c8_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[33], c6_avx), c7_avx); + + res_avx1 = c_bucket[25]; //c_bucket0 + res_avx3 = c_bucket[26]; //c_bucket1 + res_avx5 = c_bucket[27]; //c_bucket2 + res_avx7 = c_bucket[28]; //c_bucket3 + + c22_avx=c_bucket[31]; + c23_avx=c_bucket[48]; + + c21_avx=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[30], res_avx5),res_avx7); + + c24_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[49], c22_avx), c23_avx); + + c20_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[29], res_avx1), res_avx3); + + temp=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[14], res_avx4),res_avx6); + res_avx5 = _mm256_add_epi16(res_avx5, temp); + + temp = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[13], res_avx0), res_avx2); + res_avx1 = _mm256_add_epi16(res_avx1, temp); + + c22_avx=_mm256_add_epi16(c22_avx, c8_avx); + + res_avx6 = _mm256_add_epi16(res_avx6, c21_avx); + + res_avx2 = _mm256_add_epi16(res_avx2, c20_avx); + + c7_avx=_mm256_add_epi16(c7_avx, c24_avx); + + + //loop4 + + c6_avx=_mm256_sub_epi16(_mm256_sub_epi16(c6_avx, res_avx0), res_avx4); + c22_avx=_mm256_sub_epi16(_mm256_sub_epi16(c22_avx, res_avx1), res_avx5); + + c7_avx=_mm256_sub_epi16(_mm256_sub_epi16(c7_avx, res_avx2), res_avx6); + c23_avx=_mm256_sub_epi16(_mm256_sub_epi16(c23_avx, res_avx3), res_avx7); + + //loop5 + result_final1[0]=res_avx0; + result_final1[1]=res_avx1; + + result_final1[2]=_mm256_add_epi16(res_avx2, c6_avx); + result_final1[3]=_mm256_add_epi16(res_avx3, c22_avx); + + + result_final1[4]=_mm256_add_epi16(res_avx4, c7_avx); + result_final1[5]=_mm256_add_epi16(res_avx5, c23_avx); + + result_final1[6]=res_avx6; + result_final1[7]=res_avx7; + + + //------------------------AVX interpolation for 2nd poly ends-------------- + + //------------------------AVX interpolation for 3rd poly external------------------- + + //loop1 + res_avx0 = c_bucket[34]; //c_bucket0 + res_avx2 = c_bucket[35]; //c_bucket1 + res_avx4 = c_bucket[36]; + res_avx6 = c_bucket[37]; + + c6_avx=c_bucket[40]; + c7_avx=c_bucket[41]; + + c8_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[42], c6_avx), c7_avx); + + res_avx1 = c_bucket[50]; //c_bucket0 + res_avx3 = c_bucket[51]; //c_bucket1 + res_avx5 = c_bucket[52]; + res_avx7 = c_bucket[53]; + + c22_avx=c_bucket[56]; + c23_avx=c_bucket[57]; + + c21_avx=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[55], res_avx5),res_avx7); + + c24_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[58], c22_avx), c23_avx); + + c20_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[54], res_avx1), res_avx3); + + temp=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[39], res_avx4),res_avx6); + res_avx5 = _mm256_add_epi16(res_avx5, temp); + + temp = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[38], res_avx0), res_avx2); + res_avx1 = _mm256_add_epi16(res_avx1, temp); + + c22_avx=_mm256_add_epi16(c22_avx, c8_avx); + + res_avx6 = _mm256_add_epi16(res_avx6, c21_avx); + + res_avx2 = _mm256_add_epi16(res_avx2, c20_avx); + + c7_avx=_mm256_add_epi16(c7_avx, c24_avx); + + //loop4 + c6_avx=_mm256_sub_epi16(_mm256_sub_epi16(c6_avx, res_avx0), res_avx4); + c22_avx=_mm256_sub_epi16(_mm256_sub_epi16(c22_avx, res_avx1), res_avx5); + + c7_avx=_mm256_sub_epi16(_mm256_sub_epi16(c7_avx, res_avx2), res_avx6); + c23_avx=_mm256_sub_epi16(_mm256_sub_epi16(c23_avx, res_avx3), res_avx7); + //loop5 + result_final2[0]=res_avx0; + result_final2[1]=res_avx1; + + result_final2[2]=_mm256_add_epi16(res_avx2, c6_avx); + result_final2[3]=_mm256_add_epi16(res_avx3, c22_avx); + + + result_final2[4]=_mm256_add_epi16(res_avx4, c7_avx); + result_final2[5]=_mm256_add_epi16(res_avx5, c23_avx); + + result_final2[6]=res_avx6; + result_final2[7]=res_avx7; + + //------------------------AVX interpolation for 3rd poly ends-------------- + + //------------------------AVX interpolation for 4th poly external------------------- + + //loop1 + res_avx0 = c_bucket[43]; + res_avx2 = c_bucket[44]; + res_avx4 = c_bucket[45]; + res_avx6 = c_bucket[46]; + + c6_avx=c_bucket[65]; + c7_avx=c_bucket[66]; + + c8_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[67], c6_avx), c7_avx); + + res_avx1 = c_bucket[59]; + res_avx3 = c_bucket[60]; + res_avx5 = c_bucket[61]; + res_avx7 = c_bucket[62]; + + c22_avx=c_bucket[81]; + c23_avx=c_bucket[82]; + + c21_avx=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[80], res_avx5),res_avx7); + + c24_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[83], c22_avx), c23_avx); + + c20_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[63], res_avx1), res_avx3); + + temp=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[64], res_avx4),res_avx6); + res_avx5 = _mm256_add_epi16(res_avx5, temp); + + temp = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[47], res_avx0), res_avx2); + res_avx1 = _mm256_add_epi16(res_avx1, temp); + + c22_avx=_mm256_add_epi16(c22_avx, c8_avx); + + res_avx6 = _mm256_add_epi16(res_avx6, c21_avx); + + res_avx2 = _mm256_add_epi16(res_avx2, c20_avx); + + c7_avx=_mm256_add_epi16(c7_avx, c24_avx); + + + //loop4 + + c6_avx=_mm256_sub_epi16(_mm256_sub_epi16(c6_avx, res_avx0), res_avx4); + c22_avx=_mm256_sub_epi16(_mm256_sub_epi16(c22_avx, res_avx1), res_avx5); + + c7_avx=_mm256_sub_epi16(_mm256_sub_epi16(c7_avx, res_avx2), res_avx6); + c23_avx=_mm256_sub_epi16(_mm256_sub_epi16(c23_avx, res_avx3), res_avx7); + + //loop5 + result_final3[0]=res_avx0; + result_final3[1]=res_avx1; + + result_final3[2]=_mm256_add_epi16(res_avx2, c6_avx); + result_final3[3]=_mm256_add_epi16(res_avx3, c22_avx); + + + result_final3[4]=_mm256_add_epi16(res_avx4, c7_avx); + result_final3[5]=_mm256_add_epi16(res_avx5, c23_avx); + + result_final3[6]=res_avx6; + result_final3[7]=res_avx7; + + + //------------------------AVX interpolation for 4th poly ends-------------- + + //------------------------AVX interpolation for 5th poly external------------------- + + //loop1 + res_avx0 = c_bucket[68]; + res_avx2 = c_bucket[69]; + res_avx4 = c_bucket[70]; + res_avx6 = c_bucket[71]; + + c6_avx=c_bucket[74]; + c7_avx=c_bucket[75]; + + c8_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[76], c6_avx), c7_avx); + + res_avx1 = c_bucket[84]; + res_avx3 = c_bucket[85]; + res_avx5 = c_bucket[86]; + res_avx7 = c_bucket[87]; + + c22_avx=c_bucket[90]; + c23_avx=c_bucket[91]; + + c21_avx=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[89], res_avx5),res_avx7); + + c24_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[92], c22_avx), c23_avx); + + c20_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[88], res_avx1), res_avx3); + + temp=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[73], res_avx4),res_avx6); + res_avx5 = _mm256_add_epi16(res_avx5, temp); + + temp = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[72], res_avx0), res_avx2); + res_avx1 = _mm256_add_epi16(res_avx1, temp); + + c22_avx=_mm256_add_epi16(c22_avx, c8_avx); + + res_avx6 = _mm256_add_epi16(res_avx6, c21_avx); + + res_avx2 = _mm256_add_epi16(res_avx2, c20_avx); + + c7_avx=_mm256_add_epi16(c7_avx, c24_avx); + + + //loop4 + + c6_avx=_mm256_sub_epi16(_mm256_sub_epi16(c6_avx, res_avx0), res_avx4); + c22_avx=_mm256_sub_epi16(_mm256_sub_epi16(c22_avx, res_avx1), res_avx5); + + c7_avx=_mm256_sub_epi16(_mm256_sub_epi16(c7_avx, res_avx2), res_avx6); + c23_avx=_mm256_sub_epi16(_mm256_sub_epi16(c23_avx, res_avx3), res_avx7); + + //loop5 + result_final4[0]=res_avx0; + result_final4[1]=res_avx1; + + result_final4[2]=_mm256_add_epi16(res_avx2, c6_avx); + result_final4[3]=_mm256_add_epi16(res_avx3, c22_avx); + + + result_final4[4]=_mm256_add_epi16(res_avx4, c7_avx); + result_final4[5]=_mm256_add_epi16(res_avx5, c23_avx); + + result_final4[6]=res_avx6; + result_final4[7]=res_avx7; + + + //------------------------AVX interpolation for 5th poly ends-------------- + + //------------------------AVX interpolation for 6th poly external------------------- + + //loop1 + res_avx0 = c_bucket[77]; + res_avx2 = c_bucket[78]; + res_avx4 = c_bucket[79]; + res_avx6 = c_bucket[96]; + + c6_avx=c_bucket[99]; + c7_avx=c_bucket[100]; + + c8_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[101], c6_avx), c7_avx); + + res_avx1 = c_bucket[93]; + res_avx3 = c_bucket[94]; + res_avx5 = c_bucket[95]; + res_avx7 = c_bucket[112]; + + c22_avx=c_bucket[115]; + c23_avx=c_bucket[116]; + + c21_avx=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[114], res_avx5),res_avx7); + + c24_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[117], c22_avx), c23_avx); + + c20_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[113], res_avx1), res_avx3); + + temp=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[98], res_avx4),res_avx6); + res_avx5 = _mm256_add_epi16(res_avx5, temp); + + temp = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[97], res_avx0), res_avx2); + res_avx1 = _mm256_add_epi16(res_avx1, temp); + + c22_avx=_mm256_add_epi16(c22_avx, c8_avx); + + res_avx6 = _mm256_add_epi16(res_avx6, c21_avx); + + res_avx2 = _mm256_add_epi16(res_avx2, c20_avx); + + c7_avx=_mm256_add_epi16(c7_avx, c24_avx); + + + //loop4 + + c6_avx=_mm256_sub_epi16(_mm256_sub_epi16(c6_avx, res_avx0), res_avx4); + c22_avx=_mm256_sub_epi16(_mm256_sub_epi16(c22_avx, res_avx1), res_avx5); + + c7_avx=_mm256_sub_epi16(_mm256_sub_epi16(c7_avx, res_avx2), res_avx6); + c23_avx=_mm256_sub_epi16(_mm256_sub_epi16(c23_avx, res_avx3), res_avx7); + + //loop5 + result_final5[0]=res_avx0; + result_final5[1]=res_avx1; + + result_final5[2]=_mm256_add_epi16(res_avx2, c6_avx); + result_final5[3]=_mm256_add_epi16(res_avx3, c22_avx); + + + result_final5[4]=_mm256_add_epi16(res_avx4, c7_avx); + result_final5[5]=_mm256_add_epi16(res_avx5, c23_avx); + + result_final5[6]=res_avx6; + result_final5[7]=res_avx7; + + + //------------------------AVX interpolation for 6th poly ends-------------- + + //------------------------AVX interpolation for 7th poly external------------------- + + //loop1 + res_avx0 = c_bucket[102]; + res_avx2 = c_bucket[103]; + res_avx4 = c_bucket[104]; + res_avx6 = c_bucket[105]; + + c6_avx=c_bucket[108]; + c7_avx=c_bucket[109]; + + c8_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[110], c6_avx), c7_avx); + + res_avx1 = c_bucket[118]; + res_avx3 = c_bucket[119]; + res_avx5 = c_bucket[120]; + res_avx7 = c_bucket[121]; + + c22_avx=c_bucket[124]; + c23_avx=c_bucket[125]; + + c21_avx=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[123], res_avx5),res_avx7); + + c24_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[126], c22_avx), c23_avx); + + c20_avx = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[122], res_avx1), res_avx3); + + temp=_mm256_sub_epi16(_mm256_sub_epi16(c_bucket[107], res_avx4),res_avx6); + res_avx5 = _mm256_add_epi16(res_avx5, temp); + + temp = _mm256_sub_epi16(_mm256_sub_epi16(c_bucket[106], res_avx0), res_avx2); + res_avx1 = _mm256_add_epi16(res_avx1, temp); + + c22_avx=_mm256_add_epi16(c22_avx, c8_avx); + + res_avx6 = _mm256_add_epi16(res_avx6, c21_avx); + + res_avx2 = _mm256_add_epi16(res_avx2, c20_avx); + + c7_avx=_mm256_add_epi16(c7_avx, c24_avx); + + + //loop4 + + c6_avx=_mm256_sub_epi16(_mm256_sub_epi16(c6_avx, res_avx0), res_avx4); + c22_avx=_mm256_sub_epi16(_mm256_sub_epi16(c22_avx, res_avx1), res_avx5); + + c7_avx=_mm256_sub_epi16(_mm256_sub_epi16(c7_avx, res_avx2), res_avx6); + c23_avx=_mm256_sub_epi16(_mm256_sub_epi16(c23_avx, res_avx3), res_avx7); + + //loop5 + result_final6[0]=res_avx0; + result_final6[1]=res_avx1; + + result_final6[2]=_mm256_add_epi16(res_avx2, c6_avx); + result_final6[3]=_mm256_add_epi16(res_avx3, c22_avx); + + + result_final6[4]=_mm256_add_epi16(res_avx4, c7_avx); + result_final6[5]=_mm256_add_epi16(res_avx5, c23_avx); + + result_final6[6]=res_avx6; + result_final6[7]=res_avx7; + + + //------------------------AVX interpolation for 7th poly ends-------------- + + //CLOCK2=cpucycles(); + //CLOCK_INTER=CLOCK_INTER+(CLOCK2-CLOCK1); + //printf("\nTime for interpolation : %llu\n", CLOCK2-CLOCK1); + + + +} + +static void toom_cook_4way_avx_n1(__m256i* a_avx,__m256i* b_bucket, __m256i *c_bucket, int f){ + + int i; + +//---------------AVX data----------------------------- + + __m256i r0_avx, r1_avx, r2_avx, r3_avx, r4_avx, r5_avx, r6_avx; + __m256i aw_avx[7*small_len_avx]; + +//----------------AVX data---------------------------- + + +// EVALUATION + + //CLOCK1=cpucycles(); + + for (i=0; i>= 63; + return (uint8_t) r; +} + +/* b = 1 means mov, b = 0 means don't mov*/ +void PQCLEAN_SABER_AVX2_cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b) { + size_t i; + + b = -b; + for (i = 0; i < len; i++) { + r[i] ^= b & (x[i] ^ r[i]); + } +} diff --git a/crypto_kem/saber/avx2/verify.h b/crypto_kem/saber/avx2/verify.h new file mode 100644 index 00000000..32edf5d0 --- /dev/null +++ b/crypto_kem/saber/avx2/verify.h @@ -0,0 +1,22 @@ +#ifndef VERIFY_H +#define VERIFY_H +/*------------------------------------------------- +This file has been adapted from the implementation +(available at https://github.com/pq-crystals/kyber) of +"CRYSTALS – Kyber: a CCA-secure module-lattice-based KEM" + by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint, +Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle +----------------------------------------------------*/ + +#include +#include + +/* returns 0 for equal strings, 1 for non-equal strings */ +uint8_t PQCLEAN_SABER_AVX2_verify(const uint8_t *a, const uint8_t *b, size_t len); + + +/* b = 1 means mov, b = 0 means don't mov*/ +void PQCLEAN_SABER_AVX2_cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b); + + +#endif diff --git a/crypto_kem/saber/clean/LICENSE b/crypto_kem/saber/clean/LICENSE index 08c799e3..d5d21fff 100644 --- a/crypto_kem/saber/clean/LICENSE +++ b/crypto_kem/saber/clean/LICENSE @@ -1,8 +1 @@ ----------------------------------------------------------------------------------------- -SABER_v1.1 - -Public domain - -Authors: Jan-Pieter D'Anvers, Angshuman Karmakar, Sujoy Sinha Roy, -Frederik Vercauteren ----------------------------------------------------------------------------------------- +Public Domain diff --git a/crypto_kem/saber/clean/Makefile b/crypto_kem/saber/clean/Makefile index 2052d200..cbc1357c 100644 --- a/crypto_kem/saber/clean/Makefile +++ b/crypto_kem/saber/clean/Makefile @@ -1,10 +1,10 @@ # This Makefile can be used with GNU Make or BSD Make LIB=libsaber_clean.a -HEADERS=api.h cbd.h poly.h poly_mul.h SABER_indcpa.h SABER_params.h verify.h pack_unpack.h +HEADERS=api.h cbd.h pack_unpack.h poly.h poly_mul.h SABER_indcpa.h SABER_params.h verify.h OBJECTS=cbd.o kem.o pack_unpack.o poly.o poly_mul.o SABER_indcpa.o verify.o -CFLAGS=-O3 -Wall -Wextra -Wpedantic -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wredundant-decls -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_kem/saber/clean/SABER_indcpa.c b/crypto_kem/saber/clean/SABER_indcpa.c index d381194c..fe54f4ca 100644 --- a/crypto_kem/saber/clean/SABER_indcpa.c +++ b/crypto_kem/saber/clean/SABER_indcpa.c @@ -3,296 +3,90 @@ #include "fips202.h" #include "pack_unpack.h" #include "poly.h" -#include "poly_mul.h" #include "randombytes.h" #include #include +#define h1 (1 << (SABER_EQ - SABER_EP - 1)) +#define h2 ((1 << (SABER_EP - 2)) - (1 << (SABER_EP - SABER_ET - 1)) + (1 << (SABER_EQ - SABER_EP - 1))) +void PQCLEAN_SABER_CLEAN_indcpa_kem_keypair(uint8_t pk[SABER_INDCPA_PUBLICKEYBYTES], uint8_t sk[SABER_INDCPA_SECRETKEYBYTES]) { + uint16_t A[SABER_L][SABER_L][SABER_N]; + uint16_t s[SABER_L][SABER_N]; + uint16_t b[SABER_L][SABER_N] = {0}; -/*----------------------------------------------------------------------------------- - This routine generates a=[Matrix K x K] of 256-coefficient polynomials --------------------------------------------------------------------------------------*/ + uint8_t seed_A[SABER_SEEDBYTES]; + uint8_t seed_s[SABER_NOISE_SEEDBYTES]; + int i, j; -#define h1 4 //2^(EQ-EP-1) + randombytes(seed_A, SABER_SEEDBYTES); + shake128(seed_A, SABER_SEEDBYTES, seed_A, SABER_SEEDBYTES); // for not revealing system RNG state + randombytes(seed_s, SABER_NOISE_SEEDBYTES); -#define h2 ( (1<<(SABER_EP-2)) - (1<<(SABER_EP-SABER_ET-1)) + (1<<(SABER_EQ-SABER_EP-1)) ) + PQCLEAN_SABER_CLEAN_GenMatrix(A, seed_A); + PQCLEAN_SABER_CLEAN_GenSecret(s, seed_s); + PQCLEAN_SABER_CLEAN_MatrixVectorMul(b, (const uint16_t (*)[SABER_L][SABER_N])A, (const uint16_t (*)[SABER_N])s, 1); -static void InnerProd(uint16_t pkcl[SABER_K][SABER_N], uint16_t skpv[SABER_K][SABER_N], uint16_t mod, uint16_t res[SABER_N]); -static void MatrixVectorMul(polyvec *a, uint16_t skpv[SABER_K][SABER_N], uint16_t res[SABER_K][SABER_N], uint16_t mod, int16_t transpose); - -static void POL2MSG(const uint16_t *message_dec_unpacked, unsigned char *message_dec); - -static void GenMatrix(polyvec *a, const unsigned char *seed) { - unsigned char buf[SABER_K * SABER_K * (13 * SABER_N / 8)]; - - uint16_t temp_ar[SABER_N]; - - int i, j, k; - uint16_t mod = (SABER_Q - 1); - - shake128(buf, sizeof(buf), seed, SABER_SEEDBYTES); - - for (i = 0; i < SABER_K; i++) { - for (j = 0; j < SABER_K; j++) { - PQCLEAN_SABER_CLEAN_BS2POL(buf + (i * SABER_K + j) * (13 * SABER_N / 8), temp_ar); - for (k = 0; k < SABER_N; k++) { - a[i].vec[j].coeffs[k] = (temp_ar[k])& mod ; - } + for (i = 0; i < SABER_L; i++) { + for (j = 0; j < SABER_N; j++) { + b[i][j] = (b[i][j] + h1) >> (SABER_EQ - SABER_EP); } } + + PQCLEAN_SABER_CLEAN_POLVECq2BS(sk, (const uint16_t (*)[SABER_N])s); + PQCLEAN_SABER_CLEAN_POLVECp2BS(pk, (const uint16_t (*)[SABER_N])b); + memcpy(pk + SABER_POLYVECCOMPRESSEDBYTES, seed_A, sizeof(seed_A)); } +void PQCLEAN_SABER_CLEAN_indcpa_kem_enc(uint8_t ciphertext[SABER_BYTES_CCA_DEC], const uint8_t m[SABER_KEYBYTES], const uint8_t seed_sp[SABER_NOISE_SEEDBYTES], const uint8_t pk[SABER_INDCPA_PUBLICKEYBYTES]) { + uint16_t A[SABER_L][SABER_L][SABER_N]; + uint16_t sp[SABER_L][SABER_N]; + uint16_t bp[SABER_L][SABER_N] = {0}; + uint16_t vp[SABER_N] = {0}; + uint16_t mp[SABER_N]; + uint16_t b[SABER_L][SABER_N]; + int i, j; + const uint8_t *seed_A = pk + SABER_POLYVECCOMPRESSEDBYTES; -void PQCLEAN_SABER_CLEAN_indcpa_kem_keypair(unsigned char *pk, unsigned char *sk) { - polyvec a[SABER_K]; + PQCLEAN_SABER_CLEAN_GenMatrix(A, seed_A); + PQCLEAN_SABER_CLEAN_GenSecret(sp, seed_sp); + PQCLEAN_SABER_CLEAN_MatrixVectorMul(bp, (const uint16_t (*)[SABER_L][SABER_N])A, (const uint16_t (*)[SABER_N])sp, 0); - uint16_t skpv[SABER_K][SABER_N]; - - unsigned char seed[SABER_SEEDBYTES]; - unsigned char noiseseed[SABER_COINBYTES]; - int32_t i, j; - uint16_t mod_q = SABER_Q - 1; - - - uint16_t res[SABER_K][SABER_N]; - - randombytes(seed, SABER_SEEDBYTES); - - // for not revealing system RNG state - shake128(seed, SABER_SEEDBYTES, seed, SABER_SEEDBYTES); - randombytes(noiseseed, SABER_COINBYTES); - - GenMatrix(a, seed); //sample matrix A - - // generate secret from constant-time binomial distribution - PQCLEAN_SABER_CLEAN_GenSecret(skpv, noiseseed); - - // do the matrix vector multiplication and rounding - for (i = 0; i < SABER_K; i++) { + for (i = 0; i < SABER_L; i++) { for (j = 0; j < SABER_N; j++) { - res[i][j] = 0; - } - } - MatrixVectorMul(a, skpv, res, SABER_Q - 1, 1); - - // now rounding - for (i = 0; i < SABER_K; i++) { - for (j = 0; j < SABER_N; j++) { - // shift right 3 bits - res[i][j] = (res[i][j] + h1) & (mod_q); - res[i][j] = (res[i][j] >> (SABER_EQ - SABER_EP)); + bp[i][j] = (bp[i][j] + h1) >> (SABER_EQ - SABER_EP); } } - // unload and pack sk=3 x (256 coefficients of 14 bits) - PQCLEAN_SABER_CLEAN_POLVEC2BS(sk, skpv, SABER_Q); + PQCLEAN_SABER_CLEAN_POLVECp2BS(ciphertext, (const uint16_t (*)[SABER_N])bp); + PQCLEAN_SABER_CLEAN_BS2POLVECp(b, pk); + PQCLEAN_SABER_CLEAN_InnerProd(vp, (const uint16_t (*)[SABER_N])b, (const uint16_t (*)[SABER_N])sp); - // unload and pack pk=256 bits seed and 3 x (256 coefficients of 11 bits) - // load the public-key coefficients - PQCLEAN_SABER_CLEAN_POLVEC2BS(pk, res, SABER_P); + PQCLEAN_SABER_CLEAN_BS2POLmsg(mp, m); - - // now load the seedbytes in PK. Easy since seed bytes are kept in byte format. - for (i = 0; i < SABER_SEEDBYTES; i++) { - pk[SABER_POLYVECCOMPRESSEDBYTES + i] = seed[i]; + for (j = 0; j < SABER_N; j++) { + vp[j] = (vp[j] - (mp[j] << (SABER_EP - 1)) + h1) >> (SABER_EP - SABER_ET); } + PQCLEAN_SABER_CLEAN_POLT2BS(ciphertext + SABER_POLYVECCOMPRESSEDBYTES, vp); } +void PQCLEAN_SABER_CLEAN_indcpa_kem_dec(uint8_t m[SABER_KEYBYTES], const uint8_t sk[SABER_INDCPA_SECRETKEYBYTES], const uint8_t ciphertext[SABER_BYTES_CCA_DEC]) { -void PQCLEAN_SABER_CLEAN_indcpa_kem_enc(const unsigned char *message_received, unsigned char *noiseseed, const unsigned char *pk, unsigned char *ciphertext) { - uint32_t i, j, k; - polyvec a[SABER_K]; - unsigned char seed[SABER_SEEDBYTES]; - // public key of received by the client - uint16_t pkcl[SABER_K][SABER_N]; - uint16_t skpv1[SABER_K][SABER_N]; - uint16_t message[SABER_KEYBYTES * 8]; - uint16_t res[SABER_K][SABER_N]; - uint16_t mod_p = SABER_P - 1; - uint16_t mod_q = SABER_Q - 1; - uint16_t vprime[SABER_N]; - unsigned char msk_c[SABER_SCALEBYTES_KEM]; + uint16_t s[SABER_L][SABER_N]; + uint16_t b[SABER_L][SABER_N]; + uint16_t v[SABER_N] = {0}; + uint16_t cm[SABER_N]; + int i; - // extract the seedbytes from Public Key. - for (i = 0; i < SABER_SEEDBYTES; i++) { - seed[i] = pk[ SABER_POLYVECCOMPRESSEDBYTES + i]; - } + PQCLEAN_SABER_CLEAN_BS2POLVECq(s, sk); + PQCLEAN_SABER_CLEAN_BS2POLVECp(b, ciphertext); + PQCLEAN_SABER_CLEAN_InnerProd(v, (const uint16_t (*)[SABER_N])b, (const uint16_t (*)[SABER_N])s); + PQCLEAN_SABER_CLEAN_BS2POLT(cm, ciphertext + SABER_POLYVECCOMPRESSEDBYTES); - GenMatrix(a, seed); - - // generate secret from constant-time binomial distribution - PQCLEAN_SABER_CLEAN_GenSecret(skpv1, noiseseed); - - // matrix-vector multiplication and rounding - for (i = 0; i < SABER_K; i++) { - for (j = 0; j < SABER_N; j++) { - res[i][j] = 0; - } - } - MatrixVectorMul(a, skpv1, res, SABER_Q - 1, 0); - - // now rounding - //shift right 3 bits - for (i = 0; i < SABER_K; i++) { - for (j = 0; j < SABER_N; j++) { - res[i][j] = ( res[i][j] + h1 ) & mod_q; - res[i][j] = (res[i][j] >> (SABER_EQ - SABER_EP) ); - } - } - - PQCLEAN_SABER_CLEAN_POLVEC2BS(ciphertext, res, SABER_P); - - // ************client matrix-vector multiplication ends************ - - // now calculate the v' - // unpack the public_key - // pkcl is the b in the protocol - PQCLEAN_SABER_CLEAN_BS2POLVEC(pk, pkcl, SABER_P); for (i = 0; i < SABER_N; i++) { - vprime[i] = 0; - } - for (i = 0; i < SABER_K; i++) { - for (j = 0; j < SABER_N; j++) { - skpv1[i][j] = skpv1[i][j] & (mod_p); - } + v[i] = (v[i] + h2 - (cm[i] << (SABER_EP - SABER_ET))) >> (SABER_EP - 1); } - // vector-vector scalar multiplication with mod p - InnerProd(pkcl, skpv1, mod_p, vprime); - - // addition of h1 to vprime - for (i = 0; i < SABER_N; i++) { - vprime[i] = vprime[i] + h1; - } - - // unpack message_received; - for (j = 0; j < SABER_KEYBYTES; j++) { - for (i = 0; i < 8; i++) { - message[8 * j + i] = ((message_received[j] >> i) & 0x01); - } - } - - // message encoding - for (i = 0; i < SABER_N; i++) { - message[i] = (message[i] << (SABER_EP - 1)); - } - - for (k = 0; k < SABER_N; k++) { - vprime[k] = ( (vprime[k] - message[k]) & (mod_p) ) >> (SABER_EP - SABER_ET); - } - - - PQCLEAN_SABER_CLEAN_pack_4bit(msk_c, vprime); - - for (j = 0; j < SABER_SCALEBYTES_KEM; j++) { - ciphertext[SABER_POLYVECCOMPRESSEDBYTES + j] = msk_c[j]; - } -} - - -void PQCLEAN_SABER_CLEAN_indcpa_kem_dec(const unsigned char *sk, const unsigned char *ciphertext, unsigned char message_dec[]) { - uint32_t i, j; - // secret key of the server - uint16_t sksv[SABER_K][SABER_N]; - uint16_t pksv[SABER_K][SABER_N]; - uint8_t scale_ar[SABER_SCALEBYTES_KEM]; - uint16_t mod_p = SABER_P - 1; - uint16_t v[SABER_N]; - uint16_t op[SABER_N]; - - // sksv is the secret-key - PQCLEAN_SABER_CLEAN_BS2POLVEC(sk, sksv, SABER_Q); - // pksv is the ciphertext - PQCLEAN_SABER_CLEAN_BS2POLVEC(ciphertext, pksv, SABER_P); - - // vector-vector scalar multiplication with mod p - for (i = 0; i < SABER_N; i++) { - v[i] = 0; - } - for (i = 0; i < SABER_K; i++) { - for (j = 0; j < SABER_N; j++) { - sksv[i][j] = sksv[i][j] & (mod_p); - } - } - InnerProd(pksv, sksv, mod_p, v); - - //Extraction - for (i = 0; i < SABER_SCALEBYTES_KEM; i++) { - scale_ar[i] = ciphertext[SABER_POLYVECCOMPRESSEDBYTES + i]; - } - - PQCLEAN_SABER_CLEAN_un_pack4bit(scale_ar, op); - - //addition of h1 - for (i = 0; i < SABER_N; i++) { - v[i] = ( ( v[i] + h2 - (op[i] << (SABER_EP - SABER_ET)) ) & (mod_p) ) >> (SABER_EP - 1); - } - - // pack decrypted message - POL2MSG(v, message_dec); -} -static void MatrixVectorMul(polyvec *a, uint16_t skpv[SABER_K][SABER_N], uint16_t res[SABER_K][SABER_N], uint16_t mod, int16_t transpose) { - uint16_t acc[SABER_N]; - int32_t i, j, k; - - if (transpose == 1) { - for (i = 0; i < SABER_K; i++) { - for (j = 0; j < SABER_K; j++) { - PQCLEAN_SABER_CLEAN_pol_mul((uint16_t *)&a[j].vec[i], skpv[j], acc, SABER_Q, SABER_N); - - for (k = 0; k < SABER_N; k++) { - res[i][k] = res[i][k] + acc[k]; - //reduction mod p - res[i][k] = (res[i][k] & mod); - //clear the accumulator - acc[k] = 0; - } - } - } - } else { - for (i = 0; i < SABER_K; i++) { - for (j = 0; j < SABER_K; j++) { - PQCLEAN_SABER_CLEAN_pol_mul((uint16_t *)&a[i].vec[j], skpv[j], acc, SABER_Q, SABER_N); - for (k = 0; k < SABER_N; k++) { - res[i][k] = res[i][k] + acc[k]; - // reduction - res[i][k] = res[i][k] & mod; - // clear the accumulator - acc[k] = 0; - } - } - } - } -} - -static void POL2MSG(const uint16_t *message_dec_unpacked, unsigned char *message_dec) { - int32_t i, j; - - for (j = 0; j < SABER_KEYBYTES; j++) { - message_dec[j] = 0; - for (i = 0; i < 8; i++) { - message_dec[j] = message_dec[j] | (uint8_t) (message_dec_unpacked[j * 8 + i] << i); - } - } -} - - -static void InnerProd(uint16_t pkcl[SABER_K][SABER_N], uint16_t skpv[SABER_K][SABER_N], uint16_t mod, uint16_t res[SABER_N]) { - uint32_t j, k; - uint16_t acc[SABER_N]; - - // vector-vector scalar multiplication with mod p - for (j = 0; j < SABER_K; j++) { - PQCLEAN_SABER_CLEAN_pol_mul(pkcl[j], skpv[j], acc, SABER_P, SABER_N); - - for (k = 0; k < SABER_N; k++) { - res[k] = res[k] + acc[k]; - // reduction - res[k] = res[k] & mod; - // clear the accumulator - acc[k] = 0; - } - } + PQCLEAN_SABER_CLEAN_POLmsg2BS(m, v); } diff --git a/crypto_kem/saber/clean/SABER_indcpa.h b/crypto_kem/saber/clean/SABER_indcpa.h index f8503f66..3be3ce1c 100644 --- a/crypto_kem/saber/clean/SABER_indcpa.h +++ b/crypto_kem/saber/clean/SABER_indcpa.h @@ -1,9 +1,13 @@ #ifndef INDCPA_H #define INDCPA_H +#include "SABER_params.h" +#include + +void PQCLEAN_SABER_CLEAN_indcpa_kem_keypair(uint8_t pk[SABER_INDCPA_PUBLICKEYBYTES], uint8_t sk[SABER_INDCPA_SECRETKEYBYTES]); + +void PQCLEAN_SABER_CLEAN_indcpa_kem_enc(uint8_t ciphertext[SABER_BYTES_CCA_DEC], const uint8_t m[SABER_KEYBYTES], const uint8_t seed_sp[SABER_NOISE_SEEDBYTES], const uint8_t pk[SABER_INDCPA_PUBLICKEYBYTES]); + +void PQCLEAN_SABER_CLEAN_indcpa_kem_dec(uint8_t m[SABER_KEYBYTES], const uint8_t sk[SABER_INDCPA_SECRETKEYBYTES], const uint8_t ciphertext[SABER_BYTES_CCA_DEC]); -void PQCLEAN_SABER_CLEAN_indcpa_kem_keypair(unsigned char *pk, unsigned char *sk); -void PQCLEAN_SABER_CLEAN_indcpa_kem_enc(const unsigned char *message, unsigned char *noiseseed, const unsigned char *pk, unsigned char *ciphertext); -void PQCLEAN_SABER_CLEAN_indcpa_kem_dec(const unsigned char *sk, const unsigned char *ciphertext, unsigned char *message_dec); #endif - diff --git a/crypto_kem/saber/clean/SABER_params.h b/crypto_kem/saber/clean/SABER_params.h index faa9f6db..200ed0e6 100644 --- a/crypto_kem/saber/clean/SABER_params.h +++ b/crypto_kem/saber/clean/SABER_params.h @@ -1,50 +1,39 @@ #ifndef PARAMS_H #define PARAMS_H -#include "api.h" -#define SABER_K 3 +/* Change this for different security strengths */ + +/* Don't change anything below this line */ +#define SABER_L 3 #define SABER_MU 8 #define SABER_ET 4 - #define SABER_EQ 13 #define SABER_EP 10 - #define SABER_N 256 -#define SABER_Q 8192 -#define SABER_P 1024 -#define SABER_SEEDBYTES 32 -#define SABER_NOISESEEDBYTES 32 -#define SABER_COINBYTES 32 -#define SABER_KEYBYTES 32 +#define SABER_SEEDBYTES 32 +#define SABER_NOISE_SEEDBYTES 32 +#define SABER_KEYBYTES 32 +#define SABER_HASHBYTES 32 -#define SABER_HASHBYTES 32 +#define SABER_POLYCOINBYTES (SABER_MU * SABER_N / 8) -#define SABER_POLYBYTES 416 //13*256/8 +#define SABER_POLYBYTES (SABER_EQ * SABER_N / 8) +#define SABER_POLYVECBYTES (SABER_L * SABER_POLYBYTES) -#define SABER_POLYVECBYTES (SABER_K * SABER_POLYBYTES) +#define SABER_POLYCOMPRESSEDBYTES (SABER_EP * SABER_N / 8) +#define SABER_POLYVECCOMPRESSEDBYTES (SABER_L * SABER_POLYCOMPRESSEDBYTES) -#define SABER_POLYVECCOMPRESSEDBYTES (SABER_K * 320) //10*256/8 NOTE : changed till here due to parameter adaptation - -#define SABER_CIPHERTEXTBYTES (SABER_POLYVECCOMPRESSEDBYTES) - -#define SABER_SCALEBYTES (SABER_DELTA*SABER_N/8) - -#define SABER_SCALEBYTES_KEM ((SABER_ET)*SABER_N/8) +#define SABER_SCALEBYTES_KEM (SABER_ET * SABER_N / 8) #define SABER_INDCPA_PUBLICKEYBYTES (SABER_POLYVECCOMPRESSEDBYTES + SABER_SEEDBYTES) #define SABER_INDCPA_SECRETKEYBYTES (SABER_POLYVECBYTES) #define SABER_PUBLICKEYBYTES (SABER_INDCPA_PUBLICKEYBYTES) +#define SABER_SECRETKEYBYTES (SABER_INDCPA_SECRETKEYBYTES + SABER_INDCPA_PUBLICKEYBYTES + SABER_HASHBYTES + SABER_KEYBYTES) -#define SABER_SECRETKEYBYTES (SABER_INDCPA_SECRETKEYBYTES + SABER_INDCPA_PUBLICKEYBYTES + SABER_HASHBYTES + SABER_KEYBYTES) - -#define SABER_BYTES_CCA_DEC (SABER_POLYVECCOMPRESSEDBYTES + SABER_SCALEBYTES_KEM) /* Second part is for Targhi-Unruh */ - - - +#define SABER_BYTES_CCA_DEC (SABER_POLYVECCOMPRESSEDBYTES + SABER_SCALEBYTES_KEM) #endif - diff --git a/crypto_kem/saber/clean/api.h b/crypto_kem/saber/clean/api.h index 66c3b8bf..699a19f4 100644 --- a/crypto_kem/saber/clean/api.h +++ b/crypto_kem/saber/clean/api.h @@ -1,14 +1,18 @@ #ifndef PQCLEAN_SABER_CLEAN_API_H #define PQCLEAN_SABER_CLEAN_API_H + #define PQCLEAN_SABER_CLEAN_CRYPTO_ALGNAME "Saber" -#define PQCLEAN_SABER_CLEAN_CRYPTO_SECRETKEYBYTES 2304 -#define PQCLEAN_SABER_CLEAN_CRYPTO_PUBLICKEYBYTES (3*320+32) #define PQCLEAN_SABER_CLEAN_CRYPTO_BYTES 32 #define PQCLEAN_SABER_CLEAN_CRYPTO_CIPHERTEXTBYTES 1088 +#define PQCLEAN_SABER_CLEAN_CRYPTO_PUBLICKEYBYTES 992 +#define PQCLEAN_SABER_CLEAN_CRYPTO_SECRETKEYBYTES 2304 int PQCLEAN_SABER_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk); -int PQCLEAN_SABER_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk); -int PQCLEAN_SABER_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk); + +int PQCLEAN_SABER_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *k, const unsigned char *pk); + +int PQCLEAN_SABER_CLEAN_crypto_kem_dec(unsigned char *k, const unsigned char *ct, const unsigned char *sk); + #endif /* api_h */ diff --git a/crypto_kem/saber/clean/cbd.c b/crypto_kem/saber/clean/cbd.c index a2d9fcdd..e0ccef9d 100644 --- a/crypto_kem/saber/clean/cbd.c +++ b/crypto_kem/saber/clean/cbd.c @@ -1,3 +1,7 @@ +#include "SABER_params.h" +#include "api.h" +#include "cbd.h" +#include /*--------------------------------------------------------------------- This file has been adapted from the implementation (available at, Public Domain https://github.com/pq-crystals/kyber) @@ -6,12 +10,8 @@ by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint, Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle ----------------------------------------------------------------------*/ -#include "SABER_params.h" -#include "api.h" -#include "cbd.h" -#include -static uint64_t load_littleendian(const unsigned char *x, int bytes) { +static uint64_t load_littleendian(const uint8_t *x, int bytes) { int i; uint64_t r = x[0]; for (i = 1; i < bytes; i++) { @@ -20,32 +20,29 @@ static uint64_t load_littleendian(const unsigned char *x, int bytes) { return r; } - -void PQCLEAN_SABER_CLEAN_cbd(uint16_t *r, const unsigned char *buf) { - uint16_t Qmod_minus1 = SABER_Q - 1; - +void PQCLEAN_SABER_CLEAN_cbd(uint16_t s[SABER_N], const uint8_t buf[SABER_POLYCOINBYTES]) { uint32_t t, d, a[4], b[4]; int i, j; for (i = 0; i < SABER_N / 4; i++) { - t = (uint32_t) load_littleendian(buf + 4 * i, 4); + t = load_littleendian(buf + 4 * i, 4); d = 0; for (j = 0; j < 4; j++) { d += (t >> j) & 0x11111111; } - a[0] = d & 0xf; - b[0] = (d >> 4) & 0xf; - a[1] = (d >> 8) & 0xf; + a[0] = d & 0xf; + b[0] = (d >> 4) & 0xf; + a[1] = (d >> 8) & 0xf; b[1] = (d >> 12) & 0xf; a[2] = (d >> 16) & 0xf; b[2] = (d >> 20) & 0xf; a[3] = (d >> 24) & 0xf; b[3] = (d >> 28); - r[4 * i + 0] = (uint16_t)(a[0] - b[0]) & Qmod_minus1; - r[4 * i + 1] = (uint16_t)(a[1] - b[1]) & Qmod_minus1; - r[4 * i + 2] = (uint16_t)(a[2] - b[2]) & Qmod_minus1; - r[4 * i + 3] = (uint16_t)(a[3] - b[3]) & Qmod_minus1; + s[4 * i + 0] = (uint16_t)(a[0] - b[0]); + s[4 * i + 1] = (uint16_t)(a[1] - b[1]); + s[4 * i + 2] = (uint16_t)(a[2] - b[2]); + s[4 * i + 3] = (uint16_t)(a[3] - b[3]); } } diff --git a/crypto_kem/saber/clean/cbd.h b/crypto_kem/saber/clean/cbd.h index b307921f..88b0b0b5 100644 --- a/crypto_kem/saber/clean/cbd.h +++ b/crypto_kem/saber/clean/cbd.h @@ -1,6 +1,5 @@ #ifndef CBD_H #define CBD_H - /*--------------------------------------------------------------------- This file has been adapted from the implementation (available at, Public Domain https://github.com/pq-crystals/kyber) @@ -8,10 +7,10 @@ of "CRYSTALS – Kyber: a CCA-secure module-lattice-based KEM" by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint, Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle ----------------------------------------------------------------------*/ - -#include "poly.h" +#include "SABER_params.h" #include -void PQCLEAN_SABER_CLEAN_cbd(uint16_t *r, const unsigned char *buf); +void PQCLEAN_SABER_CLEAN_cbd(uint16_t s[SABER_N], const uint8_t buf[SABER_POLYCOINBYTES]); + #endif diff --git a/crypto_kem/saber/clean/kem.c b/crypto_kem/saber/clean/kem.c index 9e5b01f4..ed8e3ac7 100644 --- a/crypto_kem/saber/clean/kem.c +++ b/crypto_kem/saber/clean/kem.c @@ -1,5 +1,6 @@ #include "SABER_indcpa.h" #include "SABER_params.h" +#include "api.h" #include "fips202.h" #include "randombytes.h" #include "verify.h" @@ -7,90 +8,71 @@ #include #include -int PQCLEAN_SABER_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk) { + +int PQCLEAN_SABER_CLEAN_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) { int i; - // sk[0:SABER_INDCPA_SECRETKEYBYTES-1] <-- sk - PQCLEAN_SABER_CLEAN_indcpa_kem_keypair(pk, sk); - - // sk[SABER_INDCPA_SECRETKEYBYTES:SABER_INDCPA_SECRETKEYBYTES+SABER_INDCPA_SECRETKEYBYTES-1] <-- pk + PQCLEAN_SABER_CLEAN_indcpa_kem_keypair(pk, sk); // sk[0:SABER_INDCPA_SECRETKEYBYTES-1] <-- sk for (i = 0; i < SABER_INDCPA_PUBLICKEYBYTES; i++) { - sk[i + SABER_INDCPA_SECRETKEYBYTES] = pk[i]; + sk[i + SABER_INDCPA_SECRETKEYBYTES] = pk[i]; // sk[SABER_INDCPA_SECRETKEYBYTES:SABER_INDCPA_SECRETKEYBYTES+SABER_INDCPA_SECRETKEYBYTES-1] <-- pk } - // Then hash(pk) is appended. - sha3_256(sk + SABER_SECRETKEYBYTES - 64, pk, SABER_INDCPA_PUBLICKEYBYTES); + sha3_256(sk + SABER_SECRETKEYBYTES - 64, pk, SABER_INDCPA_PUBLICKEYBYTES); // Then hash(pk) is appended. - // Remaining part of sk contains a pseudo-random number. - // This is output when check in crypto_kem_dec() fails. - randombytes(sk + SABER_SECRETKEYBYTES - SABER_KEYBYTES, SABER_KEYBYTES ); + randombytes(sk + SABER_SECRETKEYBYTES - SABER_KEYBYTES, SABER_KEYBYTES); // Remaining part of sk contains a pseudo-random number. + // This is output when check in PQCLEAN_SABER_CLEAN_crypto_kem_dec() fails. return (0); } -int PQCLEAN_SABER_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) { - // Will contain key, coins - unsigned char kr[64]; - unsigned char buf[64]; +int PQCLEAN_SABER_CLEAN_crypto_kem_enc(uint8_t *c, uint8_t *k, const uint8_t *pk) { + + uint8_t kr[64]; // Will contain key, coins + uint8_t buf[64]; randombytes(buf, 32); - // BUF[0:31] <-- random message (will be used as the key for client) Note: hash doesnot release system RNG output - sha3_256(buf, buf, 32); + sha3_256(buf, buf, 32); // BUF[0:31] <-- random message (will be used as the key for client) Note: hash doesnot release system RNG output - // BUF[32:63] <-- Hash(public key); Multitarget countermeasure for coins + contributory KEM - sha3_256(buf + 32, pk, SABER_INDCPA_PUBLICKEYBYTES); - - // kr[0:63] <-- Hash(buf[0:63]); - sha3_512(kr, buf, 64); + sha3_256(buf + 32, pk, SABER_INDCPA_PUBLICKEYBYTES); // BUF[32:63] <-- Hash(public key); Multitarget countermeasure for coins + contributory KEM + sha3_512(kr, buf, 64); // kr[0:63] <-- Hash(buf[0:63]); // K^ <-- kr[0:31] // noiseseed (r) <-- kr[32:63]; - // buf[0:31] contains message; kr[32:63] contains randomness r; - PQCLEAN_SABER_CLEAN_indcpa_kem_enc(buf, kr + 32, pk, ct); + PQCLEAN_SABER_CLEAN_indcpa_kem_enc(c, buf, kr + 32, pk); // buf[0:31] contains message; kr[32:63] contains randomness r; - sha3_256(kr + 32, ct, SABER_BYTES_CCA_DEC); + sha3_256(kr + 32, c, SABER_BYTES_CCA_DEC); - // hash concatenation of pre-k and h(c) to k - sha3_256(ss, kr, 64); + sha3_256(k, kr, 64); // hash concatenation of pre-k and h(c) to k return (0); } - -int PQCLEAN_SABER_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) { +int PQCLEAN_SABER_CLEAN_crypto_kem_dec(uint8_t *k, const uint8_t *c, const uint8_t *sk) { int i; - unsigned char fail; - unsigned char cmp[SABER_BYTES_CCA_DEC]; - unsigned char buf[64]; - - // Will contain key, coins - unsigned char kr[64]; - const unsigned char *pk = sk + SABER_INDCPA_SECRETKEYBYTES; - - // buf[0:31] <-- message - PQCLEAN_SABER_CLEAN_indcpa_kem_dec(sk, ct, buf); + uint8_t fail; + uint8_t cmp[SABER_BYTES_CCA_DEC]; + uint8_t buf[64]; + uint8_t kr[64]; // Will contain key, coins + const uint8_t *pk = sk + SABER_INDCPA_SECRETKEYBYTES; + PQCLEAN_SABER_CLEAN_indcpa_kem_dec(buf, sk, c); // buf[0:31] <-- message // Multitarget countermeasure for coins + contributory KEM - // Save hash by storing h(pk) in sk - for (i = 0; i < 32; i++) { + for (i = 0; i < 32; i++) { // Save hash by storing h(pk) in sk buf[32 + i] = sk[SABER_SECRETKEYBYTES - 64 + i]; } sha3_512(kr, buf, 64); - PQCLEAN_SABER_CLEAN_indcpa_kem_enc(buf, kr + 32, pk, cmp); + PQCLEAN_SABER_CLEAN_indcpa_kem_enc(cmp, buf, kr + 32, pk); + fail = PQCLEAN_SABER_CLEAN_verify(c, cmp, SABER_BYTES_CCA_DEC); - fail = PQCLEAN_SABER_CLEAN_verify(ct, cmp, SABER_BYTES_CCA_DEC); - - // overwrite coins in kr with h(c) - sha3_256(kr + 32, ct, SABER_BYTES_CCA_DEC); + sha3_256(kr + 32, c, SABER_BYTES_CCA_DEC); // overwrite coins in kr with h(c) PQCLEAN_SABER_CLEAN_cmov(kr, sk + SABER_SECRETKEYBYTES - SABER_KEYBYTES, SABER_KEYBYTES, fail); - // hash concatenation of pre-k and h(c) to k - sha3_256(ss, kr, 64); + sha3_256(k, kr, 64); // hash concatenation of pre-k and h(c) to k return (0); } diff --git a/crypto_kem/saber/clean/pack_unpack.c b/crypto_kem/saber/clean/pack_unpack.c index 06a74778..e196bd34 100644 --- a/crypto_kem/saber/clean/pack_unpack.c +++ b/crypto_kem/saber/clean/pack_unpack.c @@ -1,254 +1,132 @@ +#include "api.h" #include "pack_unpack.h" +#include -void PQCLEAN_SABER_CLEAN_pack_3bit(uint8_t *bytes, const uint16_t *data) { - uint32_t j; - uint32_t offset_data, offset_byte; - - for (j = 0; j < SABER_N / 8; j++) { - offset_byte = 3 * j; - offset_data = 8 * j; - bytes[offset_byte + 0] = (data[offset_data + 0] & 0x7) | - ((data[offset_data + 1] & 0x7) << 3) | - ((data[offset_data + 2] & 0x3) << 6); - bytes[offset_byte + 1] = ((data[offset_data + 2] >> 2 ) & 0x01) | - ((data[offset_data + 3] & 0x7) << 1) | - ((data[offset_data + 4] & 0x7) << 4) | - (((data[offset_data + 5]) & 0x01) << 7); - bytes[offset_byte + 2] = ((data[offset_data + 5] >> 1 ) & 0x03) | - ((data[offset_data + 6] & 0x7) << 2) | - ((data[offset_data + 7] & 0x7) << 5); - } -} - -void PQCLEAN_SABER_CLEAN_un_pack3bit(const uint8_t *bytes, uint16_t *data) { - uint32_t j; - uint32_t offset_data, offset_byte; - - for (j = 0; j < SABER_N / 8; j++) { - offset_byte = 3 * j; - offset_data = 8 * j; - data[offset_data + 0] = (bytes[offset_byte + 0]) & 0x07; - data[offset_data + 1] = ((bytes[offset_byte + 0]) >> 3 ) & 0x07; - data[offset_data + 2] = (((bytes[offset_byte + 0]) >> 6 ) & 0x03) | - (((bytes[offset_byte + 1]) & 0x01) << 2); - data[offset_data + 3] = ((bytes[offset_byte + 1]) >> 1 ) & 0x07; - data[offset_data + 4] = ((bytes[offset_byte + 1]) >> 4 ) & 0x07; - data[offset_data + 5] = (((bytes[offset_byte + 1]) >> 7 ) & 0x01) | - (((bytes[offset_byte + 2]) & 0x03) << 1); - data[offset_data + 6] = ((bytes[offset_byte + 2] >> 2) & 0x07); - data[offset_data + 7] = ((bytes[offset_byte + 2] >> 5) & 0x07); - } -} - -void PQCLEAN_SABER_CLEAN_pack_4bit(uint8_t *bytes, const uint16_t *data) { - uint32_t j; - uint32_t offset_data; - +void PQCLEAN_SABER_CLEAN_POLT2BS(uint8_t bytes[SABER_SCALEBYTES_KEM], const uint16_t data[SABER_N]) { + size_t j, offset_byte, offset_data; for (j = 0; j < SABER_N / 2; j++) { + offset_byte = j; offset_data = 2 * j; - bytes[j] = (data[offset_data] & 0x0f) | - ((data[offset_data + 1] & 0x0f) << 4); + bytes[offset_byte] = (data[offset_data] & 0x0f) | ((data[offset_data + 1] & 0x0f) << 4); } } -void PQCLEAN_SABER_CLEAN_un_pack4bit(const unsigned char *bytes, uint16_t *ar) { - uint32_t j; - uint32_t offset_data; - +void PQCLEAN_SABER_CLEAN_BS2POLT(uint16_t data[SABER_N], const uint8_t bytes[SABER_SCALEBYTES_KEM]) { + size_t j, offset_byte, offset_data; for (j = 0; j < SABER_N / 2; j++) { + offset_byte = j; offset_data = 2 * j; - ar[offset_data] = bytes[j] & 0x0f; - ar[offset_data + 1] = (bytes[j] >> 4) & 0x0f; + data[offset_data] = bytes[offset_byte] & 0x0f; + data[offset_data + 1] = (bytes[offset_byte] >> 4) & 0x0f; } } -void PQCLEAN_SABER_CLEAN_pack_6bit(uint8_t *bytes, const uint16_t *data) { - uint32_t j; - uint32_t offset_data, offset_byte; - - for (j = 0; j < SABER_N / 4; j++) { - offset_byte = 3 * j; - offset_data = 4 * j; - bytes[offset_byte + 0] = (data[offset_data + 0] & 0x3f) | - ((data[offset_data + 1] & 0x03) << 6); - bytes[offset_byte + 1] = ((data[offset_data + 1] >> 2) & 0x0f) | - ((data[offset_data + 2] & 0x0f) << 4); - bytes[offset_byte + 2] = ((data[offset_data + 2] >> 4) & 0x03) | - ((data[offset_data + 3] & 0x3f) << 2); - } -} - - -void PQCLEAN_SABER_CLEAN_un_pack6bit(const unsigned char *bytes, uint16_t *data) { - uint32_t j; - uint32_t offset_data, offset_byte; - - for (j = 0; j < SABER_N / 4; j++) { - offset_byte = 3 * j; - offset_data = 4 * j; - data[offset_data + 0] = bytes[offset_byte + 0] & 0x3f; - data[offset_data + 1] = ((bytes[offset_byte + 0] >> 6) & 0x03) | - ((bytes[offset_byte + 1] & 0x0f) << 2); - data[offset_data + 2] = ((bytes[offset_byte + 1] & 0xff) >> 4) | - ((bytes[offset_byte + 2] & 0x03) << 4); - data[offset_data + 3] = ((bytes[offset_byte + 2] & 0xff) >> 2); - } -} - - -static void POLVECp2BS(uint8_t *bytes, uint16_t data[SABER_K][SABER_N]) { - uint32_t i, j; - uint32_t offset_data, offset_byte, offset_byte1; - - for (i = 0; i < SABER_K; i++) { - offset_byte1 = i * (SABER_N * 10) / 8; - for (j = 0; j < SABER_N / 4; j++) { - offset_byte = offset_byte1 + 5 * j; - offset_data = 4 * j; - bytes[offset_byte + 0] = (data[i][offset_data + 0] & (0xff)); - bytes[offset_byte + 1] = ((data[i][offset_data + 0] >> 8) & 0x03) | - ((data[i][offset_data + 1] & 0x3f) << 2); - bytes[offset_byte + 2] = ((data[i][offset_data + 1] >> 6) & 0x0f) | - ((data[i][offset_data + 2] & 0x0f) << 4); - bytes[offset_byte + 3] = ((data[i][offset_data + 2] >> 4) & 0x3f) | - ((data[i][offset_data + 3] & 0x03) << 6); - bytes[offset_byte + 4] = ((data[i][offset_data + 3] >> 2) & 0xff); - } - } -} - -static void BS2POLVECp(const unsigned char *bytes, uint16_t data[SABER_K][SABER_N]) { - uint32_t i, j; - uint32_t offset_data, offset_byte, offset_byte1; - - for (i = 0; i < SABER_K; i++) { - offset_byte1 = i * (SABER_N * 10) / 8; - for (j = 0; j < SABER_N / 4; j++) { - offset_byte = offset_byte1 + 5 * j; - offset_data = 4 * j; - data[i][offset_data + 0] = (bytes[offset_byte + 0] & (0xff)) | - ((bytes[offset_byte + 1] & 0x03) << 8); - data[i][offset_data + 1] = ((bytes[offset_byte + 1] >> 2) & (0x3f)) | - ((bytes[offset_byte + 2] & 0x0f) << 6); - data[i][offset_data + 2] = ((bytes[offset_byte + 2] >> 4) & (0x0f)) | - ((bytes[offset_byte + 3] & 0x3f) << 4); - data[i][offset_data + 3] = ((bytes[offset_byte + 3] >> 6) & (0x03)) | - ((bytes[offset_byte + 4] & 0xff) << 2); - } - } -} - - - -static void POLVECq2BS(uint8_t *bytes, uint16_t data[SABER_K][SABER_N]) { - uint32_t i, j; - uint32_t offset_data, offset_byte, offset_byte1; - - for (i = 0; i < SABER_K; i++) { - offset_byte1 = i * (SABER_N * 13) / 8; - for (j = 0; j < SABER_N / 8; j++) { - offset_byte = offset_byte1 + 13 * j; - offset_data = 8 * j; - bytes[offset_byte + 0] = (data[i][offset_data + 0] & (0xff)); - bytes[offset_byte + 1] = ((data[i][offset_data + 0] >> 8) & 0x1f) | - ((data[i][offset_data + 1] & 0x07) << 5); - bytes[offset_byte + 2] = ((data[i][offset_data + 1] >> 3) & 0xff); - bytes[offset_byte + 3] = ((data[i][offset_data + 1] >> 11) & 0x03) | - ((data[i][offset_data + 2] & 0x3f) << 2); - bytes[offset_byte + 4] = ((data[i][offset_data + 2] >> 6) & 0x7f) | - ((data[i][offset_data + 3] & 0x01) << 7); - bytes[offset_byte + 5] = ((data[i][offset_data + 3] >> 1) & 0xff); - bytes[offset_byte + 6] = ((data[i][offset_data + 3] >> 9) & 0x0f) | - ((data[i][offset_data + 4] & 0x0f) << 4); - bytes[offset_byte + 7] = ((data[i][offset_data + 4] >> 4) & 0xff); - bytes[offset_byte + 8] = ((data[i][offset_data + 4] >> 12) & 0x01) | - ((data[i][offset_data + 5] & 0x7f) << 1); - bytes[offset_byte + 9] = ((data[i][offset_data + 5] >> 7) & 0x3f) | - ((data[i][offset_data + 6] & 0x03) << 6); - bytes[offset_byte + 10] = ((data[i][offset_data + 6] >> 2) & 0xff); - bytes[offset_byte + 11] = ((data[i][offset_data + 6] >> 10) & 0x07) | - ((data[i][offset_data + 7] & 0x1f) << 3); - bytes[offset_byte + 12] = ((data[i][offset_data + 7] >> 5) & 0xff); - } - } -} - -static void BS2POLVECq(const unsigned char *bytes, uint16_t data[SABER_K][SABER_N]) { - uint32_t i, j; - uint32_t offset_data, offset_byte, offset_byte1; - - for (i = 0; i < SABER_K; i++) { - offset_byte1 = i * (SABER_N * 13) / 8; - for (j = 0; j < SABER_N / 8; j++) { - offset_byte = offset_byte1 + 13 * j; - offset_data = 8 * j; - data[i][offset_data + 0] = (bytes[offset_byte + 0] & (0xff)) | - ((bytes[offset_byte + 1] & 0x1f) << 8); - data[i][offset_data + 1] = (bytes[offset_byte + 1] >> 5 & (0x07)) | - ((bytes[offset_byte + 2] & 0xff) << 3) | - ((bytes[offset_byte + 3] & 0x03) << 11); - data[i][offset_data + 2] = (bytes[offset_byte + 3] >> 2 & (0x3f)) | - ((bytes[offset_byte + 4] & 0x7f) << 6); - data[i][offset_data + 3] = (bytes[offset_byte + 4] >> 7 & (0x01)) | - ((bytes[offset_byte + 5] & 0xff) << 1) | - ((bytes[offset_byte + 6] & 0x0f) << 9); - data[i][offset_data + 4] = (bytes[offset_byte + 6] >> 4 & (0x0f)) | - ((bytes[offset_byte + 7] & 0xff) << 4) | - ((bytes[offset_byte + 8] & 0x01) << 12); - data[i][offset_data + 5] = (bytes[offset_byte + 8] >> 1 & (0x7f)) | - ((bytes[offset_byte + 9] & 0x3f) << 7); - data[i][offset_data + 6] = (bytes[offset_byte + 9] >> 6 & (0x03)) | - ((bytes[offset_byte + 10] & 0xff) << 2) | - ((bytes[offset_byte + 11] & 0x07) << 10); - data[i][offset_data + 7] = (bytes[offset_byte + 11] >> 3 & (0x1f)) | - ((bytes[offset_byte + 12] & 0xff) << 5); - } - } -} - -//only BS2POLq no BS2POLp -void PQCLEAN_SABER_CLEAN_BS2POL(const unsigned char *bytes, uint16_t data[SABER_N]) { - uint32_t j; - uint32_t offset_data, offset_byte; - +static void POLq2BS(uint8_t bytes[SABER_POLYBYTES], const uint16_t data[SABER_N]) { + size_t j, offset_byte, offset_data; for (j = 0; j < SABER_N / 8; j++) { offset_byte = 13 * j; offset_data = 8 * j; - data[offset_data + 0] = (bytes[offset_byte + 0] & (0xff)) | - ((bytes[offset_byte + 1] & 0x1f) << 8); - data[offset_data + 1] = (bytes[offset_byte + 1] >> 5 & (0x07)) | - ((bytes[offset_byte + 2] & 0xff) << 3) | - ((bytes[offset_byte + 3] & 0x03) << 11); - data[offset_data + 2] = (bytes[offset_byte + 3] >> 2 & (0x3f)) | - ((bytes[offset_byte + 4] & 0x7f) << 6); - data[offset_data + 3] = (bytes[offset_byte + 4] >> 7 & (0x01)) | - ((bytes[offset_byte + 5] & 0xff) << 1) | - ((bytes[offset_byte + 6] & 0x0f) << 9); - data[offset_data + 4] = (bytes[offset_byte + 6] >> 4 & (0x0f)) | - ((bytes[offset_byte + 7] & 0xff) << 4) | - ((bytes[offset_byte + 8] & 0x01) << 12); - data[offset_data + 5] = (bytes[offset_byte + 8] >> 1 & (0x7f)) | - ((bytes[offset_byte + 9] & 0x3f) << 7); - data[offset_data + 6] = (bytes[offset_byte + 9] >> 6 & (0x03)) | - ((bytes[offset_byte + 10] & 0xff) << 2) | - ((bytes[offset_byte + 11] & 0x07) << 10); - data[offset_data + 7] = (bytes[offset_byte + 11] >> 3 & (0x1f)) | - ((bytes[offset_byte + 12] & 0xff) << 5); + bytes[offset_byte + 0] = (data[offset_data + 0] & (0xff)); + bytes[offset_byte + 1] = ((data[offset_data + 0] >> 8) & 0x1f) | ((data[offset_data + 1] & 0x07) << 5); + bytes[offset_byte + 2] = ((data[offset_data + 1] >> 3) & 0xff); + bytes[offset_byte + 3] = ((data[offset_data + 1] >> 11) & 0x03) | ((data[offset_data + 2] & 0x3f) << 2); + bytes[offset_byte + 4] = ((data[offset_data + 2] >> 6) & 0x7f) | ((data[offset_data + 3] & 0x01) << 7); + bytes[offset_byte + 5] = ((data[offset_data + 3] >> 1) & 0xff); + bytes[offset_byte + 6] = ((data[offset_data + 3] >> 9) & 0x0f) | ((data[offset_data + 4] & 0x0f) << 4); + bytes[offset_byte + 7] = ((data[offset_data + 4] >> 4) & 0xff); + bytes[offset_byte + 8] = ((data[offset_data + 4] >> 12) & 0x01) | ((data[offset_data + 5] & 0x7f) << 1); + bytes[offset_byte + 9] = ((data[offset_data + 5] >> 7) & 0x3f) | ((data[offset_data + 6] & 0x03) << 6); + bytes[offset_byte + 10] = ((data[offset_data + 6] >> 2) & 0xff); + bytes[offset_byte + 11] = ((data[offset_data + 6] >> 10) & 0x07) | ((data[offset_data + 7] & 0x1f) << 3); + bytes[offset_byte + 12] = ((data[offset_data + 7] >> 5) & 0xff); } } -void PQCLEAN_SABER_CLEAN_POLVEC2BS(uint8_t *bytes, uint16_t data[SABER_K][SABER_N], uint16_t modulus) { - if (modulus == 1024) { - POLVECp2BS(bytes, data); - } else if (modulus == 8192) { - POLVECq2BS(bytes, data); +static void BS2POLq(uint16_t data[SABER_N], const uint8_t bytes[SABER_POLYBYTES]) { + size_t j, offset_byte, offset_data; + for (j = 0; j < SABER_N / 8; j++) { + offset_byte = 13 * j; + offset_data = 8 * j; + data[offset_data + 0] = (bytes[offset_byte + 0] & (0xff)) | ((bytes[offset_byte + 1] & 0x1f) << 8); + data[offset_data + 1] = (bytes[offset_byte + 1] >> 5 & (0x07)) | ((bytes[offset_byte + 2] & 0xff) << 3) | ((bytes[offset_byte + 3] & 0x03) << 11); + data[offset_data + 2] = (bytes[offset_byte + 3] >> 2 & (0x3f)) | ((bytes[offset_byte + 4] & 0x7f) << 6); + data[offset_data + 3] = (bytes[offset_byte + 4] >> 7 & (0x01)) | ((bytes[offset_byte + 5] & 0xff) << 1) | ((bytes[offset_byte + 6] & 0x0f) << 9); + data[offset_data + 4] = (bytes[offset_byte + 6] >> 4 & (0x0f)) | ((bytes[offset_byte + 7] & 0xff) << 4) | ((bytes[offset_byte + 8] & 0x01) << 12); + data[offset_data + 5] = (bytes[offset_byte + 8] >> 1 & (0x7f)) | ((bytes[offset_byte + 9] & 0x3f) << 7); + data[offset_data + 6] = (bytes[offset_byte + 9] >> 6 & (0x03)) | ((bytes[offset_byte + 10] & 0xff) << 2) | ((bytes[offset_byte + 11] & 0x07) << 10); + data[offset_data + 7] = (bytes[offset_byte + 11] >> 3 & (0x1f)) | ((bytes[offset_byte + 12] & 0xff) << 5); } } -void PQCLEAN_SABER_CLEAN_BS2POLVEC(const unsigned char *bytes, uint16_t data[SABER_K][SABER_N], uint16_t modulus) { - if (modulus == 1024) { - BS2POLVECp(bytes, data); - } else if (modulus == 8192) { - BS2POLVECq(bytes, data); +static void POLp2BS(uint8_t bytes[SABER_POLYCOMPRESSEDBYTES], const uint16_t data[SABER_N]) { + size_t j, offset_byte, offset_data; + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = 5 * j; + offset_data = 4 * j; + bytes[offset_byte + 0] = (data[offset_data + 0] & (0xff)); + bytes[offset_byte + 1] = ((data[offset_data + 0] >> 8) & 0x03) | ((data[offset_data + 1] & 0x3f) << 2); + bytes[offset_byte + 2] = ((data[offset_data + 1] >> 6) & 0x0f) | ((data[offset_data + 2] & 0x0f) << 4); + bytes[offset_byte + 3] = ((data[offset_data + 2] >> 4) & 0x3f) | ((data[offset_data + 3] & 0x03) << 6); + bytes[offset_byte + 4] = ((data[offset_data + 3] >> 2) & 0xff); + } +} + +static void BS2POLp(uint16_t data[SABER_N], const uint8_t bytes[SABER_POLYCOMPRESSEDBYTES]) { + size_t j, offset_byte, offset_data; + for (j = 0; j < SABER_N / 4; j++) { + offset_byte = 5 * j; + offset_data = 4 * j; + data[offset_data + 0] = (bytes[offset_byte + 0] & (0xff)) | ((bytes[offset_byte + 1] & 0x03) << 8); + data[offset_data + 1] = ((bytes[offset_byte + 1] >> 2) & (0x3f)) | ((bytes[offset_byte + 2] & 0x0f) << 6); + data[offset_data + 2] = ((bytes[offset_byte + 2] >> 4) & (0x0f)) | ((bytes[offset_byte + 3] & 0x3f) << 4); + data[offset_data + 3] = ((bytes[offset_byte + 3] >> 6) & (0x03)) | ((bytes[offset_byte + 4] & 0xff) << 2); + } +} + +void PQCLEAN_SABER_CLEAN_POLVECq2BS(uint8_t bytes[SABER_POLYVECBYTES], const uint16_t data[SABER_L][SABER_N]) { + size_t i; + for (i = 0; i < SABER_L; i++) { + POLq2BS(bytes + i * SABER_POLYBYTES, data[i]); + } +} + +void PQCLEAN_SABER_CLEAN_BS2POLVECq(uint16_t data[SABER_L][SABER_N], const uint8_t bytes[SABER_POLYVECBYTES]) { + size_t i; + for (i = 0; i < SABER_L; i++) { + BS2POLq(data[i], bytes + i * SABER_POLYBYTES); + } +} + +void PQCLEAN_SABER_CLEAN_POLVECp2BS(uint8_t bytes[SABER_POLYVECCOMPRESSEDBYTES], const uint16_t data[SABER_L][SABER_N]) { + size_t i; + for (i = 0; i < SABER_L; i++) { + POLp2BS(bytes + i * (SABER_EP * SABER_N / 8), data[i]); + } +} + +void PQCLEAN_SABER_CLEAN_BS2POLVECp(uint16_t data[SABER_L][SABER_N], const uint8_t bytes[SABER_POLYVECCOMPRESSEDBYTES]) { + size_t i; + for (i = 0; i < SABER_L; i++) { + BS2POLp(data[i], bytes + i * (SABER_EP * SABER_N / 8)); + } +} + +void PQCLEAN_SABER_CLEAN_BS2POLmsg(uint16_t data[SABER_N], const uint8_t bytes[SABER_KEYBYTES]) { + size_t i, j; + for (j = 0; j < SABER_KEYBYTES; j++) { + for (i = 0; i < 8; i++) { + data[j * 8 + i] = ((bytes[j] >> i) & 0x01); + } + } +} + +void PQCLEAN_SABER_CLEAN_POLmsg2BS(uint8_t bytes[SABER_KEYBYTES], const uint16_t data[SABER_N]) { + size_t i, j; + memset(bytes, 0, SABER_KEYBYTES); + + for (j = 0; j < SABER_KEYBYTES; j++) { + for (i = 0; i < 8; i++) { + bytes[j] = bytes[j] | ((data[j * 8 + i] & 0x01) << i); + } } } diff --git a/crypto_kem/saber/clean/pack_unpack.h b/crypto_kem/saber/clean/pack_unpack.h index 2431a217..52537c07 100644 --- a/crypto_kem/saber/clean/pack_unpack.h +++ b/crypto_kem/saber/clean/pack_unpack.h @@ -1,28 +1,27 @@ #ifndef PACK_UNPACK_H #define PACK_UNPACK_H - #include "SABER_params.h" #include #include +void PQCLEAN_SABER_CLEAN_POLT2BS(uint8_t bytes[SABER_SCALEBYTES_KEM], const uint16_t data[SABER_N]); -void PQCLEAN_SABER_CLEAN_pack_3bit(uint8_t *bytes, const uint16_t *data); - -void PQCLEAN_SABER_CLEAN_un_pack3bit(const uint8_t *bytes, uint16_t *data); - -void PQCLEAN_SABER_CLEAN_pack_4bit(uint8_t *bytes, const uint16_t *data); - -void PQCLEAN_SABER_CLEAN_un_pack4bit(const unsigned char *bytes, uint16_t *ar); - -void PQCLEAN_SABER_CLEAN_pack_6bit(uint8_t *bytes, const uint16_t *data); - -void PQCLEAN_SABER_CLEAN_un_pack6bit(const unsigned char *bytes, uint16_t *data); +void PQCLEAN_SABER_CLEAN_BS2POLT(uint16_t data[SABER_N], const uint8_t bytes[SABER_SCALEBYTES_KEM]); -void PQCLEAN_SABER_CLEAN_BS2POL(const unsigned char *bytes, uint16_t data[SABER_N]); +void PQCLEAN_SABER_CLEAN_POLVECq2BS(uint8_t bytes[SABER_POLYVECBYTES], const uint16_t data[SABER_L][SABER_N]); -void PQCLEAN_SABER_CLEAN_POLVEC2BS(uint8_t *bytes, uint16_t data[SABER_K][SABER_N], uint16_t modulus); +void PQCLEAN_SABER_CLEAN_POLVECp2BS(uint8_t bytes[SABER_POLYVECCOMPRESSEDBYTES], const uint16_t data[SABER_L][SABER_N]); + + +void PQCLEAN_SABER_CLEAN_BS2POLVECq(uint16_t data[SABER_L][SABER_N], const uint8_t bytes[SABER_POLYVECBYTES]); + +void PQCLEAN_SABER_CLEAN_BS2POLVECp(uint16_t data[SABER_L][SABER_N], const uint8_t bytes[SABER_POLYVECCOMPRESSEDBYTES]); + + +void PQCLEAN_SABER_CLEAN_BS2POLmsg(uint16_t data[SABER_N], const uint8_t bytes[SABER_KEYBYTES]); + +void PQCLEAN_SABER_CLEAN_POLmsg2BS(uint8_t bytes[SABER_KEYBYTES], const uint16_t data[SABER_N]); -void PQCLEAN_SABER_CLEAN_BS2POLVEC(const unsigned char *bytes, uint16_t data[SABER_K][SABER_N], uint16_t modulus); #endif diff --git a/crypto_kem/saber/clean/poly.c b/crypto_kem/saber/clean/poly.c index 93f55fde..f0403ccf 100644 --- a/crypto_kem/saber/clean/poly.c +++ b/crypto_kem/saber/clean/poly.c @@ -1,21 +1,49 @@ -/*--------------------------------------------------------------------- -This file has been adapted from the implementation -(available at, Public Domain https://github.com/pq-crystals/kyber) -of "CRYSTALS – Kyber: a CCA-secure module-lattice-based KEM" -by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint, -Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle -----------------------------------------------------------------------*/ -#include "SABER_params.h" +#include "api.h" #include "cbd.h" #include "fips202.h" +#include "pack_unpack.h" #include "poly.h" +#include "poly_mul.h" +#include -void PQCLEAN_SABER_CLEAN_GenSecret(uint16_t r[SABER_K][SABER_N], const unsigned char *seed) { - uint8_t buf[SABER_MU * SABER_N * SABER_K / 8]; - - shake128(buf, sizeof(buf), seed, SABER_NOISESEEDBYTES); - - for (size_t i = 0; i < SABER_K; i++) { - PQCLEAN_SABER_CLEAN_cbd(r[i], buf + i * SABER_MU * SABER_N / 8); +void PQCLEAN_SABER_CLEAN_MatrixVectorMul(uint16_t res[SABER_L][SABER_N], const uint16_t A[SABER_L][SABER_L][SABER_N], const uint16_t s[SABER_L][SABER_N], int16_t transpose) { + int i, j; + for (i = 0; i < SABER_L; i++) { + for (j = 0; j < SABER_L; j++) { + if (transpose == 1) { + PQCLEAN_SABER_CLEAN_poly_mul_acc(A[j][i], s[j], res[i]); + } else { + PQCLEAN_SABER_CLEAN_poly_mul_acc(A[i][j], s[j], res[i]); + } + } + } +} + +void PQCLEAN_SABER_CLEAN_InnerProd(uint16_t res[SABER_N], const uint16_t b[SABER_L][SABER_N], const uint16_t s[SABER_L][SABER_N]) { + int j; + for (j = 0; j < SABER_L; j++) { + PQCLEAN_SABER_CLEAN_poly_mul_acc(b[j], s[j], res); + } +} + +void PQCLEAN_SABER_CLEAN_GenMatrix(uint16_t A[SABER_L][SABER_L][SABER_N], const uint8_t seed[SABER_SEEDBYTES]) { + uint8_t buf[SABER_L * SABER_POLYVECBYTES]; + int i; + + shake128(buf, sizeof(buf), seed, SABER_SEEDBYTES); + + for (i = 0; i < SABER_L; i++) { + PQCLEAN_SABER_CLEAN_BS2POLVECq(A[i], buf + i * SABER_POLYVECBYTES); + } +} + +void PQCLEAN_SABER_CLEAN_GenSecret(uint16_t s[SABER_L][SABER_N], const uint8_t seed[SABER_NOISE_SEEDBYTES]) { + uint8_t buf[SABER_L * SABER_POLYCOINBYTES]; + size_t i; + + shake128(buf, sizeof(buf), seed, SABER_NOISE_SEEDBYTES); + + for (i = 0; i < SABER_L; i++) { + PQCLEAN_SABER_CLEAN_cbd(s[i], buf + i * SABER_POLYCOINBYTES); } } diff --git a/crypto_kem/saber/clean/poly.h b/crypto_kem/saber/clean/poly.h index 9d216804..dd882cb7 100644 --- a/crypto_kem/saber/clean/poly.h +++ b/crypto_kem/saber/clean/poly.h @@ -1,26 +1,15 @@ #ifndef POLY_H #define POLY_H - -/*--------------------------------------------------------------------- -This file has been adapted from the implementation -(available at, Public Domain https://github.com/pq-crystals/kyber) -of "CRYSTALS – Kyber: a CCA-secure module-lattice-based KEM" -by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint, -Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle -----------------------------------------------------------------------*/ - - #include "SABER_params.h" #include -typedef struct { - uint16_t coeffs[SABER_N]; -} poly; +void PQCLEAN_SABER_CLEAN_MatrixVectorMul(uint16_t res[SABER_L][SABER_N], const uint16_t a[SABER_L][SABER_L][SABER_N], const uint16_t s[SABER_L][SABER_N], int16_t transpose); -typedef struct { - poly vec[SABER_K]; -} polyvec; +void PQCLEAN_SABER_CLEAN_InnerProd(uint16_t res[SABER_N], const uint16_t b[SABER_L][SABER_N], const uint16_t s[SABER_L][SABER_N]); + +void PQCLEAN_SABER_CLEAN_GenMatrix(uint16_t a[SABER_L][SABER_L][SABER_N], const uint8_t seed[SABER_SEEDBYTES]); + +void PQCLEAN_SABER_CLEAN_GenSecret(uint16_t s[SABER_L][SABER_N], const uint8_t seed[SABER_NOISE_SEEDBYTES]); -void PQCLEAN_SABER_CLEAN_GenSecret(uint16_t r[SABER_K][SABER_N], const unsigned char *seed); #endif diff --git a/crypto_kem/saber/clean/poly_mul.c b/crypto_kem/saber/clean/poly_mul.c index dc1cc779..0655383b 100644 --- a/crypto_kem/saber/clean/poly_mul.c +++ b/crypto_kem/saber/clean/poly_mul.c @@ -228,19 +228,15 @@ static void toom_cook_4way (const uint16_t *a1, const uint16_t *b1, uint16_t *re } } -void PQCLEAN_SABER_CLEAN_pol_mul(uint16_t *a, uint16_t *b, uint16_t *res, uint16_t p, uint32_t n) { - uint32_t i; - // normal multiplication - uint16_t c[512]; - - for (i = 0; i < 512; i++) { - c[i] = 0; - } +/* res += a*b */ +void PQCLEAN_SABER_CLEAN_poly_mul_acc(const uint16_t a[SABER_N], const uint16_t b[SABER_N], uint16_t res[SABER_N]) { + uint16_t c[2 * SABER_N] = {0}; + int i; toom_cook_4way(a, b, c); - // reduction - for (i = n; i < 2 * n; i++) { - res[i - n] = (c[i - n] - c[i]) & (p - 1); + /* reduction */ + for (i = SABER_N; i < 2 * SABER_N; i++) { + res[i - SABER_N] += (c[i - SABER_N] - c[i]); } } diff --git a/crypto_kem/saber/clean/poly_mul.h b/crypto_kem/saber/clean/poly_mul.h index f813be10..e0f10043 100644 --- a/crypto_kem/saber/clean/poly_mul.h +++ b/crypto_kem/saber/clean/poly_mul.h @@ -1,9 +1,9 @@ -#ifndef POLYMUL_H -#define POLYMUL_H - +#ifndef POLY_MUL_H +#define POLY_MUL_H #include "SABER_params.h" #include -void PQCLEAN_SABER_CLEAN_pol_mul(uint16_t *a, uint16_t *b, uint16_t *res, uint16_t p, uint32_t n); +void PQCLEAN_SABER_CLEAN_poly_mul_acc(const uint16_t a[SABER_N], const uint16_t b[SABER_N], uint16_t res[SABER_N]); + #endif diff --git a/crypto_kem/saber/clean/verify.c b/crypto_kem/saber/clean/verify.c index 81f30604..72f4dd34 100644 --- a/crypto_kem/saber/clean/verify.c +++ b/crypto_kem/saber/clean/verify.c @@ -1,3 +1,5 @@ +#include "verify.h" + /*------------------------------------------------- This file has been adapted from the implementation (available at https://github.com/pq-crystals/kyber) of @@ -5,26 +7,25 @@ This file has been adapted from the implementation by : Joppe Bos, Leo Ducas, Eike Kiltz, Tancrede Lepoint, Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle ----------------------------------------------------*/ -#include "verify.h" -#include + /* returns 0 for equal strings, 1 for non-equal strings */ -unsigned char PQCLEAN_SABER_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len) { +uint8_t PQCLEAN_SABER_CLEAN_verify(const uint8_t *a, const uint8_t *b, size_t len) { uint64_t r; size_t i; - r = 0; + for (i = 0; i < len; i++) { r |= a[i] ^ b[i]; } r = (~r + 1); // Two's complement r >>= 63; - return (unsigned char)r; + return (uint8_t) r; } /* b = 1 means mov, b = 0 means don't mov*/ -void PQCLEAN_SABER_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b) { +void PQCLEAN_SABER_CLEAN_cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b) { size_t i; b = -b; diff --git a/crypto_kem/saber/clean/verify.h b/crypto_kem/saber/clean/verify.h index cacb2ee6..f88fe396 100644 --- a/crypto_kem/saber/clean/verify.h +++ b/crypto_kem/saber/clean/verify.h @@ -1,6 +1,5 @@ #ifndef VERIFY_H #define VERIFY_H - /*------------------------------------------------- This file has been adapted from the implementation (available at https://github.com/pq-crystals/kyber) of @@ -13,9 +12,11 @@ Vadim Lyubashevsky, John M. Schanck, Peter Schwabe & Damien stehle #include /* returns 0 for equal strings, 1 for non-equal strings */ -unsigned char PQCLEAN_SABER_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len); +uint8_t PQCLEAN_SABER_CLEAN_verify(const uint8_t *a, const uint8_t *b, size_t len); + /* b = 1 means mov, b = 0 means don't mov*/ -void PQCLEAN_SABER_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b); +void PQCLEAN_SABER_CLEAN_cmov(uint8_t *r, const uint8_t *x, size_t len, uint8_t b); + #endif diff --git a/test/duplicate_consistency/firesaber_avx2.yml b/test/duplicate_consistency/firesaber_avx2.yml new file mode 100644 index 00000000..1790559f --- /dev/null +++ b/test/duplicate_consistency/firesaber_avx2.yml @@ -0,0 +1,7 @@ +consistency_checks: + - source: + scheme: firesaber + implementation: clean + files: + - verify.h + - verify.c diff --git a/test/duplicate_consistency/firesaber_clean.yml b/test/duplicate_consistency/firesaber_clean.yml index 60a1a153..3e93674e 100644 --- a/test/duplicate_consistency/firesaber_clean.yml +++ b/test/duplicate_consistency/firesaber_clean.yml @@ -1,31 +1,7 @@ consistency_checks: -- source: - scheme: lightsaber - implementation: clean - files: - - cbd.h - - kem.c - - pack_unpack.c - - pack_unpack.h - - poly.c - - poly.h - - poly_mul.c - - poly_mul.h - - SABER_indcpa.h - - verify.c - - verify.h -- source: - scheme: saber - implementation: clean - files: - - cbd.h - - kem.c - - pack_unpack.c - - pack_unpack.h - - poly.c - - poly.h - - poly_mul.c - - poly_mul.h - - SABER_indcpa.h - - verify.c - - verify.h + - source: + scheme: firesaber + implementation: avx2 + files: + - verify.h + - verify.c diff --git a/test/duplicate_consistency/lightsaber_avx2.yml b/test/duplicate_consistency/lightsaber_avx2.yml new file mode 100644 index 00000000..9239f8f0 --- /dev/null +++ b/test/duplicate_consistency/lightsaber_avx2.yml @@ -0,0 +1,45 @@ +consistency_checks: + - source: + scheme: lightsaber + implementation: clean + files: + - verify.h + - verify.c + - source: + scheme: saber + implementation: clean + files: + - verify.h + - verify.c + - source: + scheme: saber + implementation: avx2 + files: + - cbd.h + - kem.h + - pack_unpack.h + - poly.h + - SABER_indcpa.h + - verify.h + - kem.c + - pack_unpack.c + - verify.c + - source: + scheme: firesaber + implementation: clean + files: + - verify.h + - verify.c + - source: + scheme: firesaber + implementation: avx2 + files: + - cbd.h + - kem.h + - pack_unpack.h + - poly.h + - SABER_indcpa.h + - verify.h + - kem.c + - pack_unpack.c + - verify.c diff --git a/test/duplicate_consistency/lightsaber_clean.yml b/test/duplicate_consistency/lightsaber_clean.yml index a4d483be..14c8975d 100644 --- a/test/duplicate_consistency/lightsaber_clean.yml +++ b/test/duplicate_consistency/lightsaber_clean.yml @@ -1,31 +1,49 @@ consistency_checks: -- source: - scheme: saber - implementation: clean - files: - - cbd.h - - kem.c - - pack_unpack.c - - pack_unpack.h - - poly.c - - poly.h - - poly_mul.c - - poly_mul.h - - SABER_indcpa.h - - verify.c - - verify.h -- source: - scheme: firesaber - implementation: clean - files: - - cbd.h - - kem.c - - pack_unpack.c - - pack_unpack.h - - poly.c - - poly.h - - poly_mul.c - - poly_mul.h - - SABER_indcpa.h - - verify.c - - verify.h + - source: + scheme: lightsaber + implementation: avx2 + files: + - verify.h + - verify.c + - source: + scheme: saber + implementation: clean + files: + - cbd.h + - pack_unpack.h + - poly.h + - poly_mul.h + - SABER_indcpa.h + - verify.h + - kem.c + - poly.c + - poly_mul.c + - SABER_indcpa.c + - verify.c + - source: + scheme: saber + implementation: avx2 + files: + - verify.h + - verify.c + - source: + scheme: firesaber + implementation: clean + files: + - cbd.h + - pack_unpack.h + - poly.h + - poly_mul.h + - SABER_indcpa.h + - verify.h + - kem.c + - poly.c + - poly_mul.c + - SABER_indcpa.c + - verify.c + - source: + scheme: firesaber + implementation: avx2 + files: + - verify.h + - verify.c diff --git a/test/duplicate_consistency/saber_avx2.yml b/test/duplicate_consistency/saber_avx2.yml new file mode 100644 index 00000000..010ac0c9 --- /dev/null +++ b/test/duplicate_consistency/saber_avx2.yml @@ -0,0 +1,26 @@ +consistency_checks: + - source: + scheme: saber + implementation: clean + files: + - verify.h + - verify.c + - source: + scheme: firesaber + implementation: clean + files: + - verify.h + - verify.c + - source: + scheme: firesaber + implementation: avx2 + files: + - cbd.h + - kem.h + - pack_unpack.h + - poly.h + - SABER_indcpa.h + - verify.h + - kem.c + - pack_unpack.c + - verify.c diff --git a/test/duplicate_consistency/saber_clean.yml b/test/duplicate_consistency/saber_clean.yml index 0e1b89dd..7f01d619 100644 --- a/test/duplicate_consistency/saber_clean.yml +++ b/test/duplicate_consistency/saber_clean.yml @@ -1,31 +1,28 @@ consistency_checks: -- source: - scheme: lightsaber - implementation: clean - files: - - cbd.h - - kem.c - - pack_unpack.c - - pack_unpack.h - - poly.c - - poly.h - - poly_mul.c - - poly_mul.h - - SABER_indcpa.h - - verify.c - - verify.h -- source: - scheme: firesaber - implementation: clean - files: - - cbd.h - - kem.c - - pack_unpack.c - - pack_unpack.h - - poly.c - - poly.h - - poly_mul.c - - poly_mul.h - - SABER_indcpa.h - - verify.c - - verify.h + - source: + scheme: saber + implementation: avx2 + files: + - verify.h + - verify.c + - source: + scheme: firesaber + implementation: clean + files: + - cbd.h + - pack_unpack.h + - poly.h + - poly_mul.h + - SABER_indcpa.h + - verify.h + - kem.c + - poly.c + - poly_mul.c + - SABER_indcpa.c + - verify.c + - source: + scheme: firesaber + implementation: avx2 + files: + - verify.h + - verify.c