Browse Source

Implement NTRU Prime key generation and param sets

Tim Buktu 1 year ago
parent
commit
da2fa9f784
17 changed files with 230 additions and 27 deletions
  1. 1 1
      Makefile.bsd
  2. 1 1
      Makefile.linux
  3. 1 1
      Makefile.os2
  4. 1 1
      Makefile.osx
  5. 1 1
      Makefile.win
  6. 8 0
      src/encparams.c
  7. 19 3
      src/encparams.h
  8. 34 1
      src/ntru.c
  9. 20 6
      src/ntru.h
  10. 41 2
      src/poly.c
  11. 29 1
      src/poly.h
  12. 26 1
      src/types.h
  13. 2 0
      tests/test.c
  14. 3 3
      tests/test_ntru.c
  15. 29 0
      tests/test_ntruprime.c
  16. 8 0
      tests/test_ntruprime.h
  17. 6 5
      tests/test_poly.c

+ 1 - 1
Makefile.bsd

@@ -54,7 +54,7 @@ ifneq ($(SIMD), none)
54 54
         LIB_OBJS+=poly_avx2.o
55 55
     endif
56 56
 endif
57
-TEST_OBJS=test_bitstring.o test_hash.o test_idxgen.o test_key.o test_ntru.o test.o test_poly.o test_util.o
57
+TEST_OBJS=test_bitstring.o test_hash.o test_idxgen.o test_key.o test_ntruprime.o test_ntru.o test.o test_poly.o test_util.o
58 58
 VERSION=0.5
59 59
 INST_PFX=/usr
60 60
 INST_LIBDIR=$(INST_PFX)/lib

+ 1 - 1
Makefile.linux

@@ -55,7 +55,7 @@ ifneq ($(SIMD), none)
55 55
         LIB_OBJS+=poly_avx2.o
56 56
     endif
57 57
 endif
58
-TEST_OBJS=test_bitstring.o test_hash.o test_idxgen.o test_key.o test_ntru.o test.o test_poly.o test_util.o
58
+TEST_OBJS=test_bitstring.o test_hash.o test_idxgen.o test_key.o test_ntruprime.o test_ntru.o test.o test_poly.o test_util.o
59 59
 VERSION=0.5
60 60
 INST_PFX=/usr
61 61
 INST_LIBDIR=$(INST_PFX)/lib

+ 1 - 1
Makefile.os2

@@ -36,7 +36,7 @@ ifneq ($(SIMD), none)
36 36
         LIB_OBJS+=poly_avx2.o
37 37
     endif
38 38
 endif
39
-TEST_OBJS=test_bitstring.o test_hash.o test_idxgen.o test_key.o test_ntru.o test.o test_poly.o test_util.o
39
+TEST_OBJS=test_bitstring.o test_hash.o test_idxgen.o test_key.o test_ntruprime.o test_ntru.o test.o test_poly.o test_util.o
40 40
 VERSION=0.5
41 41
 INST_PFX=%PROGRAMFILES%
42 42
 INST_LIBDIR=$(INST_PFX)\libntru

+ 1 - 1
Makefile.osx

@@ -33,7 +33,7 @@ ifneq ($(SIMD), none)
33 33
         LIB_OBJS+=poly_avx2.o
34 34
     endif
35 35
 endif
36
-TEST_OBJS=test_bitstring.o test_hash.o test_idxgen.o test_key.o test_ntru.o test.o test_poly.o test_util.o
36
+TEST_OBJS=test_bitstring.o test_hash.o test_idxgen.o test_key.o test_ntruprime.o test_ntru.o test.o test_poly.o test_util.o
37 37
 VERSION=0.5
38 38
 INST_PFX=/usr
39 39
 INST_LIBDIR=$(INST_PFX)/lib

+ 1 - 1
Makefile.win

@@ -36,7 +36,7 @@ ifneq ($(SIMD), none)
36 36
     endif
37 37
 endif
38 38
 
39
-TEST_OBJS=test_bitstring.o test_hash.o test_idxgen.o test_key.o test_ntru.o test.o test_poly.o test_util.o
39
+TEST_OBJS=test_bitstring.o test_hash.o test_idxgen.o test_key.o test_ntruprime.o test_ntru.o test.o test_poly.o test_util.o
40 40
 VERSION=0.5
41 41
 INST_PFX=%PROGRAMFILES%
