ALL: Convert codebase to flint
POLY, ENC, DEC all converted. RAND will have to be revised.
This commit is contained in:
parent
fb7a46c363
commit
c075f4a0a3
@ -37,8 +37,8 @@ endif
|
|||||||
LIBS += -L. -lgmp -lmpfr -lm
|
LIBS += -L. -lgmp -lmpfr -lm
|
||||||
|
|
||||||
# objects
|
# objects
|
||||||
PQC_OBJS = rand.o poly.o mem.o ntru_decrypt.o pqc_encrypt.o
|
PQC_OBJS = poly.o mem.o encrypt.o decrypt.o
|
||||||
PQC_HEADERS = err.h rand.h poly.h context.h ntru_decrypt.h pqc_encrypt.h
|
PQC_HEADERS = err.h poly.h context.h encrypt.h decrypt.h
|
||||||
# CUNIT_OBJS = cunit.o
|
# CUNIT_OBJS = cunit.o
|
||||||
|
|
||||||
# includes
|
# includes
|
||||||
|
@ -19,7 +19,10 @@
|
|||||||
* MA 02110-1301 USA
|
* MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ntru_decrypt.h"
|
#include "decrypt.h"
|
||||||
|
|
||||||
|
#include <fmpz_poly.h>
|
||||||
|
#include <fmpz.h>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,48 +35,22 @@
|
|||||||
* the message
|
* the message
|
||||||
* @param priv_key_inv the inverse polynome to the private key
|
* @param priv_key_inv the inverse polynome to the private key
|
||||||
* @param context the ntru_context
|
* @param context the ntru_context
|
||||||
* @param decr_msg may contain the decrypted polynome at some point
|
* @param out the result polynom is written in here [out]
|
||||||
* @returns the decrypted polynome at the moment
|
|
||||||
*
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
pb_poly* ntru_decrypt(pb_poly *encr_msg, pb_poly *priv_key,
|
void ntru_decrypt_poly(
|
||||||
pb_poly *priv_key_inv, ntru_context *context, char ** decr_msg){
|
fmpz_poly_t encr_msg,
|
||||||
|
fmpz_poly_t priv_key,
|
||||||
|
fmpz_poly_t priv_key_inv,
|
||||||
|
fmpz_poly_t out,
|
||||||
|
ntru_context *ctx)
|
||||||
|
{
|
||||||
|
fmpz_poly_t a;
|
||||||
|
|
||||||
unsigned int q = context->q;
|
fmpz_poly_init(a);
|
||||||
unsigned int p = context->p;
|
fmpz_poly_zero(a);
|
||||||
unsigned int N = context->N;
|
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
pb_poly *a = build_polynom(NULL, N);
|
poly_starmultiply(priv_key, encr_msg, a, ctx, ctx->q);
|
||||||
pb_starmultiply(priv_key, encr_msg, a, context, q);
|
fmpz_poly_mod(a, ctx->q);
|
||||||
|
poly_starmultiply(a, priv_key_inv, out, ctx, ctx->p);
|
||||||
mp_int mp_q;
|
|
||||||
mp_int mp_qdiv2;
|
|
||||||
mp_int zero;
|
|
||||||
|
|
||||||
init_integer(&mp_q);
|
|
||||||
init_integer(&mp_qdiv2);
|
|
||||||
init_integer(&zero);
|
|
||||||
|
|
||||||
MP_SET_INT(&mp_q, q);
|
|
||||||
mp_div_2(&mp_q, &mp_qdiv2);
|
|
||||||
mp_zero(&zero);
|
|
||||||
|
|
||||||
for(i = 0; i < N; i++){
|
|
||||||
if(mp_cmp(&(a->terms[i]),&zero) == MP_LT) {
|
|
||||||
mp_add((&a->terms[i]),&mp_q,(&a->terms[i]));
|
|
||||||
}
|
|
||||||
if(mp_cmp(&(a->terms[i]), &mp_qdiv2) == MP_GT) {
|
|
||||||
mp_sub((&a->terms[i]),&mp_q,(&a->terms[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pb_poly *d = build_polynom(NULL, N);
|
|
||||||
|
|
||||||
pb_starmultiply(a, priv_key_inv, d, context, p);
|
|
||||||
|
|
||||||
pb_normalize(d,-1,1,context);
|
|
||||||
|
|
||||||
return d;
|
|
||||||
}
|
}
|
@ -25,10 +25,16 @@
|
|||||||
#include "poly.h"
|
#include "poly.h"
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
|
|
||||||
pb_poly* ntru_decrypt(pb_poly*,
|
#include <fmpz_poly.h>
|
||||||
pb_poly*,
|
#include <fmpz.h>
|
||||||
pb_poly*,
|
|
||||||
ntru_context*,
|
|
||||||
char**);
|
void ntru_decrypt_poly(
|
||||||
|
fmpz_poly_t encr_msg,
|
||||||
|
fmpz_poly_t priv_key,
|
||||||
|
fmpz_poly_t priv_key_inv,
|
||||||
|
fmpz_poly_t out,
|
||||||
|
ntru_context *ctx);
|
||||||
|
|
||||||
|
|
||||||
#endif /* NTRU_DECRYPT */
|
#endif /* NTRU_DECRYPT */
|
@ -19,9 +19,13 @@
|
|||||||
* MA 02110-1301 USA
|
* MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pqc_encrypt.h"
|
#include "encrypt.h"
|
||||||
|
|
||||||
/*
|
#include <fmpz_poly.h>
|
||||||
|
#include <fmpz.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
* encrypt the msg, using the math:
|
* encrypt the msg, using the math:
|
||||||
* e = (h ∗ r) + m (mod q)
|
* e = (h ∗ r) + m (mod q)
|
||||||
*
|
*
|
||||||
@ -35,31 +39,30 @@
|
|||||||
* @param rnd pb_poly* the random poly
|
* @param rnd pb_poly* the random poly
|
||||||
* @param msg pb_poly* the message to encrypt
|
* @param msg pb_poly* the message to encrypt
|
||||||
* @param pubKey pb_poly* the public key
|
* @param pubKey pb_poly* the public key
|
||||||
* @param out pb_poly* the output poly
|
* @param out pb_poly* the output poly [out]
|
||||||
*/
|
*/
|
||||||
void pb_encrypt(ntru_context *ctx,
|
void ntru_encrypt_poly(fmpz_poly_t rnd,
|
||||||
pb_poly *rnd,
|
fmpz_poly_t msg,
|
||||||
pb_poly *msg,
|
fmpz_poly_t pub_key,
|
||||||
pb_poly *pubKey,
|
fmpz_poly_t out,
|
||||||
pb_poly *out)
|
ntru_context *ctx)
|
||||||
{
|
{
|
||||||
mp_int *tmpOut;
|
poly_starmultiply(pub_key, rnd, out, ctx, ctx->q);
|
||||||
mp_int *tmpMsg;
|
|
||||||
mp_int mp_int_mod;
|
|
||||||
|
|
||||||
init_integer(&mp_int_mod);
|
fmpz_poly_zero(out);
|
||||||
MP_SET_INT(&mp_int_mod,(unsigned long)ctx->q);
|
|
||||||
|
|
||||||
pb_starmultiply(pubKey, rnd, out, ctx, ctx->q);
|
for(unsigned int i = 0; i <= ctx->N - 1; i++) {
|
||||||
|
fmpz_poly_t tmp_poly;
|
||||||
|
fmpz_t tmp_coeff;
|
||||||
|
fmpz *e_coeff_i = fmpz_poly_get_coeff_ptr(out, i),
|
||||||
|
*m_coeff_i = fmpz_poly_get_coeff_ptr(msg, i);
|
||||||
|
|
||||||
tmpOut = out->terms;
|
fmpz_poly_init(tmp_poly);
|
||||||
tmpMsg = msg->terms;
|
fmpz_init(tmp_coeff);
|
||||||
|
|
||||||
for(unsigned int i = 0; i <= ctx->N-1; i++) {
|
fmpz_add_n(tmp_coeff, e_coeff_i, m_coeff_i);
|
||||||
mp_add(tmpOut,tmpMsg,tmpOut);
|
fmpz_mod_ui(tmp_coeff, tmp_coeff, ctx->q);
|
||||||
mp_mod(tmpOut,&mp_int_mod,tmpOut);
|
|
||||||
|
|
||||||
tmpOut++;
|
fmpz_poly_set_coeff_fmpz(out, i, tmp_coeff);
|
||||||
tmpMsg++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -22,15 +22,19 @@
|
|||||||
#ifndef PQC_ENCRYPT_H
|
#ifndef PQC_ENCRYPT_H
|
||||||
#define PQC_ENCRYPT_H
|
#define PQC_ENCRYPT_H
|
||||||
|
|
||||||
#include <tommath.h>
|
|
||||||
#include <tompoly.h>
|
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
#include "poly.h"
|
#include "poly.h"
|
||||||
|
|
||||||
void pb_encrypt(ntru_context *ctx,
|
#include <fmpz_poly.h>
|
||||||
pb_poly *rnd,
|
#include <fmpz.h>
|
||||||
pb_poly *msg,
|
|
||||||
pb_poly *pubKey,
|
|
||||||
pb_poly *out);
|
void ntru_encrypt_poly(fmpz_poly_t rnd,
|
||||||
|
fmpz_poly_t msg,
|
||||||
|
fmpz_poly_t pubKey,
|
||||||
|
fmpz_poly_t out,
|
||||||
|
ntru_context *ctx);
|
||||||
|
|
||||||
|
|
||||||
#endif /* PQC_ENCRYPT_H */
|
#endif /* PQC_ENCRYPT_H */
|
756
src/poly.c
756
src/poly.c
@ -27,143 +27,80 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <tompoly.h>
|
|
||||||
#include <tommath.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <fmpz_poly.h>
|
||||||
|
#include <fmpz.h>
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* static declarations
|
* static declarations
|
||||||
*/
|
*/
|
||||||
static void pb_mod2_to_modq(pb_poly * const a,
|
static void poly_mod2_to_modq(fmpz_poly_t a,
|
||||||
pb_poly *Fq,
|
fmpz_poly_t Fq,
|
||||||
ntru_context *ctx);
|
ntru_context *ctx);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize a mp_int and check if this was successful, the
|
* Find the inverse polynomial modulo a power of 2,
|
||||||
* caller must free new_int.
|
* which is q.
|
||||||
*
|
*
|
||||||
* @param new_int a pointer to the mp_int you want to initialize
|
* @param a polynomial to invert
|
||||||
|
* @param Fq polynomial [out]
|
||||||
|
* @param ctx NTRU context
|
||||||
*/
|
*/
|
||||||
void init_integer(mp_int *new_int)
|
static void poly_mod2_to_modq(fmpz_poly_t a,
|
||||||
|
fmpz_poly_t Fq,
|
||||||
|
ntru_context *ctx)
|
||||||
{
|
{
|
||||||
int result;
|
int v = 2;
|
||||||
if ((result = mp_init(new_int)) != MP_OKAY) {
|
fmpz_poly_t poly_tmp, two;
|
||||||
NTRU_ABORT("Error initializing the number. %s",
|
|
||||||
mp_error_to_string(result));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
fmpz_poly_init(poly_tmp);
|
||||||
* Initialize one ore more mp_int and check if this was successful, the
|
fmpz_poly_zero(poly_tmp);
|
||||||
* caller must free new_int with mp_clear().
|
fmpz_poly_init(two);
|
||||||
*
|
fmpz_poly_set_coeff_ui(two, 0, 2);
|
||||||
* @param new_int a pointer to the mp_int you want to initialize
|
|
||||||
*/
|
|
||||||
void init_integers(mp_int *new_int, ...)
|
|
||||||
{
|
|
||||||
mp_int *next_mp;
|
|
||||||
va_list args;
|
|
||||||
|
|
||||||
next_mp = new_int;
|
while (v < (int)(ctx->q)) {
|
||||||
va_start(args, new_int);
|
v = v * 2;
|
||||||
while (next_mp != NULL) {
|
|
||||||
init_integer(next_mp);
|
|
||||||
next_mp = va_arg(args, mp_int*);
|
|
||||||
}
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
poly_starmultiply(a, Fq, poly_tmp, ctx, v);
|
||||||
* Initialize a Polynom with a pb_poly and a mp_int as characteristic.
|
fmpz_poly_sub(poly_tmp, two, poly_tmp);
|
||||||
* Checks if everything went fine. The caller must free new_poly
|
fmpz_poly_mod_unsigned(poly_tmp, v);
|
||||||
* with pb_clear().
|
poly_starmultiply(Fq, poly_tmp, Fq, ctx, v);
|
||||||
*
|
|
||||||
* @param new_poly the pb_poly you want to initialize
|
|
||||||
* @param chara the characteristic
|
|
||||||
*/
|
|
||||||
void init_polynom(pb_poly *new_poly, mp_int *chara)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
if ((result = pb_init(new_poly, chara)) != MP_OKAY) {
|
|
||||||
NTRU_ABORT("Error initializing the number. %s",
|
|
||||||
mp_error_to_string(result));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize a Polynom with a pb_poly and an mp_int as characteristic
|
|
||||||
* with size. Checks if everything went fine. The caller must free
|
|
||||||
* new_poly with pb_clear().
|
|
||||||
*
|
|
||||||
* @param new_poly the pb_poly you want to initialize
|
|
||||||
* @param chara the characteristic
|
|
||||||
* @param size the size of the polynomial
|
|
||||||
*/
|
|
||||||
void init_polynom_size(pb_poly *new_poly, mp_int *chara, size_t size)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
if ((result = pb_init_size(new_poly, chara, size)) != MP_OKAY) {
|
|
||||||
NTRU_ABORT("Error initializing the number. %s",
|
|
||||||
mp_error_to_string(result));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmpz_poly_clear(poly_tmp);
|
||||||
|
fmpz_poly_clear(two);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes and builds a polynomial with the
|
* Initializes and builds a polynomial with the
|
||||||
* coefficient values of c[] of size len within NTRU
|
* coefficient values of c[] of size len within NTRU
|
||||||
* context ctx and returns a newly allocated polynomial
|
* context ctx and returns a newly allocated polynomial
|
||||||
* pointer which is not clamped.
|
* pointer which is not clamped. For an empty polynom,
|
||||||
*
|
* both parameters can be NULL/0.
|
||||||
* If you want to fill a polyonmial of length 11 with zeros,
|
|
||||||
* call build_polynom(NULL, 11).
|
|
||||||
*
|
*
|
||||||
* @param c array of polynomial coefficients, can be NULL
|
* @param c array of polynomial coefficients, can be NULL
|
||||||
* @param len size of the coefficient array, can be 0
|
* @param len size of the coefficient array, can be 0
|
||||||
* @param ctx NTRU context
|
|
||||||
* @return newly allocated polynomial pointer, must be freed
|
* @return newly allocated polynomial pointer, must be freed
|
||||||
* with delete_polynom()
|
* with fmpz_poly_clear()
|
||||||
*/
|
*/
|
||||||
pb_poly *build_polynom(int const * const c,
|
fmpz_poly_t *poly_new(int const * const c,
|
||||||
const size_t len)
|
const size_t len)
|
||||||
{
|
{
|
||||||
pb_poly *new_poly;
|
fmpz_poly_t *new_poly = ntru_malloc(sizeof(*new_poly));
|
||||||
mp_int chara;
|
|
||||||
|
|
||||||
new_poly = ntru_malloc(sizeof(*new_poly));
|
fmpz_poly_init(*new_poly);
|
||||||
init_integer(&chara);
|
|
||||||
init_polynom_size(new_poly, &chara, len);
|
|
||||||
mp_clear(&chara);
|
|
||||||
|
|
||||||
/* fill the polynom if c is not NULL */
|
for (unsigned int i = 0; i < len; i++)
|
||||||
if (c) {
|
fmpz_poly_set_coeff_si(*new_poly, i, c[i]);
|
||||||
for (unsigned int i = 0; i < len; i++)
|
|
||||||
MP_SET_INT(&(new_poly->terms[i]), c[i]);
|
|
||||||
} else { /* fill with 0 */
|
|
||||||
for (unsigned int i = 0; i < len; i++)
|
|
||||||
MP_SET(&(new_poly->terms[i]), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
new_poly->used = len;
|
|
||||||
|
|
||||||
return new_poly;
|
return new_poly;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets all the polynomial coefficients to +0.
|
|
||||||
*
|
|
||||||
* @param poly the polynomial
|
|
||||||
* @param len the length of the polynomial
|
|
||||||
*/
|
|
||||||
void erase_polynom(pb_poly *poly, size_t len)
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < len ; i++) {
|
|
||||||
MP_SET(&(poly->terms[i]), 0);
|
|
||||||
mp_abs(&(poly->terms[i]), &(poly->terms[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This deletes the internal structure of a polynomial,
|
* This deletes the internal structure of a polynomial,
|
||||||
* and frees the pointer. Don't call this on stack variables,
|
* and frees the pointer. Don't call this on stack variables,
|
||||||
@ -172,9 +109,9 @@ void erase_polynom(pb_poly *poly, size_t len)
|
|||||||
*
|
*
|
||||||
* @param poly the polynomial to delete
|
* @param poly the polynomial to delete
|
||||||
*/
|
*/
|
||||||
void delete_polynom(pb_poly *poly)
|
void poly_delete(fmpz_poly_t *poly)
|
||||||
{
|
{
|
||||||
pb_clear(poly);
|
fmpz_poly_clear(*poly);
|
||||||
free(poly);
|
free(poly);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,20 +125,117 @@ void delete_polynom(pb_poly *poly)
|
|||||||
* @param poly the polynomial to delete
|
* @param poly the polynomial to delete
|
||||||
* @param ... follow up polynomials
|
* @param ... follow up polynomials
|
||||||
*/
|
*/
|
||||||
void delete_polynom_multi(pb_poly *poly, ...)
|
void poly_delete_all(fmpz_poly_t *poly, ...)
|
||||||
{
|
{
|
||||||
pb_poly *next_poly;
|
fmpz_poly_t *next_poly;
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
next_poly = poly;
|
next_poly = poly;
|
||||||
va_start(args, poly);
|
va_start(args, poly);
|
||||||
while (next_poly != NULL) {
|
while (next_poly != NULL) {
|
||||||
delete_polynom(next_poly);
|
poly_delete(next_poly);
|
||||||
next_poly = va_arg(args, pb_poly*);
|
next_poly = va_arg(args, fmpz_poly_t*);
|
||||||
}
|
}
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls fmpz_poly_get_nmod_poly() and
|
||||||
|
* fmpz_poly_set_nmod_poly_unsigned() in a row,
|
||||||
|
* so we don't have to deal with the intermediate
|
||||||
|
* nmod_poly_t type if we don't need it.
|
||||||
|
*
|
||||||
|
* @param a the polynom to apply the modulus to
|
||||||
|
* @param mod the modulus
|
||||||
|
*/
|
||||||
|
void fmpz_poly_mod_unsigned(fmpz_poly_t a,
|
||||||
|
unsigned int mod)
|
||||||
|
{
|
||||||
|
nmod_poly_t nmod_tmp;
|
||||||
|
|
||||||
|
nmod_poly_init(nmod_tmp, mod);
|
||||||
|
|
||||||
|
fmpz_poly_get_nmod_poly(nmod_tmp, a);
|
||||||
|
fmpz_poly_set_nmod_poly_unsigned(a, nmod_tmp);
|
||||||
|
|
||||||
|
nmod_poly_clear(nmod_tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls fmpz_poly_get_nmod_poly() and
|
||||||
|
* fmpz_poly_set_nmod_poly() in a row,
|
||||||
|
* so we don't have to deal with the intermediate
|
||||||
|
* nmod_poly_t type if we don't need it.
|
||||||
|
*
|
||||||
|
* @param a the polynom to apply the modulus to
|
||||||
|
* @param mod the modulus
|
||||||
|
*/
|
||||||
|
void fmpz_poly_mod(fmpz_poly_t a,
|
||||||
|
unsigned int mod)
|
||||||
|
{
|
||||||
|
nmod_poly_t nmod_tmp;
|
||||||
|
|
||||||
|
nmod_poly_init(nmod_tmp, mod);
|
||||||
|
|
||||||
|
fmpz_poly_get_nmod_poly(nmod_tmp, a);
|
||||||
|
fmpz_poly_set_nmod_poly(a, nmod_tmp);
|
||||||
|
|
||||||
|
nmod_poly_clear(nmod_tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The same as fmpz_poly_set_coeff_fmpz() except that it
|
||||||
|
* will take care of null-pointer coefficients and use
|
||||||
|
* fmpz_poly_set_coeff_si() in that case.
|
||||||
|
*
|
||||||
|
* @param poly the polynom we want to change a coefficient of
|
||||||
|
* @param n the coefficient we want to set
|
||||||
|
* @param x the value to assign to the coefficient
|
||||||
|
*/
|
||||||
|
void fmpz_poly_set_coeff_fmpz_n(fmpz_poly_t poly, slong n,
|
||||||
|
const fmpz_t x)
|
||||||
|
{
|
||||||
|
if (x)
|
||||||
|
fmpz_poly_set_coeff_fmpz(poly, n, x);
|
||||||
|
else
|
||||||
|
fmpz_poly_set_coeff_si(poly, n, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper around fmpz_invmod() where we convert
|
||||||
|
* mod to an fmpz_t implicitly.
|
||||||
|
*
|
||||||
|
* @param f result [out]
|
||||||
|
* @param g the inverse
|
||||||
|
* @param mod the modulo
|
||||||
|
*/
|
||||||
|
int fmpz_invmod_ui(fmpz_t f, const fmpz_t g, unsigned int mod)
|
||||||
|
{
|
||||||
|
fmpz_t modulus;
|
||||||
|
|
||||||
|
fmpz_init_set_ui(modulus, mod);
|
||||||
|
|
||||||
|
return fmpz_invmod(f, g, modulus);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The same as fmpz_add() except that it handles NULL
|
||||||
|
* pointer for g and h.
|
||||||
|
*/
|
||||||
|
void fmpz_add_n(fmpz_t f, const fmpz_t g, const fmpz_t h)
|
||||||
|
{
|
||||||
|
if (!g && !h) {
|
||||||
|
fmpz_zero(f);
|
||||||
|
} else {
|
||||||
|
if (!g && h)
|
||||||
|
fmpz_add_ui(f, h, 0);
|
||||||
|
else if (g && !h)
|
||||||
|
fmpz_add_ui(f, g, 0);
|
||||||
|
else
|
||||||
|
fmpz_add(f, g, h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starmultiplication, as follows:
|
* Starmultiplication, as follows:
|
||||||
* c = a * b mod (x^N − 1)
|
* c = a * b mod (x^N − 1)
|
||||||
@ -212,425 +246,359 @@ void delete_polynom_multi(pb_poly *poly, ...)
|
|||||||
* @param ctx NTRU context
|
* @param ctx NTRU context
|
||||||
* @param modulus whether we use p or q
|
* @param modulus whether we use p or q
|
||||||
*/
|
*/
|
||||||
void pb_starmultiply(pb_poly *a,
|
void poly_starmultiply(fmpz_poly_t a,
|
||||||
pb_poly *b,
|
fmpz_poly_t b,
|
||||||
pb_poly *c,
|
fmpz_poly_t c,
|
||||||
ntru_context *ctx,
|
ntru_context *ctx,
|
||||||
unsigned int modulus)
|
unsigned int modulus)
|
||||||
{
|
{
|
||||||
pb_poly *a_tmp;
|
fmpz_poly_t a_tmp;
|
||||||
mp_int mp_modulus;
|
fmpz_t c_coeff_k;
|
||||||
|
|
||||||
init_integer(&mp_modulus);
|
fmpz_poly_init(a_tmp);
|
||||||
MP_SET_INT(&mp_modulus, (unsigned long)(modulus));
|
fmpz_init(c_coeff_k);
|
||||||
|
|
||||||
/* avoid side effects */
|
/* avoid side effects */
|
||||||
a_tmp = build_polynom(NULL, ctx->N);
|
fmpz_poly_set(a_tmp, a);
|
||||||
PB_COPY(a, a_tmp);
|
fmpz_poly_zero(c);
|
||||||
erase_polynom(c, ctx->N);
|
|
||||||
|
|
||||||
for (int k = ctx->N - 1; k >= 0; k--) {
|
for (int k = ctx->N - 1; k >= 0; k--) {
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
j = k + 1;
|
j = k + 1;
|
||||||
|
|
||||||
|
fmpz_set_si(c_coeff_k, 0);
|
||||||
|
|
||||||
for (int i = ctx->N - 1; i >= 0; i--) {
|
for (int i = ctx->N - 1; i >= 0; i--) {
|
||||||
|
fmpz *a_tmp_coeff_i,
|
||||||
|
*b_coeff_j;
|
||||||
|
|
||||||
if (j == (int)(ctx->N))
|
if (j == (int)(ctx->N))
|
||||||
j = 0;
|
j = 0;
|
||||||
if (mp_cmp_d(&(a_tmp->terms[i]), 0) != MP_EQ &&
|
|
||||||
mp_cmp_d(&(b->terms[j]), 0) != MP_EQ) {
|
|
||||||
mp_int mp_tmp;
|
|
||||||
|
|
||||||
init_integer(&mp_tmp);
|
a_tmp_coeff_i = fmpz_poly_get_coeff_ptr(a_tmp, i);
|
||||||
|
b_coeff_j = fmpz_poly_get_coeff_ptr(b, j);
|
||||||
|
|
||||||
MP_MUL(&(a_tmp->terms[i]), &(b->terms[j]), &mp_tmp);
|
if (a_tmp_coeff_i && fmpz_cmp_si(a_tmp_coeff_i, 0) &&
|
||||||
MP_ADD(&(c->terms[k]), &mp_tmp, &(c->terms[k]));
|
b_coeff_j && fmpz_cmp_si(b_coeff_j, 0)) {
|
||||||
MP_DIV(&(c->terms[k]), &mp_modulus, NULL, &(c->terms[k]));
|
fmpz_t fmpz_tmp;
|
||||||
|
|
||||||
mp_clear(&mp_tmp);
|
fmpz_init(fmpz_tmp);
|
||||||
|
|
||||||
|
fmpz_mul(fmpz_tmp, a_tmp_coeff_i, b_coeff_j);
|
||||||
|
fmpz_add(fmpz_tmp, fmpz_tmp, c_coeff_k);
|
||||||
|
fmpz_mod_ui(c_coeff_k, fmpz_tmp, modulus);
|
||||||
|
|
||||||
|
fmpz_poly_set_coeff_fmpz(c, k, c_coeff_k);
|
||||||
|
|
||||||
|
fmpz_clear(fmpz_tmp);
|
||||||
}
|
}
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
|
fmpz_clear(c_coeff_k);
|
||||||
}
|
}
|
||||||
mp_clear(&mp_modulus);
|
|
||||||
delete_polynom(a_tmp);
|
fmpz_poly_clear(a_tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate c = a * b where c and a are polynomials
|
* Compute the inverse of a polynomial in modulo a power of 2,
|
||||||
* and b is an mp_int.
|
* which is q. This is based off the pseudo-code for "Inversion
|
||||||
*
|
* in (Z/2Z)[X](X^N - 1)" and "Inversion in (Z/p^r Z)[X](X^N - 1)".
|
||||||
* @param a polynom
|
* See NTRU Cryptosystems Tech Report #014 "Almost Inverses
|
||||||
* @param b mp_int
|
* and Fast NTRU Key Creation."
|
||||||
* @param c polynom [out]
|
|
||||||
* @return error code of pb_mul()
|
|
||||||
*/
|
|
||||||
int pb_mp_mul(pb_poly *a, mp_int *b, pb_poly *c)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
|
|
||||||
pb_poly *b_poly = build_polynom(NULL, 1);
|
|
||||||
MP_COPY(b, &(b_poly->terms[0]));
|
|
||||||
printf("u converted to poly: "); draw_polynom(b_poly);
|
|
||||||
result = pb_mul(a, b_poly, c);
|
|
||||||
|
|
||||||
delete_polynom(b_poly);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* c = a XOR b
|
|
||||||
*
|
|
||||||
* @param a polynom (is allowed to be the same as param c)
|
|
||||||
* @param b polynom
|
|
||||||
* @param c polynom [out]
|
|
||||||
* @param len max size of the polynoms, make sure all are
|
|
||||||
* properly allocated
|
|
||||||
*/
|
|
||||||
void pb_xor(pb_poly *a,
|
|
||||||
pb_poly *b,
|
|
||||||
pb_poly *c,
|
|
||||||
const size_t len)
|
|
||||||
{
|
|
||||||
for (unsigned int i = 0; i < len; i++)
|
|
||||||
MP_XOR(&(a->terms[i]), &(b->terms[i]), &(c->terms[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the degree of the polynomial.
|
|
||||||
*
|
|
||||||
* @param poly the polynomial
|
|
||||||
* @return the degree, -1 if polynom is empty
|
|
||||||
*/
|
|
||||||
int get_degree(pb_poly const * const poly)
|
|
||||||
{
|
|
||||||
int count = -1;
|
|
||||||
|
|
||||||
for (int i = 0; i < poly->alloc; i++)
|
|
||||||
if (mp_iszero(&(poly->terms[i])) == MP_NO)
|
|
||||||
count = i;
|
|
||||||
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find the inverse polynomial modulo a power of 2,
|
|
||||||
* which is q.
|
|
||||||
*
|
|
||||||
* @param a polynomial to invert
|
|
||||||
* @param Fq polynomial [out]
|
|
||||||
* @param ctx NTRU context
|
|
||||||
*/
|
|
||||||
static void pb_mod2_to_modq(pb_poly * const a,
|
|
||||||
pb_poly *Fq,
|
|
||||||
ntru_context *ctx)
|
|
||||||
{
|
|
||||||
int v = 2;
|
|
||||||
|
|
||||||
while (v < (int)(ctx->q)) {
|
|
||||||
pb_poly *pb_tmp,
|
|
||||||
*pb_tmp2;
|
|
||||||
mp_int tmp_v;
|
|
||||||
pb_tmp = build_polynom(NULL, ctx->N);
|
|
||||||
v = v * 2;
|
|
||||||
init_integer(&tmp_v);
|
|
||||||
MP_SET_INT(&tmp_v, v);
|
|
||||||
pb_tmp2 = build_polynom(NULL, ctx->N);
|
|
||||||
MP_SET_INT(&(pb_tmp2->terms[0]), 2);
|
|
||||||
|
|
||||||
pb_starmultiply(a, Fq, pb_tmp, ctx, v);
|
|
||||||
PB_SUB(pb_tmp2, pb_tmp, pb_tmp);
|
|
||||||
PB_MOD(pb_tmp, &tmp_v, pb_tmp, ctx->N);
|
|
||||||
pb_starmultiply(Fq, pb_tmp, Fq, ctx, v);
|
|
||||||
|
|
||||||
mp_clear(&tmp_v);
|
|
||||||
delete_polynom_multi(pb_tmp, pb_tmp2, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invert the polynomial a modulo q.
|
|
||||||
*
|
*
|
||||||
* @param a polynomial to invert (is allowed to be the same as param Fq)
|
* @param a polynomial to invert (is allowed to be the same as param Fq)
|
||||||
* @param Fq polynomial [out]
|
* @param Fq polynomial [out]
|
||||||
* @param ctx NTRU context
|
* @param ctx NTRU context
|
||||||
* @return true if invertible, false if not
|
* @return true if invertible, false if not
|
||||||
*/
|
*/
|
||||||
bool pb_inverse_poly_q(pb_poly * const a,
|
bool poly_inverse_poly_q(fmpz_poly_t a,
|
||||||
pb_poly *Fq,
|
fmpz_poly_t Fq,
|
||||||
ntru_context *ctx)
|
ntru_context *ctx)
|
||||||
{
|
{
|
||||||
|
bool retval = true;
|
||||||
int k = 0,
|
int k = 0,
|
||||||
j = 0;
|
j = 0;
|
||||||
pb_poly *a_tmp, *b, *c, *f, *g;
|
fmpz *b_last;
|
||||||
mp_int mp_modulus;
|
fmpz_poly_t a_tmp,
|
||||||
|
b,
|
||||||
|
c,
|
||||||
|
f,
|
||||||
|
g;
|
||||||
|
|
||||||
/* general initialization of temp variables */
|
/* general initialization of temp variables */
|
||||||
init_integer(&mp_modulus);
|
fmpz_poly_init(b);
|
||||||
MP_SET_INT(&mp_modulus, (unsigned long)(ctx->q));
|
fmpz_poly_set_coeff_ui(b, 0, 1);
|
||||||
b = build_polynom(NULL, ctx->N + 1);
|
fmpz_poly_init(c);
|
||||||
MP_SET(&(b->terms[0]), 1);
|
fmpz_poly_init(f);
|
||||||
c = build_polynom(NULL, ctx->N + 1);
|
fmpz_poly_set(f, a);
|
||||||
f = build_polynom(NULL, ctx->N + 1);
|
|
||||||
PB_COPY(a, f);
|
|
||||||
|
|
||||||
/* set g(x) = x^N − 1 */
|
/* set g(x) = x^N − 1 */
|
||||||
g = build_polynom(NULL, ctx->N + 1);
|
fmpz_poly_init(g);
|
||||||
MP_SET(&(g->terms[0]), 1);
|
fmpz_poly_set_coeff_si(g, 0, -1);
|
||||||
MP_SET(&(g->terms[ctx->N]), 1);
|
fmpz_poly_set_coeff_si(g, ctx->N, 1);
|
||||||
|
|
||||||
/* avoid side effects */
|
/* avoid side effects */
|
||||||
a_tmp = build_polynom(NULL, ctx->N);
|
fmpz_poly_init(a_tmp);
|
||||||
PB_COPY(a, a_tmp);
|
fmpz_poly_set(a_tmp, a);
|
||||||
erase_polynom(Fq, ctx->N);
|
fmpz_poly_zero(Fq);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
while (mp_cmp_d(&(f->terms[0]), 0) == MP_EQ) {
|
while (fmpz_is_zero(fmpz_poly_get_coeff_ptr(f, 0))) {
|
||||||
for (unsigned int i = 1; i <= ctx->N; i++) {
|
for (unsigned int i = 1; i <= ctx->N; i++) {
|
||||||
|
fmpz *f_coeff = fmpz_poly_get_coeff_ptr(f, i);
|
||||||
|
fmpz *c_coeff = fmpz_poly_get_coeff_ptr(c, ctx->N - i);
|
||||||
|
|
||||||
/* f(x) = f(x) / x */
|
/* f(x) = f(x) / x */
|
||||||
MP_COPY(&(f->terms[i]), &(f->terms[i - 1]));
|
fmpz_poly_set_coeff_fmpz_n(f, i - 1,
|
||||||
|
f_coeff);
|
||||||
|
|
||||||
/* c(x) = c(x) * x */
|
/* c(x) = c(x) * x */
|
||||||
MP_COPY(&(c->terms[ctx->N - i]), &(c->terms[ctx->N + 1 - i]));
|
fmpz_poly_set_coeff_fmpz_n(c, ctx->N + 1 - i,
|
||||||
|
c_coeff);
|
||||||
}
|
}
|
||||||
MP_SET(&(f->terms[ctx->N]), 0);
|
|
||||||
MP_SET(&(c->terms[0]), 0);
|
fmpz_poly_set_coeff_si(f, ctx->N, 0);
|
||||||
|
fmpz_poly_set_coeff_si(c, 0, 0);
|
||||||
|
|
||||||
k++;
|
k++;
|
||||||
if (get_degree(f) == -1)
|
|
||||||
return false;
|
if (fmpz_poly_degree(f) == -1) {
|
||||||
|
retval = false;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_degree(f) == 0)
|
if (fmpz_poly_degree(f) == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (get_degree(f) < get_degree(g)) {
|
if (fmpz_poly_degree(f) < fmpz_poly_degree(g)) {
|
||||||
pb_exch(f, g);
|
fmpz_poly_swap(f, g);
|
||||||
pb_exch(b, c);
|
fmpz_poly_swap(b, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
pb_xor(f, g, f, ctx->N);
|
fmpz_poly_add(f, g, f);
|
||||||
pb_xor(b, c, b, ctx->N);
|
fmpz_poly_mod_unsigned(f, 2);
|
||||||
|
|
||||||
|
fmpz_poly_add(b, c, b);
|
||||||
|
fmpz_poly_mod_unsigned(b, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
k = k % ctx->N;
|
k = k % ctx->N;
|
||||||
|
|
||||||
if (mp_cmp_d(&(b->terms[ctx->N]), 0) != MP_EQ)
|
b_last = fmpz_poly_get_coeff_ptr(b, ctx->N);
|
||||||
return false;
|
if (b_last && fmpz_cmp_si(b_last, 0)) {
|
||||||
|
retval = false;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
/* Fq(x) = x^(N-k) * b(x) */
|
/* Fq(x) = x^(N-k) * b(x) */
|
||||||
for (int i = ctx->N - 1; i >= 0; i--) {
|
for (int i = ctx->N - 1; i >= 0; i--) {
|
||||||
|
fmpz *b_i;
|
||||||
|
|
||||||
j = i - k;
|
j = i - k;
|
||||||
|
|
||||||
if (j < 0)
|
if (j < 0)
|
||||||
j = j + ctx->N;
|
j = j + ctx->N;
|
||||||
MP_COPY(&(b->terms[i]), &(Fq->terms[j]));
|
|
||||||
|
b_i = fmpz_poly_get_coeff_ptr(b, i);
|
||||||
|
fmpz_poly_set_coeff_fmpz_n(Fq, j, b_i);
|
||||||
}
|
}
|
||||||
|
|
||||||
pb_mod2_to_modq(a_tmp, Fq, ctx);
|
poly_mod2_to_modq(a_tmp, Fq, ctx);
|
||||||
|
|
||||||
/* pull into positive space */
|
/* check if the f * Fq = 1 (mod p) condition holds true */
|
||||||
for (int i = ctx->N - 1; i >= 0; i--)
|
fmpz_poly_set(a_tmp, a);
|
||||||
if (mp_cmp_d(&(Fq->terms[i]), 0) == MP_LT)
|
poly_starmultiply(a_tmp, Fq, a_tmp, ctx, ctx->q);
|
||||||
MP_ADD(&(Fq->terms[i]), &mp_modulus, &(Fq->terms[i]));
|
if (!fmpz_poly_is_one(a_tmp))
|
||||||
|
retval = false;
|
||||||
|
|
||||||
delete_polynom_multi(a_tmp, b, c, f, g, NULL);
|
cleanup:
|
||||||
mp_clear(&mp_modulus);
|
fmpz_poly_clear(a_tmp);
|
||||||
|
fmpz_poly_clear(b);
|
||||||
|
fmpz_poly_clear(c);
|
||||||
|
fmpz_poly_clear(f);
|
||||||
|
fmpz_poly_clear(g);
|
||||||
|
|
||||||
/* TODO: check if the f * Fq = 1 (mod p) condition holds true */
|
if (!retval)
|
||||||
|
fmpz_poly_zero(Fq);
|
||||||
|
|
||||||
return true;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invert the polynomial a modulo p.
|
* Compute the inverse of a polynomial in (Z/pZ)[X]/(X^N - 1).
|
||||||
|
* See NTRU Cryptosystems Tech Report #014 "Almost Inverses
|
||||||
|
* and Fast NTRU Key Creation."
|
||||||
*
|
*
|
||||||
* @param a polynomial to invert
|
* @param a polynomial to invert
|
||||||
* @param Fq polynomial [out]
|
* @param Fq polynomial [out]
|
||||||
* @param ctx NTRU context
|
* @param ctx NTRU context
|
||||||
*/
|
*/
|
||||||
bool pb_inverse_poly_p(pb_poly *a,
|
bool poly_inverse_poly_p(fmpz_poly_t a,
|
||||||
pb_poly *Fp,
|
fmpz_poly_t Fp,
|
||||||
ntru_context *ctx)
|
ntru_context *ctx)
|
||||||
{
|
{
|
||||||
|
bool retval = true;
|
||||||
int k = 0,
|
int k = 0,
|
||||||
j = 0;
|
j = 0;
|
||||||
pb_poly *a_tmp, *b, *c, *f, *g;
|
fmpz *b_last;
|
||||||
mp_int mp_modulus;
|
fmpz_poly_t a_tmp,
|
||||||
|
b,
|
||||||
|
c,
|
||||||
|
f,
|
||||||
|
g;
|
||||||
|
|
||||||
/* general initialization of temp variables */
|
/* general initialization of temp variables */
|
||||||
init_integer(&mp_modulus);
|
fmpz_poly_init(b);
|
||||||
MP_SET_INT(&mp_modulus, (unsigned long)(ctx->p));
|
fmpz_poly_set_coeff_ui(b, 0, 1);
|
||||||
b = build_polynom(NULL, ctx->N + 1);
|
fmpz_poly_init(c);
|
||||||
MP_SET(&(b->terms[0]), 1);
|
fmpz_poly_init(f);
|
||||||
c = build_polynom(NULL, ctx->N + 1);
|
fmpz_poly_set(f, a);
|
||||||
f = build_polynom(NULL, ctx->N + 1);
|
|
||||||
PB_COPY(a, f);
|
|
||||||
|
|
||||||
/* set g(x) = x^N − 1 */
|
/* set g(x) = x^N − 1 */
|
||||||
g = build_polynom(NULL, ctx->N + 1);
|
fmpz_poly_init(g);
|
||||||
MP_SET_INT(&(g->terms[0]), -1);
|
fmpz_poly_set_coeff_si(g, 0, -1);
|
||||||
MP_SET(&(g->terms[ctx->N]), 1);
|
fmpz_poly_set_coeff_si(g, ctx->N, 1);
|
||||||
|
|
||||||
/* avoid side effects */
|
/* avoid side effects */
|
||||||
a_tmp = build_polynom(NULL, ctx->N);
|
fmpz_poly_init(a_tmp);
|
||||||
PB_COPY(a, a_tmp);
|
fmpz_poly_set(a_tmp, a);
|
||||||
erase_polynom(Fp, ctx->N);
|
fmpz_poly_zero(Fp);
|
||||||
|
|
||||||
printf("f: "); draw_polynom(f);
|
|
||||||
printf("g: "); draw_polynom(g);
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
while (mp_cmp_d(&(f->terms[0]), 0) == MP_EQ) {
|
while (fmpz_is_zero(fmpz_poly_get_coeff_ptr(f, 0))) {
|
||||||
for (unsigned int i = 1; i <= ctx->N; i++) {
|
for (unsigned int i = 1; i <= ctx->N; i++) {
|
||||||
|
fmpz *f_coeff_tmp = fmpz_poly_get_coeff_ptr(f, i);
|
||||||
|
fmpz *c_coeff_tmp = fmpz_poly_get_coeff_ptr(c, ctx->N - i);
|
||||||
|
|
||||||
/* f(x) = f(x) / x */
|
/* f(x) = f(x) / x */
|
||||||
MP_COPY(&(f->terms[i]), &(f->terms[i - 1]));
|
fmpz_poly_set_coeff_fmpz_n(f, i - 1,
|
||||||
|
f_coeff_tmp);
|
||||||
|
|
||||||
/* c(x) = c(x) * x */
|
/* c(x) = c(x) * x */
|
||||||
MP_COPY(&(c->terms[ctx->N - i]), &(c->terms[ctx->N + 1 - i]));
|
fmpz_poly_set_coeff_fmpz_n(c, ctx->N + 1 - i,
|
||||||
|
c_coeff_tmp);
|
||||||
}
|
}
|
||||||
MP_SET(&(f->terms[ctx->N]), 0);
|
|
||||||
MP_SET(&(c->terms[0]), 0);
|
fmpz_poly_set_coeff_si(f, ctx->N, 0);
|
||||||
|
fmpz_poly_set_coeff_si(c, 0, 0);
|
||||||
|
|
||||||
k++;
|
k++;
|
||||||
|
|
||||||
|
if (fmpz_poly_degree(f) == -1) {
|
||||||
|
retval = false;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_degree(f) == 0)
|
if (fmpz_poly_degree(f) == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (get_degree(f) < get_degree(g)) {
|
if (fmpz_poly_degree(f) < fmpz_poly_degree(g)) {
|
||||||
/* exchange f and g and exchange b and c */
|
/* exchange f and g and exchange b and c */
|
||||||
pb_exch(f, g);
|
fmpz_poly_swap(f, g);
|
||||||
pb_exch(b, c);
|
fmpz_poly_swap(b, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
pb_poly *c_tmp, *g_tmp;
|
fmpz_poly_t c_tmp,
|
||||||
mp_int u, mp_tmp;
|
g_tmp;
|
||||||
|
fmpz_t u,
|
||||||
|
mp_tmp;
|
||||||
|
|
||||||
init_integers(&u, &mp_tmp, NULL);
|
fmpz_init(u);
|
||||||
g_tmp = build_polynom(NULL, ctx->N + 1);
|
fmpz_zero(u);
|
||||||
PB_COPY(g, g_tmp);
|
|
||||||
c_tmp = build_polynom(NULL, ctx->N + 1);
|
|
||||||
PB_COPY(c, c_tmp);
|
|
||||||
|
|
||||||
/* u = f[0] * g[0]^(-1) mod p
|
fmpz_init_set(mp_tmp, fmpz_poly_get_coeff_ptr(f, 0));
|
||||||
* = (f[0] mod p) * (g[0] inverse mod p) mod p */
|
|
||||||
MP_COPY(&(f->terms[0]), &mp_tmp);
|
fmpz_poly_init(g_tmp);
|
||||||
MP_INVMOD(&(g->terms[0]), &mp_modulus, &u);
|
fmpz_poly_set(g_tmp, g);
|
||||||
MP_MOD(&mp_tmp, &mp_modulus, &mp_tmp);
|
|
||||||
MP_MUL(&u, &mp_tmp, &u);
|
fmpz_poly_init(c_tmp);
|
||||||
MP_MOD(&u, &mp_modulus, &u);
|
fmpz_poly_set(c_tmp, c);
|
||||||
|
|
||||||
|
/* u = f[0] * g[0]^(-1) mod p */
|
||||||
|
/* = (f[0] mod p) * (g[0] inverse mod p) mod p */
|
||||||
|
fmpz_invmod_ui(u,
|
||||||
|
fmpz_poly_get_coeff_ptr(g, 0),
|
||||||
|
ctx->p);
|
||||||
|
fmpz_mod_ui(mp_tmp, mp_tmp, ctx->p);
|
||||||
|
fmpz_mul(u, mp_tmp, u);
|
||||||
|
fmpz_mod_ui(u, u, ctx->p);
|
||||||
|
|
||||||
/* f = f - u * g mod p */
|
/* f = f - u * g mod p */
|
||||||
PB_MP_MUL(g_tmp, &u, g_tmp);
|
fmpz_poly_scalar_mul_fmpz(g_tmp, g_tmp, u);
|
||||||
PB_SUB(f, g_tmp, f);
|
fmpz_poly_sub(f, g_tmp, f);
|
||||||
PB_MOD(f, &mp_modulus, f, ctx->N + 1);
|
fmpz_poly_mod_unsigned(f, ctx->p);
|
||||||
|
|
||||||
/* b = b - u * c mod p */
|
/* b = b - u * c mod p */
|
||||||
PB_MP_MUL(c_tmp, &u, c_tmp);
|
fmpz_poly_scalar_mul_fmpz(c_tmp, c_tmp, u);
|
||||||
PB_SUB(b, c_tmp, b);
|
fmpz_poly_sub(b, c_tmp, b);
|
||||||
PB_MOD(b, &mp_modulus, b, ctx->N + 1);
|
fmpz_poly_mod_unsigned(b, ctx->p);
|
||||||
|
|
||||||
mp_clear(&mp_tmp);
|
fmpz_clear(u);
|
||||||
delete_polynom_multi(c_tmp, g_tmp, NULL);
|
fmpz_poly_clear(g_tmp);
|
||||||
|
fmpz_poly_clear(c_tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
k = k % ctx->N;
|
k = k % ctx->N;
|
||||||
|
|
||||||
|
b_last = fmpz_poly_get_coeff_ptr(b, ctx->N);
|
||||||
|
if (b_last && fmpz_cmp_si(b_last, 0)) {
|
||||||
|
retval = false;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
/* Fp(x) = x^(N-k) * b(x) */
|
/* Fp(x) = x^(N-k) * b(x) */
|
||||||
for (int i = ctx->N - 1; i >= 0; i--) {
|
for (int i = ctx->N - 1; i >= 0; i--) {
|
||||||
|
fmpz *b_i;
|
||||||
|
|
||||||
/* b(X) = f[0]^(-1) * b(X) (mod p) */
|
/* b(X) = f[0]^(-1) * b(X) (mod p) */
|
||||||
{
|
{
|
||||||
pb_poly *poly_tmp;
|
fmpz_t mp_tmp;
|
||||||
|
|
||||||
poly_tmp = build_polynom(NULL, 1);
|
fmpz_init(mp_tmp);
|
||||||
|
|
||||||
MP_INVMOD(&(f->terms[0]), &mp_modulus, &(poly_tmp->terms[0]));
|
fmpz_invmod_ui(mp_tmp,
|
||||||
MP_MOD(&(b->terms[i]), &mp_modulus, &(b->terms[i]));
|
fmpz_poly_get_coeff_ptr(f, 0),
|
||||||
MP_MUL(&(b->terms[i]), &(poly_tmp->terms[0]), &(b->terms[i]));
|
ctx->p);
|
||||||
|
|
||||||
delete_polynom(poly_tmp);
|
if (fmpz_poly_get_coeff_ptr(b, i)) {
|
||||||
|
fmpz_mul(fmpz_poly_get_coeff_ptr(b, i),
|
||||||
|
fmpz_poly_get_coeff_ptr(b, i),
|
||||||
|
mp_tmp);
|
||||||
|
fmpz_mod_ui(fmpz_poly_get_coeff_ptr(b, i),
|
||||||
|
fmpz_poly_get_coeff_ptr(b, i),
|
||||||
|
ctx->p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
j = i - k;
|
j = i - k;
|
||||||
if (j < 0)
|
if (j < 0)
|
||||||
j = j + ctx->N;
|
j = j + ctx->N;
|
||||||
MP_COPY(&(b->terms[i]), &(Fp->terms[j]));
|
|
||||||
|
|
||||||
/* delete_polynom(f_tmp); */
|
b_i = fmpz_poly_get_coeff_ptr(b, i);
|
||||||
|
fmpz_poly_set_coeff_fmpz_n(Fp, j, b_i);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pull into positive space */
|
/* check if the f * Fq = 1 (mod p) condition holds true */
|
||||||
for (int i = ctx->N - 1; i >= 0; i--)
|
fmpz_poly_set(a_tmp, a);
|
||||||
if (mp_cmp_d(&(Fp->terms[i]), 0) == MP_LT)
|
poly_starmultiply(a_tmp, Fp, a_tmp, ctx, ctx->p);
|
||||||
MP_ADD(&(Fp->terms[i]), &mp_modulus, &(Fp->terms[i]));
|
if (!fmpz_poly_is_one(a_tmp))
|
||||||
|
retval = false;
|
||||||
|
|
||||||
mp_clear(&mp_modulus);
|
cleanup:
|
||||||
delete_polynom_multi(a_tmp, b, c, f, g, NULL);
|
fmpz_poly_clear(a_tmp);
|
||||||
|
fmpz_poly_clear(b);
|
||||||
|
fmpz_poly_clear(c);
|
||||||
|
fmpz_poly_clear(f);
|
||||||
|
fmpz_poly_clear(g);
|
||||||
|
|
||||||
/* TODO: check if the f * Fq = 1 (mod p) condition holds true */
|
if (!retval)
|
||||||
|
fmpz_poly_zero(Fp);
|
||||||
|
|
||||||
return true;
|
return retval;
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Print the polynomial in a human readable format to stdout.
|
|
||||||
*
|
|
||||||
* @param poly to draw
|
|
||||||
*/
|
|
||||||
void draw_polynom(pb_poly * const poly)
|
|
||||||
{
|
|
||||||
int x;
|
|
||||||
char buf[8192];
|
|
||||||
|
|
||||||
if (poly->used == 0) {
|
|
||||||
printf("0");
|
|
||||||
} else {
|
|
||||||
for (x = poly->used - 1; x >= 0; x--) {
|
|
||||||
if (mp_iszero(&(poly->terms[x])) == MP_YES)
|
|
||||||
continue;
|
|
||||||
mp_toradix(&(poly->terms[x]), buf, 10);
|
|
||||||
if ((x != poly->used - 1) && poly->terms[x].sign == MP_ZPOS) {
|
|
||||||
printf("+");
|
|
||||||
}
|
|
||||||
printf(" %sx^%d ", buf, x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mp_iszero(&(poly->characteristic)) == MP_NO) {
|
|
||||||
mp_toradix(&(poly->characteristic), buf, 10);
|
|
||||||
printf(" (mod %s)", buf);
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void pb_normalize(pb_poly *poly, int low_border, int high_border, ntru_context *ctx){
|
|
||||||
unsigned int p = ctx->p;
|
|
||||||
unsigned int N = ctx->N;
|
|
||||||
|
|
||||||
mp_int mp_p;
|
|
||||||
mp_int mp_low_border;
|
|
||||||
mp_int mp_high_border;
|
|
||||||
|
|
||||||
init_integer(&mp_low_border);
|
|
||||||
init_integer(&mp_high_border);
|
|
||||||
init_integer(&mp_p);
|
|
||||||
|
|
||||||
MP_SET_INT(&mp_p, p);
|
|
||||||
MP_SET_INT(&mp_low_border,(unsigned long)abs(low_border));
|
|
||||||
mp_neg(&mp_low_border,&mp_low_border);
|
|
||||||
MP_SET_INT(&mp_high_border,high_border);
|
|
||||||
|
|
||||||
|
|
||||||
unsigned int i;
|
|
||||||
for(i = 0; i < N; i++){
|
|
||||||
if(mp_cmp(&(poly->terms[i]),&mp_low_border) == MP_LT) {
|
|
||||||
mp_add(&(poly->terms[i]),&mp_p,&(poly->terms[i]));
|
|
||||||
} else if(mp_cmp(&(poly->terms[i]),&mp_high_border) == MP_GT) {
|
|
||||||
mp_sub(&(poly->terms[i]),&mp_p,&(poly->terms[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw_mp_int(mp_int *digit) {
|
|
||||||
char buf[8192];
|
|
||||||
mp_toradix(digit, buf, 10);
|
|
||||||
printf("%s\n",buf);
|
|
||||||
}
|
}
|
||||||
|
202
src/poly.h
202
src/poly.h
@ -26,199 +26,49 @@
|
|||||||
#include "context.h"
|
#include "context.h"
|
||||||
#include "err.h"
|
#include "err.h"
|
||||||
|
|
||||||
#include <tompoly.h>
|
|
||||||
#include <tommath.h>
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <fmpz_poly.h>
|
||||||
#define MP_SET(...) mp_set(__VA_ARGS__)
|
|
||||||
|
|
||||||
#define MP_SET_INT(a, b) \
|
|
||||||
{ \
|
|
||||||
int result; \
|
|
||||||
if ((result = mp_set_int(a, (unsigned long)abs(b))) != MP_OKAY) \
|
|
||||||
NTRU_ABORT("Error setting long constant. %s", \
|
|
||||||
mp_error_to_string(result)); \
|
|
||||||
if ((int)b < 0) \
|
|
||||||
mp_neg(a, a); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MP_MUL(...) \
|
|
||||||
{ \
|
|
||||||
int result; \
|
|
||||||
if ((result = mp_mul(__VA_ARGS__)) != MP_OKAY) \
|
|
||||||
NTRU_ABORT("Error multiplying terms. %s", \
|
|
||||||
mp_error_to_string(result)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MP_DIV(...) \
|
|
||||||
{ \
|
|
||||||
int result; \
|
|
||||||
if ((result = mp_div(__VA_ARGS__)) != MP_OKAY) \
|
|
||||||
NTRU_ABORT("Error dividing terms. %s", \
|
|
||||||
mp_error_to_string(result)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MP_ADD(...) \
|
|
||||||
{ \
|
|
||||||
int result; \
|
|
||||||
if ((result = mp_add(__VA_ARGS__)) != MP_OKAY) \
|
|
||||||
NTRU_ABORT("Error adding terms. %s", \
|
|
||||||
mp_error_to_string(result)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MP_SUB(...) \
|
|
||||||
{ \
|
|
||||||
int result; \
|
|
||||||
if ((result = mp_sub(__VA_ARGS__)) != MP_OKAY) \
|
|
||||||
NTRU_ABORT("Error substracting terms. %s", \
|
|
||||||
mp_error_to_string(result)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MP_MOD(...) \
|
|
||||||
{ \
|
|
||||||
int result; \
|
|
||||||
if ((result = mp_mod(__VA_ARGS__)) != MP_OKAY) \
|
|
||||||
NTRU_ABORT("Error reducing term by modulo. %s", \
|
|
||||||
mp_error_to_string(result)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MP_COPY(...) \
|
|
||||||
{ \
|
|
||||||
int result; \
|
|
||||||
if ((result = mp_copy(__VA_ARGS__)) != MP_OKAY) \
|
|
||||||
NTRU_ABORT("Error copying terms. %s", \
|
|
||||||
mp_error_to_string(result)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MP_XOR(...) \
|
|
||||||
{ \
|
|
||||||
int result; \
|
|
||||||
if ((result = mp_xor(__VA_ARGS__)) != MP_OKAY) \
|
|
||||||
NTRU_ABORT("Error XORing terms. %s", \
|
|
||||||
mp_error_to_string(result)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MP_EXPTMOD(...) \
|
|
||||||
{ \
|
|
||||||
int result; \
|
|
||||||
if ((result = mp_exptmod(__VA_ARGS__)) != MP_OKAY) \
|
|
||||||
NTRU_ABORT("Error computing modular exponentiation. %s", \
|
|
||||||
mp_error_to_string(result)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MP_INVMOD(...) \
|
|
||||||
{ \
|
|
||||||
int result; \
|
|
||||||
if ((result = mp_invmod(__VA_ARGS__)) != MP_OKAY) \
|
|
||||||
NTRU_ABORT("Error computing modular inverse. %s", \
|
|
||||||
mp_error_to_string(result)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MP_EXPT_D(...) \
|
|
||||||
{ \
|
|
||||||
int result; \
|
|
||||||
if ((result = mp_expt_d(__VA_ARGS__)) != MP_OKAY) \
|
|
||||||
NTRU_ABORT("Error computing modular exponentiation. %s", \
|
|
||||||
mp_error_to_string(result)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PB_MUL(...) \
|
|
||||||
{ \
|
|
||||||
int result; \
|
|
||||||
if ((result = pb_mul(__VA_ARGS__)) != MP_OKAY) \
|
|
||||||
NTRU_ABORT("Error multiplying polynomials. %s", \
|
|
||||||
mp_error_to_string(result)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PB_MP_MUL(...) \
|
|
||||||
{ \
|
|
||||||
int result; \
|
|
||||||
if ((result = pb_mp_mul(__VA_ARGS__)) != MP_OKAY) \
|
|
||||||
NTRU_ABORT("Error multiplying polynomial with mp_int. %s", \
|
|
||||||
mp_error_to_string(result)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PB_ADD(...) \
|
|
||||||
{ \
|
|
||||||
int result; \
|
|
||||||
if ((result = pb_add(__VA_ARGS__)) != MP_OKAY) \
|
|
||||||
NTRU_ABORT("Error adding polynomials. %s", \
|
|
||||||
mp_error_to_string(result)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PB_SUB(...) \
|
|
||||||
{ \
|
|
||||||
int result; \
|
|
||||||
if ((result = pb_sub(__VA_ARGS__)) != MP_OKAY) \
|
|
||||||
NTRU_ABORT("Error substracting polynomials. %s", \
|
|
||||||
mp_error_to_string(result)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PB_MOD(poly_a, mp_int, poly_out, len) \
|
|
||||||
{ \
|
|
||||||
for (unsigned int i = 0; i < len; i++) \
|
|
||||||
MP_DIV(&(poly_a->terms[i]), mp_int, NULL, &(poly_out->terms[i])); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PB_COPY(...) \
|
|
||||||
{ \
|
|
||||||
int result; \
|
|
||||||
if ((result = pb_copy(__VA_ARGS__)) != MP_OKAY) \
|
|
||||||
NTRU_ABORT("Error copying polynomial. %s", \
|
|
||||||
mp_error_to_string(result)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void init_integer(mp_int *new_int);
|
fmpz_poly_t *poly_new(int const * const c,
|
||||||
|
|
||||||
void init_integers(mp_int *new_int, ...);
|
|
||||||
|
|
||||||
void init_polynom(pb_poly *new_poly, mp_int *chara);
|
|
||||||
|
|
||||||
void init_polynom_size(pb_poly *new_poly, mp_int *chara, size_t size);
|
|
||||||
|
|
||||||
pb_poly *build_polynom(int const * const c,
|
|
||||||
const size_t len);
|
const size_t len);
|
||||||
|
|
||||||
void erase_polynom(pb_poly *poly, size_t len);
|
void poly_delete(fmpz_poly_t *poly);
|
||||||
|
|
||||||
void delete_polynom(pb_poly *new_poly);
|
void poly_delete_all(fmpz_poly_t *poly, ...);
|
||||||
|
|
||||||
void delete_polynom_multi(pb_poly *poly, ...);
|
void fmpz_poly_mod_unsigned(fmpz_poly_t a,
|
||||||
|
unsigned int mod);
|
||||||
|
|
||||||
void pb_starmultiply(pb_poly *a,
|
void fmpz_poly_mod(fmpz_poly_t a,
|
||||||
pb_poly *b,
|
unsigned int mod);
|
||||||
pb_poly *c,
|
|
||||||
|
void fmpz_poly_set_coeff_fmpz_n(fmpz_poly_t poly,
|
||||||
|
slong n,
|
||||||
|
const fmpz_t x);
|
||||||
|
|
||||||
|
int fmpz_invmod_ui(fmpz_t f,
|
||||||
|
const fmpz_t g,
|
||||||
|
unsigned int mod);
|
||||||
|
|
||||||
|
void fmpz_add_n(fmpz_t f, const fmpz_t g, const fmpz_t h);
|
||||||
|
|
||||||
|
void poly_starmultiply(fmpz_poly_t a,
|
||||||
|
fmpz_poly_t b,
|
||||||
|
fmpz_poly_t c,
|
||||||
ntru_context *ctx,
|
ntru_context *ctx,
|
||||||
unsigned int modulus);
|
unsigned int modulus);
|
||||||
|
|
||||||
int pb_mp_mul(pb_poly *a, mp_int *b, pb_poly *c);
|
bool poly_inverse_poly_q(fmpz_poly_t a,
|
||||||
|
fmpz_poly_t Fq,
|
||||||
void pb_xor(pb_poly *a,
|
|
||||||
pb_poly *b,
|
|
||||||
pb_poly *c,
|
|
||||||
const size_t len);
|
|
||||||
|
|
||||||
int get_degree(pb_poly const * const poly);
|
|
||||||
|
|
||||||
bool pb_inverse_poly_q(pb_poly *a,
|
|
||||||
pb_poly *Fq,
|
|
||||||
ntru_context *ctx);
|
ntru_context *ctx);
|
||||||
|
|
||||||
bool pb_inverse_poly_p(pb_poly *a,
|
bool poly_inverse_poly_p(fmpz_poly_t a,
|
||||||
pb_poly *Fp,
|
fmpz_poly_t Fp,
|
||||||
ntru_context *ctx);
|
ntru_context *ctx);
|
||||||
|
|
||||||
void draw_polynom(pb_poly * const poly);
|
|
||||||
|
|
||||||
void pb_normalize(pb_poly*,
|
|
||||||
int,
|
|
||||||
int,
|
|
||||||
ntru_context*);
|
|
||||||
|
|
||||||
void draw_mp_int(mp_int*);
|
|
||||||
|
|
||||||
#endif /* NTRU_POLY_H */
|
#endif /* NTRU_POLY_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user