Commit 7e346d2a authored by Johann Groszschädl's avatar Johann Groszschädl
Browse files

Initial commit of the product-form polynomial multiplication

parent b2a27b08
This diff is collapsed.
///////////////////////////////////////////////////////////////////////////////
// ring_red_mod3.S: Reduction of a 16-bit unsigned integer modulo 3. //
// This file is part of AVRNTRU, a fast NTRU implementation for 8-bit AVR. //
// Version 1.0.0 (2018-12-17), see <http://www.cryptolux.org/> for updates. //
// Authors: Johann Groszschaedl and Hao Cheng (University of Luxembourg). //
// License: GPLv3 (see LICENSE file), other licenses available upon request. //
// Copyright (C) 2018-2019 University of Luxembourg <http://www.uni.lu/> //
// ------------------------------------------------------------------------- //
// This program is free software: you can redistribute it and/or modify it //
// under the terms of the GNU General Public License as published by the //
// Free Software Foundation, either version 3 of the License, or (at your //
// option) any later version. This program is distributed in the hope that //
// it will be useful, but WITHOUT ANY WARRANTY; without even the implied //
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. You should have received a //
// copy of the GNU General Public License along with this program. If not, //
// see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////
// Function prototype:
// -------------------
//
// Description:
// ------------
//
// Operands:
// ---------
//
// Version history:
// ----------------
// define register names
#define HIBYTE R25 // upper byte of 16-bit UINT to be reduced mod 3
#define LOBYTE R24 // upper byte of 16-bit UINT to be reduced mod 3
#define ZERO R23 // ZERO is always 0
.global ring_red_mod3
.func ring_red_mod3
ring_red_mod3:
// initialize variables
CLR ZERO
// first step: reduction modulo 85*3 = 255 = 2^8 - 1
ADD LOBYTE, HIBYTE //
ADC LOBYTE, ZERO //
// second step: reduction modulo 5*3 = 15 = 2^4 - 1
MOV HIBYTE, LOBYTE //
SWAP HIBYTE // swap the 4-bit nibbles of HIBYTE
ANDI LOBYTE, 0xF //
ANDI HIBYTE, 0xF //
ADD LOBYTE, HIBYTE //
MOV HIBYTE, LOBYTE //
SWAP HIBYTE // swap the 4-bit nibbles of HIBYTE
ADD LOBYTE, HIBYTE //
ANDI LOBYTE, 0xF //
// third step: reduction modulo 3 = 2^2 - 1
MOV HIBYTE, LOBYTE //
LSR HIBYTE //
LSR HIBYTE //
ANDI LOBYTE, 0x3 //
ADD LOBYTE, HIBYTE //
MOV HIBYTE, LOBYTE //
LSR HIBYTE //
LSR HIBYTE //
ANDI LOBYTE, 0x3 //
ADD LOBYTE, HIBYTE //
// final subtraction of 3, followed by addition of 3 if difference < 0
SUBI LOBYTE, 0x3 //
SBC ZERO, ZERO //
ANDI ZERO, 0x3 // ZERO is now either 0 or 3
ADD LOBYTE, ZERO //
// pop registers from stack
CLR HIBYTE
CLR R1
// that's all folks :-)
RET
.end func
///////////////////////////////////////////////////////////////////////////////
// config.h: Basic Configuration of AVRNTRU (e.g. C/ASM, VLAs/static arrays) //
// This file is part of AVRNTRU, a fast NTRU implementation for 8-bit AVR. //
// Version 1.1.0 (2019-04-19), see <http://www.cryptolux.org/> for updates. //
// Authors: Johann Groszschaedl and Hao Cheng (University of Luxembourg). //
// License: GPLv3 (see LICENSE file), other licenses available upon request. //
// Copyright (C) 2018-2019 University of Luxembourg <http://www.uni.lu/> //
// ------------------------------------------------------------------------- //
// This program is free software: you can redistribute it and/or modify it //
// under the terms of the GNU General Public License as published by the //
// Free Software Foundation, either version 3 of the License, or (at your //
// option) any later version. This program is distributed in the hope that //
// it will be useful, but WITHOUT ANY WARRANTY; without even the implied //
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. You should have received a //
// copy of the GNU General Public License along with this program. If not, //
// see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////
#ifndef AVRNTRU_CONFIG_H
#define AVRNTRU_CONFIG_H
#include "typedefs.h"
// The identifier AVRNTRU_MAX_NZC has to be set to the highest number of non-0
// coefficients in the three sparse ternary polynomials f1(x), f2(x), f3(x) of
// which a product-form polynomial f(x) = f1(x)*f2(x) + f3(x) is composed of.
// If multiple parameter sets are to be supported, AVRNTRU_MAX_PM1 must be set
// to the highest number of non-0 coefficients among all sparse polynomials of
// these parameter sets. The present version of AVRNTRU supports the parameter
// sets EES443EP1, EES587EP1, and EES743EP1, of which the polynomial f3(x) in
// EES743EP1 has the highest number of non-0 coefficients, namely 30.
#define AVRNTRU_MAX_NZC 30
// The identifier AVRNTRU_MAX_DIM has to be set to the dimension N of the NTRU
// ring. If multiple parameter sets (i.e. rings of different dimension) are to
// be supported, AVRNTRU_MAX_DEG must be set to the highest dimension among all
// rings of these parameter sets, which is N = 743 for the present version of
// AVRNTRU.
#define AVRNTRU_MAX_DIM 743
// The identifier AVRNTRU_USE_ASM determines whether AVRNTRU is compiled with
// the AVR-assembler implementation or the ANSI C99 implementation of the ring
// arithmetic and all other operations that are either performance-critical or
// need to have constant execution time. On non-AVR platforms the C99 version
// is always used, irrespective of whether AVRNTRU_USE_ASM is defined or not.
#define AVRNTRU_USE_ASM
// The identifier AVRNTRU_USE_VLA determines whether AVRNTRU is compiled with
// Variable-Length Arrays (VLAs) or static arrays for the ring arithmetic (e.g.
// temporary array <t> in ring_mul_tern_prodform) and other functions that are
// implemented in a scalable fashion to support multiple parameter sets without
// re-compilation. If AVRNTRU_USE_VLA is not defined then the length of these
// arrays is fixed to a certain maximum value like AVRNTRU_MAX_DIM. Using VLAs
// reduces the stack consumption of "small" parameterizations (e.g. ES443EP1)
// when AVRNTRU is compiled for multiple parameter sets. However, VLAs inhibit
// static stack-depth analysis and are not supported by some compilers. On the
// other hand, static arrays are usually faster (and also smaller in terms of
// code size) at the expense of higher stack consumption for "small" parameter
// sets (e.g. ES443EP1 would have the same stack footprint as EES743EP1).
#define AVRNTRU_USE_VLA
// xxx
#ifndef NDEBUG
#define AVRNTRU_DEBUG_PRINT
#endif
#define AVRNTRU_NO_ERROR 0
#define AVRNTRU_ERR_xxx1 1
#define AVRNTRU_ERR_xxx2 2
#define AVRNTRU_ERR_xxx3 4
// AVRNTRU comes with optimized Assembler implementations of many "low-level"
// functions that are performance-critical and/or can potentially leak secret
// information through operand-dependent execution times. In addition, AVRNTRU
// contains a plain C99 implementation of every function to ensure it can also
// be compiled for non-AVR platforms. The Assembler version and the C version
// of a function have basically the same name, but the former is appended with
// a "_avr" suffix and the latter with a "_c99" suffix. Higher-level functions
// call these low-level functions using a suffix-less version of the function
// name, which works because the following preprocessor directives rename the
// suffix-less function into either the Assembler function or the C function,
// depending on whether AVRNTRU_USE_ASM is defined or not.
#if defined(__AVR__) && defined(AVRNTRU_USE_ASM)
extern void ring_mul_tern_sparse_avr(uint16_t *z, const uint16_t *u, \
uint16_t *v, int vlen, int N);
#define ring_mul_tern_sparse(z, u, v, vlen, N) \
ring_mul_tern_sparse_avr((z), (u), (v), (vlen), (N))
#else // the C versions of the functions are used
#define ring_mul_tern_sparse(z, u, v, vlen, N) \
ring_mul_tern_sparse_c99((z), (u), (v), (vlen), (N))
#endif // defined(__AVR__) && ...
#endif // AVRNTRU_CONFIG_H
///////////////////////////////////////////////////////////////////////////////
// ring_arith.c: Polynomial Arithmetic for the NTRU Ring Z_q[x]/(x^N - 1). //
// This file is part of AVRNTRU, a fast NTRU implementation for 8-bit AVR. //
// Version 1.1.0 (2019-02-26), see <http://www.cryptolux.org/> for updates. //
// Authors: Johann Groszschaedl and Hao Cheng (University of Luxembourg). //
// License: GPLv3 (see LICENSE file), other licenses available upon request. //
// Copyright (C) 2018-2019 University of Luxembourg <http://www.uni.lu/> //
// ------------------------------------------------------------------------- //
// This program is free software: you can redistribute it and/or modify it //
// under the terms of the GNU General Public License as published by the //
// Free Software Foundation, either version 3 of the License, or (at your //
// option) any later version. This program is distributed in the hope that //
// it will be useful, but WITHOUT ANY WARRANTY; without even the implied //
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. You should have received a //
// copy of the GNU General Public License along with this program. If not, //
// see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////
#include "config.h"
#include "ring_arith.h"
// The macro INTMASK(x) converts an integer x to an "all-1" mask when x = 1 and
// to an "all-0" mask when x = 0.
#define INTMASK(x) (~((x) - 1))
// The following preprocessor directives define the length of two local arrays
// in the ring arithmetic, namely array <index> in ring_mul_tern_sparse and <t>
// in ring_mul_tern_prodform. Depending on AVRNTRU_USE_VLA, these lengths are
// defined such that the concerned arrays become either Variable-Length Arrays
// (VLAs) or static arrays (see config.h for further information).
#ifdef AVRNTRU_USE_VLA
// Microsoft Visual C does not support VLAs
#if !(defined(_MSC_VER) && !defined(__ICL))
#define _vlen vlen
#define _tlen (N + 7)
#else // static arrays are used
#define _vlen AVRNTRU_MAX_NZC
#define _tlen (AVRNTRU_MAX_DIM + 7)
#endif
#endif
// The function <ring_mul_tern_sparse_c99> performs a polynomial multiplication
// z(x) = u(x)*v(x) in the quotient ring R = (Z/Zq)[x]/(x^N-1), where u(x) is
// an arbitrary element of the ring (i.e. a polynomial of degree up to N-1 with
// coefficients in [0, q-1]) and v(x) is a ternary polynomial of degree up to
// N-1. Both the operand u(x) and the result r(x) are represented by arrays of
// 16-bit unsigned integers containing the coefficients of the polynomial (the
// element with index 0 holds the least-significant coefficient). The array <u>
// consists of N+7 elements, whereby u[0]-u[N-1] contain the <N> coefficients
// of u(x) and u[N+i] = u[i] for 0 <= i < 7. On the other hand, the length of
// the result-array <z> is the smallest multiple of eight that is greater than
// or equal to <N>. The operand v(x) is represented by <v>, an array of 16-bit
// unsigned integers whose elements contain the indices of the "+1" and "-1"
// coefficients (and not the coefficients themselves!). This array consists of
// <vlen> elements, whereby the first half (i.e. v[0]-v[vlen/2-1]) holds the
// indices of the "+1" coefficients and the second half the indices of the "-1"
// coefficients. The coefficients of the product z(x) are written to the first
// <N> elements of array <z> and are not reduced modulo q, which means they can
// even be negative. Note that the up to seven remaining elements of array <z>
// will contain arbitrary values and can be ignored. It is assumed that <z> has
// been initialized to 0 before calling the function; if not, a MAC operation
// of the form z(x) = z(x) + u(x)*v(x) is computed instead of a multiplication.
void ring_mul_tern_sparse_c99(uint16_t *r, const uint16_t *u, const uint16_t *v,
int vlen, int N)
{
int index[_vlen], i, j, idx;
register uint16_t sum0, sum1, sum2, sum3, sum4, sum5, sum6, sum7;
// compute index = -j mod N for every j for which coefficient v_j != 0
for (i = 0; i < vlen; i ++)
index[i] = INTMASK(v[i] != 0) & (N - v[i]);
for (i = 0; i < N; i += 8) {
// hybrid method: load eight coefficients of r(x) to eight registers
sum0 = r[i ]; sum1 = r[i+1]; sum2 = r[i+2]; sum3 = r[i+3];
sum4 = r[i+4]; sum5 = r[i+5]; sum6 = r[i+6]; sum7 = r[i+7];
// process all "+1" coefficients of the sparse ternary polynomial v(x)
for (j = 0; j < vlen/2; j ++) {
idx = index[j];
sum0 += u[idx++]; sum1 += u[idx++]; sum2 += u[idx++]; sum3 += u[idx++];
sum4 += u[idx++]; sum5 += u[idx++]; sum6 += u[idx++]; sum7 += u[idx++];
index[j] = idx - (INTMASK(idx >= N) & N);
}
// process all "-1" coefficients of the sparse ternary polynomial v(x)
for (j = vlen/2; j < vlen; j ++) {
idx = index[j];
sum0 -= u[idx++]; sum1 -= u[idx++]; sum2 -= u[idx++]; sum3 -= u[idx++];
sum4 -= u[idx++]; sum5 -= u[idx++]; sum6 -= u[idx++]; sum7 -= u[idx++];
index[j] = idx - (INTMASK(idx >= N) & N);
}
// hybrid method: write the (updated) eight coefficients back to RAM
r[i ] = sum0; r[i+1] = sum1; r[i+2] = sum2; r[i+3] = sum3;
r[i+4] = sum4; r[i+5] = sum5; r[i+6] = sum6; r[i+7] = sum7;
}
}
// The function <ring_mul_tern_sparse_V2> is a more compact implementation of
// the function <ring_mul_tern_sparse_c99> above to show that a multiplication
// of a ring-element by a sparse ternary polynomial requires just 25 lines of
// C code.
void ring_mul_tern_sparse_V2(uint16_t *r, const uint16_t *u, const uint16_t *v,
int vlen, int N)
{
int index[_vlen], i, j, k;
// compute index = -j mod N for every j for which coefficient v_j != 0
for (i = 0; i < vlen; i ++)
index[i] = INTMASK(v[i] != 0) & (N - v[i]);
for (i = 0; i < N; i += 8) {
// process the "+1" coefficients of the sparse ternary polynomial v(x)
for (j = 0; j < vlen/2; j ++) {
k = index[j];
r[i ] += u[k ]; r[i+1] += u[k+1]; r[i+2] += u[k+2]; r[i+3] += u[k+3];
r[i+4] += u[k+4]; r[i+5] += u[k+5]; r[i+6] += u[k+6]; r[i+7] += u[k+7];
index[j] = k + 8 - (INTMASK(k + 8 >= N) & N);
}
// process the "-1" coefficients of the sparse ternary polynomial v(x)
for (j = vlen/2; j < vlen; j ++) {
k = index[j];
r[i ] -= u[k ]; r[i+1] -= u[k+1]; r[i+2] -= u[k+2]; r[i+3] -= u[k+3];
r[i+4] -= u[k+4]; r[i+5] -= u[k+5]; r[i+6] -= u[k+6]; r[i+7] -= u[k+7];
index[j] = k + 8 - (INTMASK(k + 8 >= N) & N);
}
}
}
// The function <ring_mul_tern_prodform> performs a polynomial multiplication
// r(x) = a(x)*b(x) in the quotient ring R = (Z/Zq)[x]/(x^N-1), where a(x) is
// an arbitrary element of the ring (i.e. a polynomial of degree up to N-1 with
// coefficients in [0, q-1]) and b(x) is a ternary polynomial given in "product
// form" (i.e. b(x) = b1(x)*b2(x) + b3(x) is composed of three sub-polynomials
// b1(x), b2(x), and b3(x), all of which are sparse and have a degree of up to
// N-1). Both the operand u(x) and the result r(x) are represented by arrays of
// 16-bit unsigned integers containing the coefficients of the polynomial (the
// element with index 0 holds the least-significant coefficient). The array <a>
// consists of N+7 elements, whereby a[0]-a[N-1] contain the <N> coefficients
// of a(x) and a[N+i] = a[i] for 0 <= i < 7. On the other hand, the length of
// the result-array <r> is the smallest multiple of eight that is greater than
// or equal to <N>. The second operand b(x) is a product-form polynomial and
// represented by the struct prod_form_poly_t (defined in ring_arith.h), which
// consists of (i) an array containing the indices of the non-0 coefficients of
// b1(x), b2(x), b3(x), and (ii) three integers specifying the number of non-0
// coefficients of each sub-polynomial. The coefficients of the product r(x)
// are written to the first <N> elements of array <r> and are reduced modulo
// q = 2^11 = 2048. Note that the up to seven remaining elements of array <z>
// will contain arbitrary values and can be ignored.
void ring_mul_tern_prodform(uint16_t *r, const uint16_t *a,
const prod_form_poly_t *b, int N)
{
int i;
uint16_t t[_tlen], *bstart = b->indices;
// Initialization of array <r> and <t>
for (i = ((N+7)&(-8))-1; i >= 0; i--) r[i] = t[i] = 0;
// 1st multiplication: t(x) = a(x)*b1(x)
ring_mul_tern_sparse(t, a, bstart, b->num_nzc_poly1, N);
// 2nd multiplication: r(x) = t(x)*b2(x) = a(x)*b1(x)*b2(x)
bstart = &(b->indices[b->num_nzc_poly1]);
for (i = 6; i >= 0; i--) t[N+i] = t[i];
ring_mul_tern_sparse(r, t, bstart, b->num_nzc_poly2, N);
// 3rd multiplication: r(x) = r(x) + a(x)*b3(x) = a(x)*[b1(x)*b2(x) + b3(x)]
bstart = &(b->indices[b->num_nzc_poly1 + b->num_nzc_poly2]);
ring_mul_tern_sparse(r, a, bstart, b->num_nzc_poly3, N);
// Reduction of the coefficients of r(x) modulo 2048
for (i = N-1; i >= 0; i--) r[i] &= 0x07FF;
}
///////////////////////////////////////////////////////////////////////////////
// ring_arith.h: Polynomial Arithmetic for the NTRU Ring Z_q[x]/(x^N - 1). //
// This file is part of AVRNTRU, a fast NTRU implementation for 8-bit AVR. //
// Version 1.1.0 (2019-02-26), see <http://www.cryptolux.org/> for updates. //
// Authors: Johann Groszschaedl and Hao Cheng (University of Luxembourg). //
// License: GPLv3 (see LICENSE file), other licenses available upon request. //
// Copyright (C) 2018-2019 University of Luxembourg <http://www.uni.lu/> //
// ------------------------------------------------------------------------- //
// This program is free software: you can redistribute it and/or modify it //
// under the terms of the GNU General Public License as published by the //
// Free Software Foundation, either version 3 of the License, or (at your //
// option) any later version. This program is distributed in the hope that //
// it will be useful, but WITHOUT ANY WARRANTY; without even the implied //
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. You should have received a //
// copy of the GNU General Public License along with this program. If not, //
// see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////
#ifndef AVRNTRU_RING_ARITH_H
#define AVRNTRU_RING_ARITH_H
#include "typedefs.h"
// Struct for a product-form polynomial f(x) = f1(x)*f2(x) + f3(x) where f1(x),
// f2(x), and f3(x) are sparse ternary polynomials.
typedef struct prod_form_poly {
uint16_t *indices; // array with indices of non-0 coefficients in f1, f2, f3
int num_nzc_poly1; // number of non-0 coefficients in sparse polynomial f1
int num_nzc_poly2; // number of non-0 coefficients in sparse polynomial f2
int num_nzc_poly3; // number of non-0 coefficients in sparse polynomial f3
} prod_form_poly_t;
// Function prototypes
void ring_mul_tern_sparse_c99(uint16_t *r, const uint16_t *u, const uint16_t *v,
int vlen, int N);
void ring_mul_tern_prodform(uint16_t *r, const uint16_t *a,
const prod_form_poly_t *b, int N);
#endif // AVRNTRU_RING_ARITH_H
///////////////////////////////////////////////////////////////////////////////
// ring_arith_test.c: Simple Test Programs for the Ring Arithmetic of NTRU. //
// This file is part of AVRNTRU, a fast NTRU implementation for 8-bit AVR. //
// Version 1.1.0 (2019-02-26), see <http://www.cryptolux.org/> for updates. //
// Authors: Johann Groszschaedl and Hao Cheng (University of Luxembourg). //
// License: GPLv3 (see LICENSE file), other licenses available upon request. //
// Copyright (C) 2018-2019 University of Luxembourg <http://www.uni.lu/> //
// ------------------------------------------------------------------------- //
// This program is free software: you can redistribute it and/or modify it //
// under the terms of the GNU General Public License as published by the //
// Free Software Foundation, either version 3 of the License, or (at your //
// option) any later version. This program is distributed in the hope that //
// it will be useful, but WITHOUT ANY WARRANTY; without even the implied //
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. You should have received a //
// copy of the GNU General Public License along with this program. If not, //
// see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include "config.h"
#include "ring_arith.h"
#include "ring_arith_test.h"
#include "utils.h"
#ifdef __AVR__
static FILE mystdout = FDEV_SETUP_STREAM(uart_putch, NULL, _FDEV_SETUP_WRITE);
#endif
// Example from NTRU PKCS Tutorial (Section 3)
void test_ring_mul_11(void)
{
int i, N = 11;
// a(x) is the public key, i.e. a polynomial of degree N-1 with coefficients
// in the range [0, q-1]. However, our implementation requires array <a> to
// have N+7 elements, whereby a[N] = a[0], a[N+1] = a[1], ..., a[N+6] = a[6].
uint16_t a[18] = { 8, 25, 22, 20, 12, 24, 15, 19, 12, 19, 16, 8, 25, 22, \
20, 12, 24, 15 };
// b(x) is a sparse ternary polynomial; in our example the coefficients b_2,
// b_3, b_4 are +1, while the coefficients b_0, b_5, b_7 are -1.
uint16_t b[6] = { 2, 3, 4, 0, 5, 7 };
// c(x) is the message to become encrypted, a polynomial of degree N-1 with
// coefficients in { -1, 0, 1 }.
uint16_t c[11] = { -1, 0, 0, 1, -1, 0, 0, 0, -1, 1, 1 };
// r(x) is the result (i.e. the ciphertext), a polynomial of degree N-1 with
// coefficients in the range [0, q-1]. Our implementation requires the array
// <r> to have a length that is a multiple of 8 and >= N.
uint16_t r[16];
for (i = 0; i < N; i ++) r[i] = 0;
ring_mul_tern_sparse(r, a, b, 6, 11);
for (i = 0; i < N; i ++) r[i] = (r[i] + c[i]) & 0x1F;
printf("r = { ");
for (i = 0; i < N-1; i ++) printf("%i, ", r[i]);
printf("%i }\n", r[N-1]);
// Expected result: { 14, 11, 26, 24, 14, 16, 30, 7, 25, 6, 19 }
}
void test_ring_mul_401(void)
{
int i, N = 401;
// Our implementation requires array <a> to have a length of N+7 elements.
uint16_t a401[408] = { A401COEFFS }; // see ring_arith_test.h for A401COEFFS
uint16_t b401[44] = { B401INDICES }; // see ring_arith_test.h for B401INDICES
// The polynomial b(x) is a ternary polynomial in "product form," which means
// it is given as b(x) = [b1(x)*b2(x) + b3(x)]. When N = 401, b1(x) and b2(x)
// have 16 non-0 coefficients (namely eight "+1" and eight "-1"), while b3(x)
// has 12 non-0 coefficients, half of which are "+1" and the other half "-1".
prod_form_poly_t b = { &(b401[0]), 16, 16, 12 };
uint16_t r[408]; // the length of array <r> must be >= N and a multiple of 8
// Our implementation requires array <a> to have a length of N+7 elements,
// whereby a[N] = a[0], a[N+1] = a[1], ..., and a[N+6] = a[6].
for (i = 0; i < 7; i ++) a401[N+i] = a401[i];
ring_mul_tern_prodform(r, a401, &b, N);
printf("r = { ");
for (i = 0; i < N-1; i ++) printf("%03x, ", r[i]);
printf("%03x }\n", r[N-1]);
// Expected result: { 002, 006, 7fc, 002, 7fe, ..., 7f2, 00d, 007, 004, 7f8 }
}
int main(void)
{
#ifdef __AVR__
init_uart();
stdout = &mystdout;
#endif
test_ring_mul_11();
test_ring_mul_401();
// testmod3();
return 0;
}
///////////////////////////////////////////////////////////////////////////////
// ring_arith_test.h: Simple Test Programs for the Ring Arithmetic of NTRU. //
// This file is part of AVRNTRU, a fast NTRU implementation for 8-bit AVR. //
// Version 1.1.0 (2019-02-26), see <http://www.cryptolux.org/> for updates. //
// Authors: Johann Groszschaedl and Hao Cheng (University of Luxembourg). //
// License: GPLv3 (see LICENSE file), other licenses available upon request. //
// Copyright (C) 2018-2019 University of Luxembourg <http://www.uni.lu/> //
// ------------------------------------------------------------------------- //
// This program is free software: you can redistribute it and/or modify it //
// under the terms of the GNU General Public License as published by the //
// Free Software Foundation, either version 3 of the License, or (at your //
// option) any later version. This program is distributed in the hope that //
// it will be useful, but WITHOUT ANY WARRANTY; without even the implied //
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. You should have received a //
// copy of the GNU General Public License along with this program. If not, //
// see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////
#ifndef AVRNTRU_RING_ARITH_TEST_H
#define AVRNTRU_RING_ARITH_TEST_H
#define A401COEFFS \
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, \
0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, \
0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, \
0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, \
0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, \
0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, \
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, \
0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, \
0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, \
0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, \
0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, \
0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, \
0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, \
0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, \
0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, \
0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, \
0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, \
0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, \
0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, \
0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, \
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, \
0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, \
0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, \
0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, \
0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, \
0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, \
0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, \
0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, \
0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00
#define B401INDICES \
0x0EF, 0x13C, 0x01F, 0x00E, 0x162, 0x028, 0x128, 0x130, \
0x0B3, 0x0F1, 0x07F, 0x13A, 0x09D, 0x0FB, 0x08B, 0x040, \
0x18A, 0x186, 0x111, 0x05F, 0x0C8, 0x10B, 0x0D1, 0x0DE, \
0x021, 0x0D3, 0x034, 0x103, 0x101, 0x08D, 0x087, 0x050, \
0x0B4, 0x064, 0x032, 0x01F, 0x12A, 0x074, 0x039, 0x105, \
0x152, 0x179, 0x027, 0x0C7
#endif // AVRNTRU_RING_ARITH_TEST_H
///////////////////////////////////////////////////////////////////////////////
// typedefs.h: Definition of Fixed-Widh Integer Types for Pre-C99 Compilers. //
// This file is part of AVRNTRU, a fast NTRU implementation for 8-bit AVR. //
// Version 1.0.0 (2018-12-17), see <http://www.cryptolux.org/> for updates. //
// Authors: Johann Groszschaedl and Hao Cheng (University of Luxembourg). //
// License: GPLv3 (see LICENSE file), other licenses available upon request. //
// Copyright (C) 2018-2019 University of Luxembourg <http://www.uni.lu/> //
// ------------------------------------------------------------------------- //
// This program is free software: you can redistribute it and/or modify it //
// under the terms of the GNU General Public License as published by the //
// Free Software Foundation, either version 3 of the License, or (at your //
// option) any later version. This program is distributed in the hope that //
// it will be useful, but WITHOUT ANY WARRANTY; without even the implied //
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. You should have received a //
// copy of the GNU General Public License along with this program. If not, //
// see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////
#ifndef AVRNTRU_TYPEDEFS_H
#define AVRNTRU_TYPED