42 42
 INST_LIBDIR=$(INST_PFX)\libntru

+ 8 - 0
src/encparams.c

@@ -1,6 +1,14 @@
1 1
 #include "encparams.h"
2 2
 #include "arith.h"
3 3
 
4
+const NtruPrimeParams NTRUPRIME_739 = {\
5
+    "NTRUPRM_739",   /* name */\
6
+    739,             /* p */\
7
+    9829,            /* q */\
8
+    204,             /* t */\
9
+    6553             /* inv_3 */
10
+};
11
+
4 12
 const NtruEncParams EES401EP1 = {\
5 13
     "EES401EP1",   /* name */\
6 14
     401,           /* N */\

+ 19 - 3
src/encparams.h

@@ -8,9 +8,25 @@
8 8
  *           NTRU Prime                *
9 9
  ***************************************/
10 10
 
11
-#define NTRUPRIME_P 739
12
-#define NTRUPRIME_Q 9829
13
-#define NTRUPRIME_T 204
11
+/* A set of parameters for NTRU Prime */
12
+typedef struct NtruPrimeParams {
13
+    /* name of the parameter set */
14
+    char name[11];
15
+
16
+    /* number of polynomial coefficients */
17
+    uint16_t p;
18
+
19
+    /* modulus */
20
+    uint16_t q;
21
+
22
+    /* number of ones + number of negative ones in f */
23
+    uint16_t t;
24
+
25
+    /* 3^(-1) mod q */
26
+    uint16_t inv_3;
27
+} NtruPrimeParams;
28
+
29
+extern const NtruPrimeParams NTRUPRIME_739;
14 30
 
15 31
 /***************************************
16 32
  *           NTRUEncrypt               *

+ 34 - 1
src/ntru.c

@@ -7,7 +7,40 @@
7 7
 #include "idxgen.h"
8 8
 #include "mgf.h"
9 9
 
10
-/** Whether to ensure g is invertible when generating a key */
10
+/***************************************
11
+ *          NTRU Prime                 *
12
+ ***************************************/
13
+
14
+uint8_t ntruprime_gen_key_pair(const NtruPrimeParams *params, NtruPrimeKeyPair *kp, NtruRandContext *rand_ctx) {
15
+    NtruIntPoly g;
16
+    NtruIntPoly *g_inv = &kp->priv.g_inv;
17
+    uint8_t invertible;
18
+    do {
19
+        if (!ntruprime_rand_tern(params->p, &g, rand_ctx))
20
+            return NTRU_ERR_PRNG;
21
+        invertible = ntruprime_inv_poly(&g, g_inv, params->q);
22
+    } while (!invertible);
23
+
24
+    NtruIntPoly *f = &kp->priv.f;
25
+    if (!ntruprime_rand_tern_t(params->p, params->t, f, rand_ctx))
26
+        return NTRU_ERR_PRNG;
27
+    NtruIntPoly f_inv;
28
+    if (!ntruprime_inv_poly(f, &f_inv, params->q))
29
+        return NTRU_ERR_INVALID_PARAM;
30
+
31
+    NtruIntPoly *h = &kp->pub.h;
32
+    if (!ntruprime_mult_poly(&g, &f_inv, h, params->q))
33
+        return NTRU_ERR_INVALID_PARAM;
34
+    ntruprime_mult_mod(h, params->inv_3, params->q);
35
+
36
+    return NTRU_SUCCESS;
37
+}
38
+
39
+/***************************************
40
+ *          NTRUEncrypt                *
41
+ ***************************************/
42
+
43
+/** whether to ensure g is invertible when generating a key */
11 44
 #define NTRU_CHECK_INVERTIBILITY_G 0
12 45
 
13 46
 const int8_t NTRU_COEFF1_TABLE[] = {0, 0, 0, 1, 1, 1, -1, -1};

+ 20 - 6
src/ntru.h

@@ -12,7 +12,21 @@ extern "C" {
12 12
 #include "err.h"
13 13
 
14 14
 /**
15
- * @brief Key generation
15
+ * @brief NTRU Prime key generation
16
+ *
17
+ * Generates a NTRU Prime key pair.
18
+ * If a deterministic RNG is used, the key pair will be deterministic for a given random seed;
19
+ * otherwise, the key pair will be completely random.
20
+ *
21
+ * @param params the NTRU Prime parameters to use
22
+ * @param kp pointer to write the key pair to (output parameter)
23
+ * @param rand_ctx an initialized random number generator. See ntru_rand_init() in rand.h.
24
+ * @return NTRU_SUCCESS for success, or a NTRU_ERR_ code for failure
25
+ */
26
+uint8_t ntruprime_gen_key_pair(const NtruPrimeParams *params, NtruPrimeKeyPair *kp, NtruRandContext *rand_ctx);
27
+
28
+/**
29
+ * @brief NtruEncrypt key generation
16 30
  *
17 31
  * Generates a NtruEncrypt key pair.
18 32
  * If a deterministic RNG is used, the key pair will be deterministic for a given random seed;
@@ -26,7 +40,7 @@ extern "C" {
26 40
 uint8_t ntru_gen_key_pair(const NtruEncParams *params, NtruEncKeyPair *kp, NtruRandContext *rand_ctx);
27 41
 
28 42
 /**
29
- * @brief Key generation with multiple public keys
43
+ * @brief NtruEncrypt key generation with multiple public keys
30 44
  *
31 45
  * Generates num_pub NtruEncrypt key pairs. They all share a private key but their public keys
32 46
  * differ. The private key decrypts messages encrypted for any of the public keys.
@@ -45,7 +59,7 @@ uint8_t ntru_gen_key_pair(const NtruEncParams *params, NtruEncKeyPair *kp, NtruR
45 59
 uint8_t ntru_gen_key_pair_multi(const NtruEncParams *params, NtruEncPrivKey *priv, NtruEncPubKey *pub, NtruRandContext *rand_ctx, uint32_t num_pub);
46 60
 
47 61
 /**
48
- * @brief New public key
62
+ * @brief New NtruEncrypt public key
49 63
  *
50 64
  * Generates a new public key for an existing private key. The new public key can be used
51 65
  * interchangeably with the existing public key(s).
@@ -67,7 +81,7 @@ uint8_t ntru_gen_key_pair_multi(const NtruEncParams *params, NtruEncPrivKey *pri
67 81
 uint8_t ntru_gen_pub(const NtruEncParams *params, NtruEncPrivKey *priv, NtruEncPubKey *pub, NtruRandContext *rand_ctx);
68 82
 
69 83
 /**
70
- * @brief Encryption
84
+ * @brief NtruEncrypt Encryption
71 85
  *
72 86
  * Encrypts a message.
73 87
  * If a deterministic RNG is used, the encrypted message will also be deterministic for a given
@@ -87,7 +101,7 @@ uint8_t ntru_gen_pub(const NtruEncParams *params, NtruEncPrivKey *priv, NtruEncP
87 101
 uint8_t ntru_encrypt(uint8_t *msg, uint16_t msg_len, NtruEncPubKey *pub, const NtruEncParams *params, NtruRandContext *rand_ctx, uint8_t *enc);
88 102
 
89 103
 /**
90
- * @brief Decryption
104
+ * @brief NtruEncrypt Decryption
91 105
  *
92 106
  * Decrypts a message.
93 107
  * See P1363.1 section 9.2.3.
@@ -104,7 +118,7 @@ uint8_t ntru_encrypt(uint8_t *msg, uint16_t msg_len, NtruEncPubKey *pub, const N
104 118
 uint8_t ntru_decrypt(uint8_t *enc, NtruEncKeyPair *kp, const NtruEncParams *params, uint8_t *dec, uint16_t *dec_len);
105 119
 
106 120
 /**
107
- * @brief Maximum message length
121
+ * @brief Maximum NtruEncrypt message length
108 122
  *
109 123
  * Returns the maximum length a plaintext message can be.
110 124
  * Depending on the parameter set, the maximum lengths for the predefined

+ 41 - 2
src/poly.c

@@ -44,6 +44,45 @@ uint8_t ntruprime_mult_poly(NtruIntPoly *a, NtruIntPoly *b, NtruIntPoly *c, uint
44 44
     return 1;
45 45
 }
46 46
 
47
+uint8_t ntruprime_rand_tern(uint16_t N, NtruIntPoly *poly, NtruRandContext *rand_ctx) {
48
+    poly->N = N;
49
+    uint16_t i;
50
+    uint32_t arr[N];
51
+    if (ntru_rand_generate((uint8_t*)arr, N*sizeof(arr[0]), rand_ctx) != NTRU_SUCCESS)
52
+        return 0;
53
+    for (i=0; i<N; i++)
54
+        /* produces almost uniform output, there is a 1 in 2^32 chance of it being biased */
55
+        poly->coeffs[i] = arr[i] % 3;
56
+    return 1;
57
+}
58
+
59
+int ntru_cmp_uint32(const void *a, const void *b) {
60
+    uint32_t a_int = *(uint32_t*)a;
61
+    uint32_t b_int = *(uint32_t*)b;
62
+    return a_int<b_int ? -1 : 1;
63
+}
64
+
65
+/* not constant time! */
66
+uint8_t ntruprime_rand_tern_t(uint16_t N, uint16_t t, NtruIntPoly *poly, NtruRandContext *rand_ctx) {
67
+    poly->N = N;
68
+
69
+    uint32_t arr[N];
70
+    if (ntru_rand_generate((uint8_t*)arr, N*sizeof(arr[0]), rand_ctx) != NTRU_SUCCESS)
71
+        return 0;
72
+
73
+    uint16_t i;
74
+    for (i=0; i<t; i++)
75
+        arr[i] &= arr[i]%2==0 ? 0xFFFFFFFC : 0xFFFFFFFE;
76
+    for (; i<N; i++)
77
+        arr[i] &= 0xFFFFFFFB;
78
+
79
+    qsort(arr, N, sizeof arr[0], &ntru_cmp_uint32);
80
+
81
+    for (i=0; i<N; i++)
82
+        poly->coeffs[i] = arr[i] % 4;
83
+    return 1;
84
+}
85
+
47 86
 /* Zeros a polynomial and sets the number of coefficients */
48 87
 void ntruprime_zero(NtruIntPoly *a, uint16_t N) {
49 88
     a->N = N;
@@ -84,7 +123,7 @@ uint16_t ntruprime_deg(NtruIntPoly *a) {
84 123
 }
85 124
 
86 125
 /* Multiplies a polynomial by an integer */
87
-void ntruprime_mult_mod_q(NtruIntPoly *a, uint16_t factor, uint16_t modulus) {
126
+void ntruprime_mult_mod(NtruIntPoly *a, uint16_t factor, uint16_t modulus) {
88 127
     uint16_t i;
89 128
     for (i=0; i<a->N; i++)
90 129
         a->coeffs[i] = (((uint64_t)a->coeffs[i]) * factor) % modulus;
@@ -184,7 +223,7 @@ uint8_t ntruprime_inv_poly(NtruIntPoly *a, NtruIntPoly *inv, uint16_t modulus) {
184 223
         }
185 224
         if (ntruprime_deg(f) == 0) {
186 225
             uint16_t f0_inv = ntruprime_inv_int(f->coeffs[0], modulus);
187
-            ntruprime_mult_mod_q(b, f0_inv, modulus);   /* b = b * f[0]^(-1) */
226
+            ntruprime_mult_mod(b, f0_inv, modulus);   /* b = b * f[0]^(-1) */
188 227
             ntruprime_reduce(b, inv, modulus);
189 228
             uint16_t i;
190 229
 

+ 29 - 1
src/poly.h

@@ -18,6 +18,34 @@
18 18
 uint8_t ntruprime_mult_poly(NtruIntPoly *a, NtruIntPoly *b, NtruIntPoly *c, uint16_t modulus);
19 19
 
20 20
 /**
21
+ * @brief Random small polynomial
22
+ *
23
+ * Generates a random ternary polynomial for NTRU Prime.
24
+ *
25
+ * @param N the number of coefficients; must be NTRU_MAX_DEGREE or less
26
+ * @param poly output parameter; a pointer to store the new polynomial
27
+ * @param rand_ctx a random number generator
28
+ * @return 1 for success, 0 for failure
29
+ */
30
+uint8_t ntruprime_rand_tern(uint16_t N, NtruIntPoly *poly, NtruRandContext *rand_ctx);
31
+
32
+/**
33
+ * @brief Random t-small polynomial
34
+ *
35
+ * Generates a random ternary polynomial for NTRU Prime with t nonzero coefficients.
36
+ *
37
+ * @param N the number of coefficients; must be NTRU_MAX_DEGREE or less
38
+ * @param t number of ones + number of negative ones
39
+ * @param poly output parameter; a pointer to store the new polynomial
40
+ * @param rand_ctx a random number generator
41
+ * @return 1 for success, 0 for failure
42
+ */
43
+uint8_t ntruprime_rand_tern_t(uint16_t N, uint16_t t, NtruIntPoly *poly, NtruRandContext *rand_ctx);
44
+
45
+/* Multiplies a polynomial by an integer, modulo another integer */
46
+void ntruprime_mult_mod(NtruIntPoly *a, uint16_t factor, uint16_t modulus);
47
+
48
+/**
21 49
  * @brief Modular inverse
22 50
  *
23 51
  * Computes the multiplicative inverse of a number using the extended Euclidean algorithm.
@@ -44,7 +72,7 @@ uint8_t ntruprime_inv_poly(NtruIntPoly *a, NtruIntPoly *b, uint16_t modulus);
44 72
 /**
45 73
  * @brief Random ternary polynomial
46 74
  *
47
- * Generates a random ternary polynomial.
75
+ * Generates a random ternary polynomial for NTRUEncrypt.
48 76
  *
49 77
  * @param N the number of coefficients; must be NTRU_MAX_DEGREE or less
50 78
  * @param num_ones number of ones

+ 26 - 1
src/types.h

@@ -33,7 +33,7 @@ typedef struct NtruProdPoly {
33 33
 } NtruProdPoly;
34 34
 #endif   /* NTRU_AVOID_HAMMING_WT_PATENT */
35 35
 
36
-/** Private polynomial, can be ternary or product-form */
36
+/** Private NtruEncrypt polynomial, can be ternary or product-form */
37 37
 typedef struct {
38 38
     uint8_t prod_flag;   /* whether the polynomial is in product form */
39 39
     union {
@@ -45,6 +45,31 @@ typedef struct {
45 45
 } NtruPrivPoly;
46 46
 
47 47
 /**
48
+ * NTRU Prime public key
49
+ */
50
+typedef struct NtruPrimePubKey {
51
+    uint16_t p;
52
+    NtruIntPoly h;
53
+} NtruPrimePubKey;
54
+
55
+/**
56
+ * NTRU Prime private key
57
+ */
58
+typedef struct NtruPrimePrivKey {
59
+    uint16_t p;
60
+    NtruIntPoly f;
61
+    NtruIntPoly g_inv;
62
+} NtruPrimePrivKey;
63
+
64
+/**
65
+ * NTRU Prime key pair
66
+ */
67
+typedef struct NtruPrimeKeyPair {
68
+    NtruPrimePrivKey priv;
69
+    NtruPrimePubKey pub;
70
+} NtruPrimeKeyPair;
71
+
72
+/**
48 73
  * NtruEncrypt private key
49 74
  */
50 75
 typedef struct NtruEncPrivKey {

+ 2 - 0
tests/test.c

@@ -1,6 +1,7 @@
1 1
 #include <stdio.h>
2 2
 #include <stdint.h>
3 3
 #include "test_poly.h"
4
+#include "test_ntruprime.h"
4 5
 #include "test_ntru.h"
5 6
 #include "test_idxgen.h"
6 7
 #include "test_bitstring.h"
@@ -13,6 +14,7 @@ int main(int argc, char** argv) {
13 14
     printf("Running tests...\n");
14 15
     ntru_set_optimized_impl();   /* normally called by the functions in ntru.h */
15 16
     uint8_t pass = test_poly();
17
+    pass &= test_ntruprime();
16 18
     pass &= test_ntru();
17 19
     pass &= test_idxgen();
18 20
     pass &= test_bitstring();

+ 3 - 3
tests/test_ntru.c

@@ -42,7 +42,7 @@ uint8_t gen_key_pair(char *seed, NtruEncParams *params, NtruEncKeyPair *kp) {
42 42
     return result;
43 43
 }
44 44
 
45
-uint8_t test_keygen() {
45
+uint8_t test_ntru_keygen() {
46 46
     NtruEncParams param_arr[] = ALL_PARAM_SETS;
47 47
     uint8_t valid = 1;
48 48
 
@@ -87,7 +87,7 @@ uint8_t test_keygen() {
87 87
         valid &= equals_key_pair(&kp, &kp2);
88 88
     }
89 89
 
90
-    print_result("test_keygen", valid);
90
+    print_result("test_ntru_keygen", valid);
91 91
     return valid;
92 92
 }
93 93
 
@@ -281,7 +281,7 @@ uint8_t test_encr_decr() {
281 281
 }
282 282
 
283 283
 uint8_t test_ntru() {
284
-    uint8_t valid = test_keygen();
284
+    uint8_t valid = test_ntru_keygen();
285 285
     valid &= test_encr_decr();
286 286
     return valid;
287 287
 }

+ 29 - 0
tests/test_ntruprime.c

@@ -0,0 +1,29 @@
1
+#include <string.h>
2
+#include "test_ntruprime.h"
3
+#include "poly.h"
4
+#include "test_util.h"
5
+
6
+uint8_t test_ntruprime_keygen() {
7
+    NtruRandGen rng = NTRU_RNG_DEFAULT;
8
+    NtruRandContext rand_ctx;
9
+    uint8_t valid = ntru_rand_init(&rand_ctx, &rng) == NTRU_SUCCESS;
10
+    NtruPrimeKeyPair kp;
11
+    NtruPrimeParams params = NTRUPRIME_739;
12
+    valid &= ntruprime_gen_key_pair(&params, &kp, &rand_ctx) == NTRU_SUCCESS;
13
+
14
+    /* verify that h*f*3*g_inv==1 (mod q) */
15
+    NtruIntPoly a;
16
+    valid &= ntruprime_mult_poly(&kp.pub.h, &kp.priv.f, &a, params.q);
17
+    ntruprime_mult_mod(&a, 3, params.q);
18
+    NtruIntPoly b;
19
+    valid &= ntruprime_mult_poly(&a, &kp.priv.g_inv, &b, params.q);
20
+    valid &= equals_one(&b);
21
+
22
+    print_result("test_ntruprime_keygen", valid);
23
+    return valid;
24
+}
25
+
26
+uint8_t test_ntruprime() {
27
+    uint8_t valid = test_ntruprime_keygen();
28
+    return valid;
29
+}

+ 8 - 0
tests/test_ntruprime.h

@@ -0,0 +1,8 @@
1
+#ifndef TEST_NTRUPRIME_H
2
+#define TEST_NTRUPRIME_H
3
+
4
+#include <stdint.h>
5
+
6
+uint8_t test_ntruprime();
7
+
8
+#endif

+ 6 - 5
tests/test_poly.c

@@ -11,10 +11,11 @@
11 11
 uint8_t test_ntruprime_inv_int() {
12 12
     uint16_t i;
13 13
     uint8_t valid = 1;
14
+    uint16_t q = NTRUPRIME_739.q;
14 15
     for (i=0; i<10; i++) {
15
-        uint16_t a = random() % NTRUPRIME_Q;
16
-        uint16_t inv = ntruprime_inv_int(a, NTRUPRIME_Q);
17
-        valid &= (a*inv) % NTRUPRIME_Q == 1;
16
+        uint16_t a = random() % q;
17
+        uint16_t inv = ntruprime_inv_int(a, q);
18
+        valid &= (a*inv) % q == 1;
18 19
     }
19 20
     print_result("test_ntruprime_inv_int", valid);
20 21
     return valid;
@@ -25,7 +26,7 @@ uint8_t test_ntruprime_inv_poly_modulus(uint16_t modulus) {
25 26
     uint8_t valid = 1;
26 27
     for (i=0; i<10; i++) {
27 28
         NtruIntPoly a, c;
28
-        rand_poly(&a, NTRUPRIME_P, modulus);
29
+        rand_poly(&a, NTRUPRIME_739.p, modulus);
29 30
         while (!ntruprime_inv_poly(&a, &c, modulus));
30 31
         NtruIntPoly prod;
31 32
         ntruprime_mult_poly(&a, &c, &prod, modulus);
@@ -37,7 +38,7 @@ uint8_t test_ntruprime_inv_poly_modulus(uint16_t modulus) {
37 38
 /** tests ntruprime_inv_poly() */
38 39
 uint8_t test_ntruprime_inv_poly() {
39 40
     uint8_t valid = test_ntruprime_inv_poly_modulus(3);
40
-    valid &= test_ntruprime_inv_poly_modulus(NTRUPRIME_Q);
41
+    valid &= test_ntruprime_inv_poly_modulus(NTRUPRIME_739.q);
41 42
     print_result("test_ntruprime_inv_poly", valid);
42 43
     return valid;
43 44
 }