mirror of
https://github.com/henrydcase/pqc.git
synced 2024-11-23 07:59:01 +00:00
86 lines
2.5 KiB
C
86 lines
2.5 KiB
C
|
#include "mq.h"
|
||
|
#include "params.h"
|
||
|
|
||
|
/* Computes all products x_i * x_j, returns in reduced form */
|
||
|
inline static
|
||
|
void generate_quadratic_terms( gf31 * xij , const gf31 * x )
|
||
|
{
|
||
|
int i, j, k;
|
||
|
k=0;
|
||
|
for(i=0;i<N;i++) {
|
||
|
for(j=0;j<=i;j++) {
|
||
|
xij[k] = PQCLEAN_MQDSS48_CLEAN_mod31((gf31)(x[i]*x[j]));
|
||
|
k++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Computes all terms (x_i * y_j) + (x_j * y_i), returns in reduced form */
|
||
|
inline static
|
||
|
void generate_xiyj_p_xjyi_terms( gf31 * xij , const gf31 * x , const gf31 * y )
|
||
|
{
|
||
|
int i, j, k;
|
||
|
k=0;
|
||
|
for(i=0;i<N;i++) {
|
||
|
for(j=0;j<=i;j++) {
|
||
|
xij[k] = PQCLEAN_MQDSS48_CLEAN_mod31((gf31)(x[i]*y[j]+x[j]*y[i]));
|
||
|
k++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Evaluates the MQ function on a vector of N gf31 elements x (expected to be
|
||
|
in reduced 5-bit representation). Expects the coefficients in F to be in
|
||
|
signed representation (i.e. [-15, 15], packed bytewise).
|
||
|
Outputs M gf31 elements in unique 16-bit representation as fx. */
|
||
|
void PQCLEAN_MQDSS48_CLEAN_MQ(gf31 *fx, const gf31 *x, const signed char *F)
|
||
|
{
|
||
|
int i, j;
|
||
|
gf31 _xij[N*(N+1) >> 1];
|
||
|
int r[M] = {0};
|
||
|
|
||
|
generate_quadratic_terms(_xij, x);
|
||
|
|
||
|
for (i = 0; i < N; i += 2) {
|
||
|
for (j = 0; j < M; j++) {
|
||
|
r[j] += ((int)x[i])*((int)F[i*M + 2*j]) +
|
||
|
((int)x[i+1])*((int)F[i*M + 2*j + 1]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < (N*(N+1)) >> 1; i += 2) {
|
||
|
for (j = 0; j < M; j++) {
|
||
|
r[j] += ((int)_xij[i])*((int)F[N*M + i*M + 2*j]) +
|
||
|
((int)_xij[i+1])*((int)F[N*M + i*M + 2*j + 1]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < M; i++) {
|
||
|
fx[i] = PQCLEAN_MQDSS48_CLEAN_mod31((gf31)((r[i] >> 15) + (r[i] & 0x7FFF)));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Evaluates the bilinear polar form of the MQ function (i.e. G) on a vector of
|
||
|
N gf31 elements x (expected to be in reduced 5-bit representation). Expects
|
||
|
the coefficients in F to be in signed representation (i.e. [-15, 15], packed
|
||
|
bytewise). Outputs M gf31 elements in unique 16-bit representation as fx. */
|
||
|
void PQCLEAN_MQDSS48_CLEAN_G(gf31 *fx, const gf31 *x, const gf31 *y, const signed char *F)
|
||
|
{
|
||
|
int i, j;
|
||
|
gf31 _xij[N*(N+1) >> 1];
|
||
|
int r[M] = {0};
|
||
|
|
||
|
generate_xiyj_p_xjyi_terms(_xij, x, y);
|
||
|
|
||
|
for (i = 0; i < (N*(N+1)) >> 1; i += 2) {
|
||
|
for (j = 0; j < M; j++) {
|
||
|
r[j] += ((int)_xij[i])*((int)F[N*M + i*M + 2*j]) +
|
||
|
((int)_xij[i+1])*((int)F[N*M + i*M + 2*j + 1]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < M; i++) {
|
||
|
fx[i] = PQCLEAN_MQDSS48_CLEAN_mod31((gf31)((r[i] >> 15) + (r[i] & 0x7FFF)));
|
||
|
}
|
||
|
}
|