pqc/crypto_kem/kyber768/clean/ntt.c

81 lines
2.9 KiB
C
Raw Normal View History

2019-01-16 10:02:32 +00:00
#include "ntt.h"
#include "inttypes.h"
#include "params.h"
#include "reduce.h"
extern const uint16_t PQCLEAN_KYBER768_CLEAN_omegas_inv_bitrev_montgomery[];
extern const uint16_t PQCLEAN_KYBER768_CLEAN_psis_inv_montgomery[];
extern const uint16_t PQCLEAN_KYBER768_CLEAN_zetas[];
2019-01-16 10:02:32 +00:00
/*************************************************
* Name: ntt
*
* Description: Computes negacyclic number-theoretic transform (NTT) of
* a polynomial (vector of 256 coefficients) in place;
* inputs assumed to be in normal order, output in bitreversed
*order
*
* Arguments: - uint16_t *p: pointer to in/output polynomial
**************************************************/
void PQCLEAN_KYBER768_CLEAN_ntt(uint16_t *p) {
2019-01-16 10:02:32 +00:00
int level, start, j, k;
uint16_t zeta, t;
k = 1;
for (level = 7; level >= 0; level--) {
for (start = 0; start < KYBER_N; start = j + (1 << level)) {
zeta = PQCLEAN_KYBER768_CLEAN_zetas[k++];
2019-01-16 10:02:32 +00:00
for (j = start; j < start + (1 << level); ++j) {
t = PQCLEAN_KYBER768_CLEAN_montgomery_reduce((uint32_t)zeta * p[j + (1 << level)]);
2019-01-16 10:02:32 +00:00
p[j + (1 << level)] = PQCLEAN_KYBER768_CLEAN_barrett_reduce(p[j] + 4 * KYBER_Q - t);
2019-01-16 10:02:32 +00:00
if (level & 1) { /* odd level */
p[j] = p[j] + t; /* Omit reduction (be lazy) */
} else {
p[j] = PQCLEAN_KYBER768_CLEAN_barrett_reduce(p[j] + t);
2019-01-16 10:02:32 +00:00
}
}
}
}
}
/*************************************************
* Name: invntt
*
* Description: Computes inverse of negacyclic number-theoretic transform (NTT)
*of a polynomial (vector of 256 coefficients) in place; inputs assumed to be in
*bitreversed order, output in normal order
*
* Arguments: - uint16_t *a: pointer to in/output polynomial
**************************************************/
void PQCLEAN_KYBER768_CLEAN_invntt(uint16_t *a) {
2019-01-16 10:02:32 +00:00
int start, j, jTwiddle, level;
uint16_t temp, W;
uint32_t t;
for (level = 0; level < 8; level++) {
for (start = 0; start < (1 << level); start++) {
jTwiddle = 0;
for (j = start; j < KYBER_N - 1; j += 2 * (1 << level)) {
W = PQCLEAN_KYBER768_CLEAN_omegas_inv_bitrev_montgomery[jTwiddle++];
2019-01-16 10:02:32 +00:00
temp = a[j];
if (level & 1) { /* odd level */
a[j] = PQCLEAN_KYBER768_CLEAN_barrett_reduce((temp + a[j + (1 << level)]));
2019-01-16 10:02:32 +00:00
} else {
a[j] = (temp + a[j + (1 << level)]); /* Omit reduction (be lazy) */
2019-01-16 10:02:32 +00:00
}
t = (W * ((uint32_t)temp + 4 * KYBER_Q - a[j + (1 << level)]));
a[j + (1 << level)] = PQCLEAN_KYBER768_CLEAN_montgomery_reduce(t);
2019-01-16 10:02:32 +00:00
}
}
}
for (j = 0; j < KYBER_N; j++) {
a[j] = PQCLEAN_KYBER768_CLEAN_montgomery_reduce((a[j] * PQCLEAN_KYBER768_CLEAN_psis_inv_montgomery[j]));
2019-01-16 10:02:32 +00:00
}
}