2019-01-16 10:02:32 +00:00
|
|
|
#include "ntt.h"
|
|
|
|
#include "inttypes.h"
|
|
|
|
#include "params.h"
|
|
|
|
#include "reduce.h"
|
|
|
|
|
2019-01-22 16:38:22 +00:00
|
|
|
extern const uint16_t PQCLEAN_KYBER768_omegas_inv_bitrev_montgomery[];
|
|
|
|
extern const uint16_t PQCLEAN_KYBER768_psis_inv_montgomery[];
|
|
|
|
extern const uint16_t PQCLEAN_KYBER768_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
|
|
|
|
**************************************************/
|
2019-01-22 16:38:22 +00:00
|
|
|
void PQCLEAN_KYBER768_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)) {
|
2019-01-22 16:38:22 +00:00
|
|
|
zeta = PQCLEAN_KYBER768_zetas[k++];
|
2019-01-16 10:02:32 +00:00
|
|
|
for (j = start; j < start + (1 << level); ++j) {
|
2019-02-13 16:45:09 +00:00
|
|
|
t = PQCLEAN_KYBER768_montgomery_reduce((uint32_t)zeta * p[j + (1 << level)]);
|
2019-01-16 10:02:32 +00:00
|
|
|
|
2019-02-13 16:45:09 +00:00
|
|
|
p[j + (1 << level)] = PQCLEAN_KYBER768_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 {
|
2019-01-22 16:38:22 +00:00
|
|
|
p[j] = PQCLEAN_KYBER768_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
|
|
|
|
**************************************************/
|
2019-01-22 16:38:22 +00:00
|
|
|
void PQCLEAN_KYBER768_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)) {
|
2019-01-22 16:38:22 +00:00
|
|
|
W = PQCLEAN_KYBER768_omegas_inv_bitrev_montgomery[jTwiddle++];
|
2019-01-16 10:02:32 +00:00
|
|
|
temp = a[j];
|
|
|
|
|
|
|
|
if (level & 1) { /* odd level */
|
2019-02-14 14:30:55 +00:00
|
|
|
a[j] = PQCLEAN_KYBER768_barrett_reduce((temp + a[j + (1 << level)]));
|
2019-01-16 10:02:32 +00:00
|
|
|
} else {
|
2019-02-13 16:45:09 +00:00
|
|
|
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)]));
|
|
|
|
|
2019-01-22 16:38:22 +00:00
|
|
|
a[j + (1 << level)] = PQCLEAN_KYBER768_montgomery_reduce(t);
|
2019-01-16 10:02:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (j = 0; j < KYBER_N; j++) {
|
2019-02-14 14:30:55 +00:00
|
|
|
a[j] = PQCLEAN_KYBER768_montgomery_reduce((a[j] * PQCLEAN_KYBER768_psis_inv_montgomery[j]));
|
2019-01-16 10:02:32 +00:00
|
|
|
}
|
|
|
|
}
|