#include <stdint.h>
#include "params.h"
#include "polyvec.h"
#include "poly.h"
#include "ntt.h"
#include "consts.h"
#ifdef DILITHIUM_USE_AES
#include "aes256ctr.h"
#endif
#ifdef DILITHIUM_USE_AES
void polyvec_matrix_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]) {
unsigned int i, j;
uint64_t nonce;
aes256ctr_ctx state;
aes256ctr_init_u64(&state, rho, 0);
for(i = 0; i < K; i++) {
for(j = 0; j < L; j++) {
nonce = (i << 8) + j;
aes256ctr_init_iv_u64(&state, nonce);
poly_uniform_preinit(&mat[i].vec[j], &state);
poly_nttunpack(&mat[i].vec[j]);
}
}
aes256_ctx_release(&state);
}
#elif K == 4 && L == 4
void polyvec_matrix_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]) {
polyvec_matrix_expand_row0(&mat[0], NULL, rho);
polyvec_matrix_expand_row1(&mat[1], NULL, rho);
polyvec_matrix_expand_row2(&mat[2], NULL, rho);
polyvec_matrix_expand_row3(&mat[3], NULL, rho);
}
void polyvec_matrix_expand_row0(polyvecl *rowa, __attribute__((unused)) polyvecl *rowb, const uint8_t rho[SEEDBYTES]) {
poly_uniform_4x(&rowa->vec[0], &rowa->vec[1], &rowa->vec[2], &rowa->vec[3], rho, 0, 1, 2, 3);
poly_nttunpack(&rowa->vec[0]);
poly_nttunpack(&rowa->vec[1]);
poly_nttunpack(&rowa->vec[2]);
poly_nttunpack(&rowa->vec[3]);
}
void polyvec_matrix_expand_row1(polyvecl *rowa, __attribute__((unused)) polyvecl *rowb, const uint8_t rho[SEEDBYTES]) {
poly_uniform_4x(&rowa->vec[0], &rowa->vec[1], &rowa->vec[2], &rowa->vec[3], rho, 256, 257, 258, 259);
poly_nttunpack(&rowa->vec[0]);
poly_nttunpack(&rowa->vec[1]);
poly_nttunpack(&rowa->vec[2]);
poly_nttunpack(&rowa->vec[3]);
}
void polyvec_matrix_expand_row2(polyvecl *rowa, __attribute__((unused)) polyvecl *rowb, const uint8_t rho[SEEDBYTES]) {
poly_uniform_4x(&rowa->vec[0], &rowa->vec[1], &rowa->vec[2], &rowa->vec[3], rho, 512, 513, 514, 515);
poly_nttunpack(&rowa->vec[0]);
poly_nttunpack(&rowa->vec[1]);
poly_nttunpack(&rowa->vec[2]);
poly_nttunpack(&rowa->vec[3]);
}
void polyvec_matrix_expand_row3(polyvecl *rowa, __attribute__((unused)) polyvecl *rowb, const uint8_t rho[SEEDBYTES]) {
poly_uniform_4x(&rowa->vec[0], &rowa->vec[1], &rowa->vec[2], &rowa->vec[3], rho, 768, 769, 770, 771);
poly_nttunpack(&rowa->vec[0]);
poly_nttunpack(&rowa->vec[1]);
poly_nttunpack(&rowa->vec[2]);
poly_nttunpack(&rowa->vec[3]);
}
#elif K == 6 && L == 5
void polyvec_matrix_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]) {
polyvecl tmp;
polyvec_matrix_expand_row0(&mat[0], &mat[1], rho);
polyvec_matrix_expand_row1(&mat[1], &mat[2], rho);
polyvec_matrix_expand_row2(&mat[2], &mat[3], rho);
polyvec_matrix_expand_row3(&mat[3], NULL, rho);
polyvec_matrix_expand_row4(&mat[4], &mat[5], rho);
polyvec_matrix_expand_row5(&mat[5], &tmp, rho);
}
void polyvec_matrix_expand_row0(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) {
poly_uniform_4x(&rowa->vec[0], &rowa->vec[1], &rowa->vec[2], &rowa->vec[3], rho, 0, 1, 2, 3);
poly_uniform_4x(&rowa->vec[4], &rowb->vec[0], &rowb->vec[1], &rowb->vec[2], rho, 4, 256, 257, 258);
poly_nttunpack(&rowa->vec[0]);
poly_nttunpack(&rowa->vec[1]);
poly_nttunpack(&rowa->vec[2]);
poly_nttunpack(&rowa->vec[3]);
poly_nttunpack(&rowa->vec[4]);
poly_nttunpack(&rowb->vec[0]);
poly_nttunpack(&rowb->vec[1]);
poly_nttunpack(&rowb->vec[2]);
}
void polyvec_matrix_expand_row1(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) {
poly_uniform_4x(&rowa->vec[3], &rowa->vec[4], &rowb->vec[0], &rowb->vec[1], rho, 259, 260, 512, 513);
poly_nttunpack(&rowa->vec[3]);
poly_nttunpack(&rowa->vec[4]);
poly_nttunpack(&rowb->vec[0]);
poly_nttunpack(&rowb->vec[1]);
}
void polyvec_matrix_expand_row2(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) {
poly_uniform_4x(&rowa->vec[2], &rowa->vec[3], &rowa->vec[4], &rowb->vec[0], rho, 514, 515, 516, 768);
poly_nttunpack(&rowa->vec[2]);
poly_nttunpack(&rowa->vec[3]);
poly_nttunpack(&rowa->vec[4]);
poly_nttunpack(&rowb->vec[0]);
}
void polyvec_matrix_expand_row3(polyvecl *rowa, __attribute__((unused)) polyvecl *rowb, const uint8_t rho[SEEDBYTES]) {
poly_uniform_4x(&rowa->vec[1], &rowa->vec[2], &rowa->vec[3], &rowa->vec[4], rho, 769, 770, 771, 772);
poly_nttunpack(&rowa->vec[1]);
poly_nttunpack(&rowa->vec[2]);
poly_nttunpack(&rowa->vec[3]);
poly_nttunpack(&rowa->vec[4]);
}
void polyvec_matrix_expand_row4(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) {
poly_uniform_4x(&rowa->vec[0], &rowa->vec[1], &rowa->vec[2], &rowa->vec[3], rho, 1024, 1025, 1026, 1027);
poly_uniform_4x(&rowa->vec[4], &rowb->vec[0], &rowb->vec[1], &rowb->vec[2], rho, 1028, 1280, 1281, 1282);
poly_nttunpack(&rowa->vec[0]);
poly_nttunpack(&rowa->vec[1]);
poly_nttunpack(&rowa->vec[2]);
poly_nttunpack(&rowa->vec[3]);
poly_nttunpack(&rowa->vec[4]);
poly_nttunpack(&rowb->vec[0]);
poly_nttunpack(&rowb->vec[1]);
poly_nttunpack(&rowb->vec[2]);
}
void polyvec_matrix_expand_row5(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) {
poly_uniform_4x(&rowa->vec[3], &rowa->vec[4], &rowb->vec[0], &rowb->vec[1], rho, 1283, 1284, 1536, 1537);
poly_nttunpack(&rowa->vec[3]);
poly_nttunpack(&rowa->vec[4]);
}
#elif K == 8 && L == 7
void polyvec_matrix_expand(polyvecl mat[K], const uint8_t rho[SEEDBYTES]) {
polyvec_matrix_expand_row0(&mat[0], &mat[1], rho);
polyvec_matrix_expand_row1(&mat[1], &mat[2], rho);
polyvec_matrix_expand_row2(&mat[2], &mat[3], rho);
polyvec_matrix_expand_row3(&mat[3], NULL, rho);
polyvec_matrix_expand_row4(&mat[4], &mat[5], rho);
polyvec_matrix_expand_row5(&mat[5], &mat[6], rho);
polyvec_matrix_expand_row6(&mat[6], &mat[7], rho);
polyvec_matrix_expand_row7(&mat[7], NULL, rho);
}
void polyvec_matrix_expand_row0(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) {
poly_uniform_4x(&rowa->vec[0], &rowa->vec[1], &rowa->vec[2], &rowa->vec[3], rho, 0, 1, 2, 3);
poly_uniform_4x(&rowa->vec[4], &rowa->vec[5], &rowa->vec[6], &rowb->vec[0], rho, 4, 5, 6, 256);
poly_nttunpack(&rowa->vec[0]);
poly_nttunpack(&rowa->vec[1]);
poly_nttunpack(&rowa->vec[2]);
poly_nttunpack(&rowa->vec[3]);
poly_nttunpack(&rowa->vec[4]);
poly_nttunpack(&rowa->vec[5]);
poly_nttunpack(&rowa->vec[6]);
poly_nttunpack(&rowb->vec[0]);
}
void polyvec_matrix_expand_row1(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) {
poly_uniform_4x(&rowa->vec[1], &rowa->vec[2], &rowa->vec[3], &rowa->vec[4], rho, 257, 258, 259, 260);
poly_uniform_4x(&rowa->vec[5], &rowa->vec[6], &rowb->vec[0], &rowb->vec[1], rho, 261, 262, 512, 513);
poly_nttunpack(&rowa->vec[1]);
poly_nttunpack(&rowa->vec[2]);
poly_nttunpack(&rowa->vec[3]);
poly_nttunpack(&rowa->vec[4]);
poly_nttunpack(&rowa->vec[5]);
poly_nttunpack(&rowa->vec[6]);
poly_nttunpack(&rowb->vec[0]);
poly_nttunpack(&rowb->vec[1]);
}
void polyvec_matrix_expand_row2(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) {
poly_uniform_4x(&rowa->vec[2], &rowa->vec[3], &rowa->vec[4], &rowa->vec[5], rho, 514, 515, 516, 517);
poly_uniform_4x(&rowa->vec[6], &rowb->vec[0], &rowb->vec[1], &rowb->vec[2], rho, 518, 768, 769, 770);
poly_nttunpack(&rowa->vec[2]);
poly_nttunpack(&rowa->vec[3]);
poly_nttunpack(&rowa->vec[4]);
poly_nttunpack(&rowa->vec[5]);
poly_nttunpack(&rowa->vec[6]);
poly_nttunpack(&rowb->vec[0]);
poly_nttunpack(&rowb->vec[1]);
poly_nttunpack(&rowb->vec[2]);
}
void polyvec_matrix_expand_row3(polyvecl *rowa, __attribute__((unused)) polyvecl *rowb, const uint8_t rho[SEEDBYTES]) {
poly_uniform_4x(&rowa->vec[3], &rowa->vec[4], &rowa->vec[5], &rowa->vec[6], rho, 771, 772, 773, 774);
poly_nttunpack(&rowa->vec[3]);
poly_nttunpack(&rowa->vec[4]);
poly_nttunpack(&rowa->vec[5]);
poly_nttunpack(&rowa->vec[6]);
}
void polyvec_matrix_expand_row4(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) {
poly_uniform_4x(&rowa->vec[0], &rowa->vec[1], &rowa->vec[2], &rowa->vec[3], rho, 1024, 1025, 1026, 1027);
poly_uniform_4x(&rowa->vec[4], &rowa->vec[5], &rowa->vec[6], &rowb->vec[0], rho, 1028, 1029, 1030, 1280);
poly_nttunpack(&rowa->vec[0]);
poly_nttunpack(&rowa->vec[1]);
poly_nttunpack(&rowa->vec[2]);
poly_nttunpack(&rowa->vec[3]);
poly_nttunpack(&rowa->vec[4]);
poly_nttunpack(&rowa->vec[5]);
poly_nttunpack(&rowa->vec[6]);
poly_nttunpack(&rowb->vec[0]);
}
void polyvec_matrix_expand_row5(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) {
poly_uniform_4x(&rowa->vec[1], &rowa->vec[2], &rowa->vec[3], &rowa->vec[4], rho, 1281, 1282, 1283, 1284);
poly_uniform_4x(&rowa->vec[5], &rowa->vec[6], &rowb->vec[0], &rowb->vec[1], rho, 1285, 1286, 1536, 1537);
poly_nttunpack(&rowa->vec[1]);
poly_nttunpack(&rowa->vec[2]);
poly_nttunpack(&rowa->vec[3]);
poly_nttunpack(&rowa->vec[4]);
poly_nttunpack(&rowa->vec[5]);
poly_nttunpack(&rowa->vec[6]);
poly_nttunpack(&rowb->vec[0]);
poly_nttunpack(&rowb->vec[1]);
}
void polyvec_matrix_expand_row6(polyvecl *rowa, polyvecl *rowb, const uint8_t rho[SEEDBYTES]) {
poly_uniform_4x(&rowa->vec[2], &rowa->vec[3], &rowa->vec[4], &rowa->vec[5], rho, 1538, 1539, 1540, 1541);
poly_uniform_4x(&rowa->vec[6], &rowb->vec[0], &rowb->vec[1], &rowb->vec[2], rho, 1542, 1792, 1793, 1794);
poly_nttunpack(&rowa->vec[2]);
poly_nttunpack(&rowa->vec[3]);
poly_nttunpack(&rowa->vec[4]);
poly_nttunpack(&rowa->vec[5]);
poly_nttunpack(&rowa->vec[6]);
poly_nttunpack(&rowb->vec[0]);
poly_nttunpack(&rowb->vec[1]);
poly_nttunpack(&rowb->vec[2]);
}
void polyvec_matrix_expand_row7(polyvecl *rowa, __attribute__((unused)) polyvecl *rowb, const uint8_t rho[SEEDBYTES]) {
poly_uniform_4x(&rowa->vec[3], &rowa->vec[4], &rowa->vec[5], &rowa->vec[6], rho, 1795, 1796, 1797, 1798);
poly_nttunpack(&rowa->vec[3]);
poly_nttunpack(&rowa->vec[4]);
poly_nttunpack(&rowa->vec[5]);
poly_nttunpack(&rowa->vec[6]);
}
#else
#error
#endif
void polyvec_matrix_pointwise_montgomery(polyveck *t, const polyvecl mat[K], const polyvecl *v) {
unsigned int i;
for(i = 0; i < K; ++i)
polyvecl_pointwise_acc_montgomery(&t->vec[i], &mat[i], v);
}
void polyvecl_uniform_eta(polyvecl *v, const uint8_t seed[CRHBYTES], uint16_t nonce) {
unsigned int i;
for(i = 0; i < L; ++i)
poly_uniform_eta(&v->vec[i], seed, nonce++);
}
void polyvecl_uniform_gamma1(polyvecl *v, const uint8_t seed[CRHBYTES], uint16_t nonce) {
unsigned int i;
for(i = 0; i < L; ++i)
poly_uniform_gamma1(&v->vec[i], seed, L*nonce + i);
}
void polyvecl_reduce(polyvecl *v) {
unsigned int i;
for(i = 0; i < L; ++i)
poly_reduce(&v->vec[i]);
}
void polyvecl_add(polyvecl *w, const polyvecl *u, const polyvecl *v) {
unsigned int i;
for(i = 0; i < L; ++i)
poly_add(&w->vec[i], &u->vec[i], &v->vec[i]);
}
void polyvecl_ntt(polyvecl *v) {
unsigned int i;
for(i = 0; i < L; ++i)
poly_ntt(&v->vec[i]);
}
void polyvecl_invntt_tomont(polyvecl *v) {
unsigned int i;
for(i = 0; i < L; ++i)
poly_invntt_tomont(&v->vec[i]);
}
void polyvecl_pointwise_poly_montgomery(polyvecl *r, const poly *a, const polyvecl *v) {
unsigned int i;
for(i = 0; i < L; ++i)
poly_pointwise_montgomery(&r->vec[i], a, &v->vec[i]);
}
void polyvecl_pointwise_acc_montgomery(poly *w, const polyvecl *u, const polyvecl *v) {
pointwise_acc_avx(w->vec, u->vec->vec, v->vec->vec, qdata.vec);
}
int polyvecl_chknorm(const polyvecl *v, int32_t bound) {
unsigned int i;
for(i = 0; i < L; ++i)
if(poly_chknorm(&v->vec[i], bound))
return 1;
return 0;
}
void polyveck_uniform_eta(polyveck *v, const uint8_t seed[CRHBYTES], uint16_t nonce) {
unsigned int i;
for(i = 0; i < K; ++i)
poly_uniform_eta(&v->vec[i], seed, nonce++);
}
void polyveck_reduce(polyveck *v) {
unsigned int i;
for(i = 0; i < K; ++i)
poly_reduce(&v->vec[i]);
}
void polyveck_caddq(polyveck *v) {
unsigned int i;
for(i = 0; i < K; ++i)
poly_caddq(&v->vec[i]);
}
void polyveck_add(polyveck *w, const polyveck *u, const polyveck *v) {
unsigned int i;
for(i = 0; i < K; ++i)
poly_add(&w->vec[i], &u->vec[i], &v->vec[i]);
}
void polyveck_sub(polyveck *w, const polyveck *u, const polyveck *v) {
unsigned int i;
for(i = 0; i < K; ++i)
poly_sub(&w->vec[i], &u->vec[i], &v->vec[i]);
}
void polyveck_shiftl(polyveck *v) {
unsigned int i;
for(i = 0; i < K; ++i)
poly_shiftl(&v->vec[i]);
}
void polyveck_ntt(polyveck *v) {
unsigned int i;
for(i = 0; i < K; ++i)
poly_ntt(&v->vec[i]);
}
void polyveck_invntt_tomont(polyveck *v) {
unsigned int i;
for(i = 0; i < K; ++i)
poly_invntt_tomont(&v->vec[i]);
}
void polyveck_pointwise_poly_montgomery(polyveck *r, const poly *a, const polyveck *v) {
unsigned int i;
for(i = 0; i < K; ++i)
poly_pointwise_montgomery(&r->vec[i], a, &v->vec[i]);
}
int polyveck_chknorm(const polyveck *v, int32_t bound) {
unsigned int i;
for(i = 0; i < K; ++i)
if(poly_chknorm(&v->vec[i], bound))
return 1;
return 0;
}
void polyveck_power2round(polyveck *v1, polyveck *v0, const polyveck *v) {
unsigned int i;
for(i = 0; i < K; ++i)
poly_power2round(&v1->vec[i], &v0->vec[i], &v->vec[i]);
}
void polyveck_decompose(polyveck *v1, polyveck *v0, const polyveck *v) {
unsigned int i;
for(i = 0; i < K; ++i)
poly_decompose(&v1->vec[i], &v0->vec[i], &v->vec[i]);
}
unsigned int polyveck_make_hint(uint8_t *hint, const polyveck *v0, const polyveck *v1)
{
unsigned int i, n = 0;
for(i = 0; i < K; ++i)
n += poly_make_hint(&hint[n], &v0->vec[i], &v1->vec[i]);
return n;
}
void polyveck_use_hint(polyveck *w, const polyveck *u, const polyveck *h) {
unsigned int i;
for(i = 0; i < K; ++i)
poly_use_hint(&w->vec[i], &u->vec[i], &h->vec[i]);
}
void polyveck_pack_w1(uint8_t r[K*POLYW1_PACKEDBYTES], const polyveck *w1) {
unsigned int i;
for(i = 0; i < K; ++i)
polyw1_pack(&r[i*POLYW1_PACKEDBYTES], &w1->vec[i]);
}