kpqc 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/Gemfile +4 -0
  4. data/README.md +9 -6
  5. data/THIRD_PARTY_NOTICES.md +14 -47
  6. data/ext/kpqc/extconf_helper.rb +6 -3
  7. data/ext/kpqc/secure_clear.c +8 -0
  8. data/kpqc.gemspec +4 -5
  9. data/lib/kpqc/aimer.rb +6 -6
  10. data/lib/kpqc/version.rb +1 -2
  11. data/test/kat/aimer128f.rsp +4 -4
  12. data/test/kat/aimer128s.rsp +4 -4
  13. data/test/kat/aimer192f.rsp +4 -4
  14. data/test/kat/aimer192s.rsp +4 -4
  15. data/test/kat/aimer256f.rsp +4 -4
  16. data/test/kat/aimer256s.rsp +4 -4
  17. data/test/kat/haetae2.rsp +1 -1
  18. data/test/kat/haetae3.rsp +1 -1
  19. data/test/kat/haetae5.rsp +1 -1
  20. data/vendor/AIMer/LICENSE +1 -1
  21. data/vendor/AIMer/aim3.c +227 -0
  22. data/vendor/AIMer/aim3.h +63 -0
  23. data/vendor/AIMer/field.h +12 -4
  24. data/vendor/AIMer/field128.c +24 -381
  25. data/vendor/AIMer/field192.c +24 -400
  26. data/vendor/AIMer/field256.c +28 -447
  27. data/vendor/AIMer/field_common.c +98 -0
  28. data/vendor/AIMer/field_internal.h +218 -0
  29. data/vendor/AIMer/params/params-aimer-128f.h +8 -8
  30. data/vendor/AIMer/params/params-aimer-128s.h +8 -8
  31. data/vendor/AIMer/params/params-aimer-192f.h +8 -8
  32. data/vendor/AIMer/params/params-aimer-192s.h +8 -8
  33. data/vendor/AIMer/params/params-aimer-256f.h +8 -8
  34. data/vendor/AIMer/params/params-aimer-256s.h +8 -8
  35. data/vendor/AIMer/params.h +5 -0
  36. data/vendor/AIMer/sign.c +246 -167
  37. data/vendor/AIMer/sign.h +6 -6
  38. data/vendor/AIMer/tree.c +10 -4
  39. data/vendor/AIMer/tree.h +1 -1
  40. data/vendor/HAETAE/include/fixpoint.h +14 -14
  41. data/vendor/HAETAE/include/rans_byte.h +10 -9
  42. data/vendor/HAETAE/src/decompose.c +8 -4
  43. data/vendor/HAETAE/src/encoding.c +5 -5
  44. data/vendor/HAETAE/src/fft.c +1 -1
  45. data/vendor/HAETAE/src/fips202.c +26 -14
  46. data/vendor/HAETAE/src/fixpoint.c +21 -18
  47. data/vendor/HAETAE/src/ntt.c +2 -0
  48. data/vendor/HAETAE/src/packing.c +15 -15
  49. data/vendor/HAETAE/src/poly.c +30 -3
  50. data/vendor/HAETAE/src/polyfix.c +2 -2
  51. data/vendor/HAETAE/src/polymat.c +2 -2
  52. data/vendor/HAETAE/src/polyvec.c +7 -5
  53. data/vendor/HAETAE/src/reduce.c +2 -0
  54. data/vendor/HAETAE/src/sampler.c +231 -47
  55. data/vendor/HAETAE/src/sign.c +11 -10
  56. data/vendor/NTRUplus/NTRU+1152/api.h +27 -8
  57. data/vendor/NTRUplus/NTRU+1152/fips202/fips202.c +12 -269
  58. data/vendor/NTRUplus/NTRU+1152/fips202/fips202.h +4 -113
  59. data/vendor/NTRUplus/NTRU+1152/kem.c +110 -40
  60. data/vendor/NTRUplus/NTRU+1152/ntt.c +50 -54
  61. data/vendor/NTRUplus/NTRU+1152/poly.c +21 -13
  62. data/vendor/NTRUplus/NTRU+1152/poly.h +3 -3
  63. data/vendor/NTRUplus/NTRU+1152/randombytes.h +1 -0
  64. data/vendor/NTRUplus/NTRU+1152/symmetric.c +3 -9
  65. data/vendor/NTRUplus/NTRU+1152/symmetric.h +13 -3
  66. data/vendor/NTRUplus/NTRU+1152/util.h +15 -0
  67. data/vendor/NTRUplus/NTRU+768/api.h +27 -8
  68. data/vendor/NTRUplus/NTRU+768/fips202/fips202.c +12 -269
  69. data/vendor/NTRUplus/NTRU+768/fips202/fips202.h +4 -113
  70. data/vendor/NTRUplus/NTRU+768/kem.c +110 -40
  71. data/vendor/NTRUplus/NTRU+768/ntt.c +50 -54
  72. data/vendor/NTRUplus/NTRU+768/poly.c +23 -13
  73. data/vendor/NTRUplus/NTRU+768/poly.h +3 -3
  74. data/vendor/NTRUplus/NTRU+768/randombytes.h +1 -0
  75. data/vendor/NTRUplus/NTRU+768/symmetric.c +3 -9
  76. data/vendor/NTRUplus/NTRU+768/symmetric.h +13 -3
  77. data/vendor/NTRUplus/NTRU+768/util.h +15 -0
  78. data/vendor/NTRUplus/NTRU+864/api.h +27 -8
  79. data/vendor/NTRUplus/NTRU+864/fips202/fips202.c +12 -269
  80. data/vendor/NTRUplus/NTRU+864/fips202/fips202.h +4 -113
  81. data/vendor/NTRUplus/NTRU+864/kem.c +110 -40
  82. data/vendor/NTRUplus/NTRU+864/ntt.c +24 -28
  83. data/vendor/NTRUplus/NTRU+864/poly.c +26 -12
  84. data/vendor/NTRUplus/NTRU+864/poly.h +3 -3
  85. data/vendor/NTRUplus/NTRU+864/randombytes.h +1 -0
  86. data/vendor/NTRUplus/NTRU+864/symmetric.c +3 -9
  87. data/vendor/NTRUplus/NTRU+864/symmetric.h +13 -3
  88. data/vendor/NTRUplus/NTRU+864/util.h +15 -0
  89. data/vendor/SMAUG-T/src/cbd.c +4 -4
  90. data/vendor/SMAUG-T/src/ciphertext.c +2 -2
  91. data/vendor/SMAUG-T/src/dg.c +2 -2
  92. data/vendor/SMAUG-T/src/hwt.c +4 -4
  93. data/vendor/SMAUG-T/src/indcpa.c +5 -5
  94. data/vendor/SMAUG-T/src/kem.c +9 -7
  95. data/vendor/SMAUG-T/src/key.c +2 -2
  96. data/vendor/SMAUG-T/src/pack.c +8 -8
  97. metadata +17 -42
  98. data/vendor/AIMer/aim2.c +0 -163
  99. data/vendor/AIMer/aim2.h +0 -36
  100. data/vendor/AIMer/aim2_constant.h +0 -74
  101. data/vendor/SOURCES.json +0 -130
@@ -1,4 +1,4 @@
1
- /* kpqc-py: propagate OS entropy failures (2026-09-06). */
1
+ #include "util.h"
2
2
  #include <stddef.h>
3
3
  #include <stdint.h>
4
4
  #include "api.h"
@@ -8,6 +8,13 @@
8
8
  #include "fips202/fips202.h"
9
9
  #include "randombytes.h"
10
10
 
11
+ #ifdef NTRUPLUS_SUPERCOP
12
+ #include "crypto_declassify.h"
13
+ #define ntruplus_declassify crypto_declassify
14
+ #else
15
+ #define ntruplus_declassify(x, xlen) ((void)(x), (void)(xlen))
16
+ #endif
17
+
11
18
  /*************************************************
12
19
  * Name: verify
13
20
  *
@@ -38,18 +45,19 @@ static inline int verify(const uint8_t *a, const uint8_t *b, size_t len)
38
45
  * Arguments: - poly *f: output polynomial f (NTT domain)
39
46
  * - poly *finv: output multiplicative inverse of f
40
47
  * in the NTT domain
48
+ * - uint8_t *buf: workspace of NTRUPLUS_N/4 bytes
41
49
  * - const uint8_t *coins: 32-byte deterministic seed
42
50
  *
43
51
  * Returns 0 on success; non-zero if f is not invertible in the NTT domain.
44
52
  **************************************************/
45
- static inline int genf_derand(poly *f, poly *finv, const uint8_t *coins)
53
+ static inline int genf_derand(poly *f, poly *finv,
54
+ uint8_t buf[NTRUPLUS_N / 4],
55
+ const uint8_t *coins)
46
56
  {
47
- uint8_t buf[NTRUPLUS_N / 4];
48
-
49
- shake256(buf, sizeof buf, coins, 32);
57
+ shake256(buf, NTRUPLUS_N / 4, coins, 32);
50
58
 
51
59
  poly_cbd1(f, buf);
52
- poly_triple(f, f);
60
+ poly_triple(f);
53
61
  f->coeffs[0] += 1;
54
62
 
55
63
  poly_ntt(f);
@@ -66,18 +74,19 @@ static inline int genf_derand(poly *f, poly *finv, const uint8_t *coins)
66
74
  * Arguments: - poly *g: output polynomial g (NTT domain)
67
75
  * - poly *ginv: output multiplicative inverse of g
68
76
  * in the NTT domain
77
+ * - uint8_t *buf: workspace of NTRUPLUS_N/4 bytes
69
78
  * - const uint8_t *coins: 32-byte deterministic seed
70
79
  *
71
80
  * Returns 0 on success; non-zero if g is not invertible in the NTT domain.
72
81
  **************************************************/
73
- static inline int geng_derand(poly *g, poly *ginv, const uint8_t *coins)
82
+ static inline int geng_derand(poly *g, poly *ginv,
83
+ uint8_t buf[NTRUPLUS_N / 4],
84
+ const uint8_t *coins)
74
85
  {
75
- uint8_t buf[NTRUPLUS_N / 4];
76
-
77
- shake256(buf, sizeof buf, coins, 32);
86
+ shake256(buf, NTRUPLUS_N / 4, coins, 32);
78
87
 
79
88
  poly_cbd1(g, buf);
80
- poly_triple(g, g);
89
+ poly_triple(g);
81
90
 
82
91
  poly_ntt(g);
83
92
 
@@ -113,6 +122,9 @@ static inline void crypto_kem_keypair_derand(uint8_t *pk, uint8_t *sk,
113
122
  poly_tobytes(sk, f);
114
123
  poly_tobytes(sk + NTRUPLUS_POLYBYTES, &hinv);
115
124
  hash_f(sk + 2 * NTRUPLUS_POLYBYTES, pk);
125
+
126
+ secure_clear(&h, sizeof h);
127
+ secure_clear(&hinv, sizeof hinv);
116
128
  }
117
129
 
118
130
  /*************************************************
@@ -130,23 +142,39 @@ static inline void crypto_kem_keypair_derand(uint8_t *pk, uint8_t *sk,
130
142
  *
131
143
  * Returns 0 on success.
132
144
  **************************************************/
133
- int crypto_kem_keypair(uint8_t *pk, uint8_t *sk)
145
+ int crypto_kem_keypair(unsigned char *pk, unsigned char *sk)
134
146
  {
135
147
  uint8_t coins[NTRUPLUS_SYMBYTES];
148
+ uint8_t buf[NTRUPLUS_N / 4];
149
+ int r;
150
+ int status = -1;
136
151
 
137
152
  poly f, finv;
138
153
  poly g, ginv;
139
154
 
140
155
  do {
141
- if (randombytes(coins, sizeof coins) != 0) return -1;
142
- } while (genf_derand(&f, &finv, coins));
156
+ if (randombytes(coins, sizeof coins) != 0) goto cleanup;
157
+ r = genf_derand(&f, &finv, buf, coins);
158
+ ntruplus_declassify(&r, sizeof r);
159
+ } while (r);
143
160
 
144
161
  do {
145
- if (randombytes(coins, sizeof coins) != 0) return -1;
146
- } while (geng_derand(&g, &ginv, coins));
162
+ if (randombytes(coins, sizeof coins) != 0) goto cleanup;
163
+ r = geng_derand(&g, &ginv, buf, coins);
164
+ ntruplus_declassify(&r, sizeof r);
165
+ } while (r);
147
166
 
148
167
  crypto_kem_keypair_derand(pk, sk, &f, &finv, &g, &ginv);
149
- return 0;
168
+ status = 0;
169
+
170
+ cleanup:
171
+ secure_clear(coins, sizeof coins);
172
+ secure_clear(buf, sizeof buf);
173
+ secure_clear(&f, sizeof f);
174
+ secure_clear(&finv, sizeof finv);
175
+ secure_clear(&g, sizeof g);
176
+ secure_clear(&ginv, sizeof ginv);
177
+ return status;
150
178
  }
151
179
 
152
180
  /*************************************************
@@ -162,17 +190,27 @@ int crypto_kem_keypair(uint8_t *pk, uint8_t *sk)
162
190
  * - const uint8_t *coins: input randomness for
163
191
  * deterministic encapsulation
164
192
  *
165
- * Returns 0 on success.
193
+ * Returns 0 on success. If pk contains a non-canonical coefficient, ct and ss
194
+ * are set to all zero bytes and 1 is returned.
166
195
  **************************************************/
167
196
  static inline int crypto_kem_enc_derand(uint8_t *ct, uint8_t *ss,
168
197
  const uint8_t *pk,
169
198
  const uint8_t *coins)
170
199
  {
171
- uint8_t msg[NTRUPLUS_N / 8 + NTRUPLUS_SYMBYTES];
172
- uint8_t buf1[NTRUPLUS_SYMBYTES + NTRUPLUS_N / 4];
173
- uint8_t buf2[NTRUPLUS_POLYBYTES];
200
+ uint8_t msg[HASH_H_INBYTES];
201
+ uint8_t buf1[HASH_H_OUTBYTES];
202
+ uint8_t buf2[HASH_G_INBYTES];
174
203
 
175
204
  poly c, h, r, m;
205
+
206
+ if(poly_frombytes(&h, pk))
207
+ {
208
+ for (size_t i = 0; i < NTRUPLUS_CIPHERTEXTBYTES; i++)
209
+ ct[i] = 0;
210
+ secure_clear(ss, NTRUPLUS_SSBYTES);
211
+
212
+ return 1;
213
+ }
176
214
 
177
215
  for (size_t i = 0; i < NTRUPLUS_N / 8; i++)
178
216
  msg[i] = coins[i];
@@ -188,12 +226,17 @@ static inline int crypto_kem_enc_derand(uint8_t *ct, uint8_t *ss,
188
226
  poly_sotp_encode(&m, msg, buf2);
189
227
  poly_ntt(&m);
190
228
 
191
- poly_frombytes(&h, pk);
192
229
  poly_basemul_add(&c, &h, &r, &m);
193
230
  poly_tobytes(ct, &c);
194
231
 
195
232
  for (size_t i = 0; i < NTRUPLUS_SSBYTES; i++)
196
233
  ss[i] = buf1[i];
234
+
235
+ secure_clear(msg, sizeof msg);
236
+ secure_clear(buf1, sizeof buf1);
237
+ secure_clear(buf2, sizeof buf2);
238
+ secure_clear(&r, sizeof r);
239
+ secure_clear(&m, sizeof m);
197
240
 
198
241
  return 0;
199
242
  }
@@ -212,14 +255,22 @@ static inline int crypto_kem_enc_derand(uint8_t *ct, uint8_t *ss,
212
255
  * - const uint8_t *pk: input public key
213
256
  * (array of CRYPTO_PUBLICKEYBYTES bytes)
214
257
  *
215
- * Returns 0 on success.
258
+ * Returns 0 on success. If pk contains a non-canonical coefficient, ct and ss
259
+ * are set to all zero bytes and 1 is returned.
216
260
  **************************************************/
217
- int crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk)
261
+ int crypto_kem_enc(unsigned char *ct, unsigned char *ss,
262
+ const unsigned char *pk)
218
263
  {
219
264
  uint8_t coins[NTRUPLUS_N / 8];
265
+ int ret;
220
266
 
221
- if (randombytes(coins, sizeof coins) != 0) return -1;
222
- return crypto_kem_enc_derand(ct, ss, pk, coins);
267
+ if (randombytes(coins, sizeof coins) != 0) {
268
+ secure_clear(coins, sizeof coins);
269
+ return -1;
270
+ }
271
+ ret = crypto_kem_enc_derand(ct, ss, pk, coins);
272
+ secure_clear(coins, sizeof coins);
273
+ return ret;
223
274
  }
224
275
 
225
276
  /*************************************************
@@ -238,26 +289,32 @@ int crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk)
238
289
  *
239
290
  * Returns 0 on success, 1 on failure.
240
291
  **************************************************/
241
- int crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk)
292
+ int crypto_kem_dec(unsigned char *ss, const unsigned char *ct,
293
+ const unsigned char *sk)
242
294
  {
243
- uint8_t msg[NTRUPLUS_N / 8 + NTRUPLUS_SYMBYTES];
244
- uint8_t buf1[NTRUPLUS_POLYBYTES];
245
- uint8_t buf2[NTRUPLUS_POLYBYTES];
246
- uint8_t buf3[NTRUPLUS_POLYBYTES + NTRUPLUS_SYMBYTES];
247
-
248
- int8_t fail;
295
+ uint8_t msg[HASH_H_INBYTES];
296
+ uint8_t buf1[HASH_G_INBYTES];
297
+ uint8_t buf2[HASH_G_INBYTES];
298
+ uint8_t buf3[HASH_H_OUTBYTES];
299
+
300
+ int8_t fail = 1;
249
301
 
250
302
  poly c, f, hinv;
251
303
  poly r1, r2;
252
304
  poly m1, m2;
253
-
254
- poly_frombytes(&c, ct);
255
- poly_frombytes(&f, sk);
256
- poly_frombytes(&hinv, sk + NTRUPLUS_POLYBYTES);
305
+
306
+ if(poly_frombytes(&c, ct) ||
307
+ poly_frombytes(&f, sk) ||
308
+ poly_frombytes(&hinv, sk + NTRUPLUS_POLYBYTES))
309
+ {
310
+ secure_clear(ss, NTRUPLUS_SSBYTES);
311
+
312
+ goto cleanup;
313
+ }
257
314
 
258
315
  poly_basemul(&m1, &c, &f);
259
316
  poly_invntt(&m1);
260
- poly_crepmod3(&m1, &m1);
317
+ poly_crepmod3(&m1);
261
318
 
262
319
  m2 = m1;
263
320
  poly_ntt(&m2);
@@ -268,7 +325,7 @@ int crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk)
268
325
  hash_g(buf2, buf1);
269
326
  fail = poly_sotp_decode(msg, &m1, buf2);
270
327
 
271
- for (size_t i = 0; i < NTRUPLUS_SYMBYTES; i++)
328
+ for (size_t i = 0; i < HASH_F_OUTBYTES; i++)
272
329
  msg[i + NTRUPLUS_N / 8] = sk[i + 2 * NTRUPLUS_POLYBYTES];
273
330
 
274
331
  hash_h(buf3, msg);
@@ -281,6 +338,19 @@ int crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk)
281
338
 
282
339
  for (size_t i = 0; i < NTRUPLUS_SSBYTES; i++)
283
340
  ss[i] = buf3[i] & ~(-fail);
284
-
341
+
342
+ cleanup:
343
+ secure_clear(msg, sizeof msg);
344
+ secure_clear(buf1, sizeof buf1);
345
+ secure_clear(buf2, sizeof buf2);
346
+ secure_clear(buf3, sizeof buf3);
347
+ secure_clear(&c, sizeof c);
348
+ secure_clear(&f, sizeof f);
349
+ secure_clear(&hinv, sizeof hinv);
350
+ secure_clear(&r1, sizeof r1);
351
+ secure_clear(&r2, sizeof r2);
352
+ secure_clear(&m1, sizeof m1);
353
+ secure_clear(&m2, sizeof m2);
354
+
285
355
  return fail;
286
356
  }
@@ -104,8 +104,9 @@ static inline int16_t fqmul(int16_t a, int16_t b)
104
104
  /*************************************************
105
105
  * Name: fqinv
106
106
  *
107
- * Description: Computes the multiplicative inverse of a value in the
108
- * finite field Z_q.
107
+ * Description: Computes the multiplicative inverse in Z_q using Fermat's
108
+ * little theorem. The exponent q-2 = 3455 is evaluated using
109
+ * a shortest addition chain of length 15 (OEIS A003313).
109
110
  *
110
111
  * Arguments: - int16_t a: input value a mod q
111
112
  *
@@ -113,32 +114,27 @@ static inline int16_t fqmul(int16_t a, int16_t b)
113
114
  **************************************************/
114
115
  static inline int16_t fqinv(int16_t a)
115
116
  {
116
- int16_t t1, t2, t3;
117
-
118
- t1 = fqmul(a, a); // 10
119
- t2 = fqmul(t1, t1); // 100
120
- t2 = fqmul(t2, t2); // 1000
121
- t3 = fqmul(t2, t2); // 10000
122
-
123
- t1 = fqmul(t1, t2); // 1010
124
-
125
- t2 = fqmul(t1, t3); // 11010
126
- t2 = fqmul(t2, t2); // 110100
127
- t2 = fqmul(t2, a); // 110101
128
-
129
- t1 = fqmul(t1, t2); // 111111
130
-
131
- t2 = fqmul(t2, t2); // 1101010
132
- t2 = fqmul(t2, t2); // 11010100
133
- t2 = fqmul(t2, t2); // 110101000
134
- t2 = fqmul(t2, t2); // 1101010000
135
- t2 = fqmul(t2, t2); // 11010100000
136
- t2 = fqmul(t2, t2); // 110101000000
137
- t2 = fqmul(t2, t1); // 110101111111
138
-
139
- t2 = fqmul(NTRUPLUS_RINV, t2);
140
-
141
- return t2;
117
+ int16_t t0, t1;
118
+
119
+ t0 = fqmul(a, a); // 10
120
+ t0 = fqmul(t0, t0); // 100
121
+ t0 = fqmul(t0, t0); // 1000
122
+ t0 = fqmul(t0, t0); // 10000
123
+ t1 = fqmul(t0, a); // 10001
124
+
125
+ t0 = fqmul(t0, t0); // 100000
126
+ t0 = fqmul(t0, t0); // 1000000
127
+ t0 = fqmul(t0, t0); // 10000000
128
+ t1 = fqmul(t0, t1); // 10010001
129
+
130
+ t0 = fqmul(t1, t0); // 100010001
131
+ t1 = fqmul(t0, t1); // 110100010
132
+ t1 = fqmul(t1, t0); // 1010110011
133
+ t0 = fqmul(t1, t1); // 10101100110
134
+ t0 = fqmul(t0, t0); // 101011001100
135
+ t0 = fqmul(t0, t1); // 110101111111
136
+
137
+ return fqmul(NTRUPLUS_RINV, t0);
142
138
  }
143
139
 
144
140
  /*************************************************
@@ -331,19 +327,19 @@ int baseinv(int16_t r[4], const int16_t a[4], const int16_t zeta)
331
327
  **************************************************/
332
328
  void basemul(int16_t r[4], const int16_t a[4], const int16_t b[4], const int16_t zeta)
333
329
  {
334
- r[0] = montgomery_reduce(a[1]*b[3]+a[2]*b[2]+a[3]*b[1]); // R^-1
335
- r[1] = montgomery_reduce(a[2]*b[3]+a[3]*b[2]); // R^-1
336
- r[2] = montgomery_reduce(a[3]*b[3]); // R^-1
337
-
338
- r[0] = montgomery_reduce(r[0]*zeta+a[0]*b[0]); // R^-1
339
- r[1] = montgomery_reduce(r[1]*zeta+a[0]*b[1]+a[1]*b[0]); // R^-1
340
- r[2] = montgomery_reduce(r[2]*zeta+a[0]*b[2]+a[1]*b[1]+a[2]*b[0]); // R^-1
341
- r[3] = montgomery_reduce(a[0]*b[3]+a[1]*b[2]+a[2]*b[1]+a[3]*b[0]); // R^-1
342
-
343
- r[0] = montgomery_reduce(r[0]*NTRUPLUS_RSQ); // R^0
344
- r[1] = montgomery_reduce(r[1]*NTRUPLUS_RSQ); // R^0
345
- r[2] = montgomery_reduce(r[2]*NTRUPLUS_RSQ); // R^0
346
- r[3] = montgomery_reduce(r[3]*NTRUPLUS_RSQ); // R^0
330
+ int16_t t0 = montgomery_reduce(a[1]*b[3]+a[2]*b[2]+a[3]*b[1]); // R^-1
331
+ int16_t t1 = montgomery_reduce(a[2]*b[3]+a[3]*b[2]); // R^-1
332
+ int16_t t2 = montgomery_reduce(a[3]*b[3]); // R^-1
333
+
334
+ int16_t c0 = montgomery_reduce(t0*zeta+a[0]*b[0]); // R^-1
335
+ int16_t c1 = montgomery_reduce(t1*zeta+a[0]*b[1]+a[1]*b[0]); // R^-1
336
+ int16_t c2 = montgomery_reduce(t2*zeta+a[0]*b[2]+a[1]*b[1]+a[2]*b[0]); // R^-1
337
+ int16_t c3 = montgomery_reduce(a[0]*b[3]+a[1]*b[2]+a[2]*b[1]+a[3]*b[0]); // R^-1
338
+
339
+ r[0] = montgomery_reduce(c0*NTRUPLUS_RSQ); // R^0
340
+ r[1] = montgomery_reduce(c1*NTRUPLUS_RSQ); // R^0
341
+ r[2] = montgomery_reduce(c2*NTRUPLUS_RSQ); // R^0
342
+ r[3] = montgomery_reduce(c3*NTRUPLUS_RSQ); // R^0
347
343
  }
348
344
 
349
345
  /*************************************************
@@ -363,17 +359,17 @@ void basemul(int16_t r[4], const int16_t a[4], const int16_t b[4], const int16_t
363
359
  **************************************************/
364
360
  void basemul_add(int16_t r[4], const int16_t a[4], const int16_t b[4], const int16_t c[4], const int16_t zeta)
365
361
  {
366
- r[0] = montgomery_reduce(a[1]*b[3]+a[2]*b[2]+a[3]*b[1]); // R^-1
367
- r[1] = montgomery_reduce(a[2]*b[3]+a[3]*b[2]); // R^-1
368
- r[2] = montgomery_reduce(a[3]*b[3]); // R^-1
369
-
370
- r[0] = montgomery_reduce(r[0]*zeta+a[0]*b[0]); // R^-1
371
- r[1] = montgomery_reduce(r[1]*zeta+a[0]*b[1]+a[1]*b[0]); // R^-1
372
- r[2] = montgomery_reduce(r[2]*zeta+a[0]*b[2]+a[1]*b[1]+a[2]*b[0]); // R^-1
373
- r[3] = montgomery_reduce(a[0]*b[3]+a[1]*b[2]+a[2]*b[1]+a[3]*b[0]); // R^-1
374
-
375
- r[0] = montgomery_reduce(c[0]*NTRUPLUS_R + r[0]*NTRUPLUS_RSQ); // R^0
376
- r[1] = montgomery_reduce(c[1]*NTRUPLUS_R + r[1]*NTRUPLUS_RSQ); // R^0
377
- r[2] = montgomery_reduce(c[2]*NTRUPLUS_R + r[2]*NTRUPLUS_RSQ); // R^0
378
- r[3] = montgomery_reduce(c[3]*NTRUPLUS_R + r[3]*NTRUPLUS_RSQ); // R^0
362
+ int16_t t0 = montgomery_reduce(a[1]*b[3]+a[2]*b[2]+a[3]*b[1]); // R^-1
363
+ int16_t t1 = montgomery_reduce(a[2]*b[3]+a[3]*b[2]); // R^-1
364
+ int16_t t2 = montgomery_reduce(a[3]*b[3]); // R^-1
365
+
366
+ int16_t c0 = montgomery_reduce(t0*zeta+a[0]*b[0]); // R^-1
367
+ int16_t c1 = montgomery_reduce(t1*zeta+a[0]*b[1]+a[1]*b[0]); // R^-1
368
+ int16_t c2 = montgomery_reduce(t2*zeta+a[0]*b[2]+a[1]*b[1]+a[2]*b[0]); // R^-1
369
+ int16_t c3 = montgomery_reduce(a[0]*b[3]+a[1]*b[2]+a[2]*b[1]+a[3]*b[0]); // R^-1
370
+
371
+ r[0] = montgomery_reduce(c[0]*NTRUPLUS_R + c0*NTRUPLUS_RSQ); // R^0
372
+ r[1] = montgomery_reduce(c[1]*NTRUPLUS_R + c1*NTRUPLUS_RSQ); // R^0
373
+ r[2] = montgomery_reduce(c[2]*NTRUPLUS_R + c2*NTRUPLUS_RSQ); // R^0
374
+ r[3] = montgomery_reduce(c[3]*NTRUPLUS_R + c3*NTRUPLUS_RSQ); // R^0
379
375
  }
@@ -1,3 +1,4 @@
1
+ #include "util.h"
1
2
  #include <stdint.h>
2
3
  #include <string.h>
3
4
  #include "params.h"
@@ -42,7 +43,6 @@ void poly_tobytes(uint8_t r[NTRUPLUS_POLYBYTES], const poly *a)
42
43
  {
43
44
  int16_t t[2];
44
45
 
45
- #pragma GCC unroll 2
46
46
  for(size_t i = 0; i < NTRUPLUS_N/2; i++)
47
47
  {
48
48
  t[0] = a->coeffs[2*i];
@@ -65,14 +65,25 @@ void poly_tobytes(uint8_t r[NTRUPLUS_POLYBYTES], const poly *a)
65
65
  * Arguments: - poly *r: pointer to output polynomial
66
66
  * - const uint8_t *a: pointer to input byte array
67
67
  * (of NTRUPLUS_POLYBYTES bytes)
68
+ *
69
+ * Returns 0 on success, 1 if any coefficient is greater than or equal to q.
68
70
  **************************************************/
69
- void poly_frombytes(poly *r, const uint8_t a[NTRUPLUS_POLYBYTES])
71
+ int poly_frombytes(poly *r, const uint8_t a[NTRUPLUS_POLYBYTES])
70
72
  {
73
+ uint32_t fail = 0;
74
+
71
75
  for(size_t i = 0; i < NTRUPLUS_N/2; i++)
72
76
  {
73
- r->coeffs[2*i] = ((a[3*i+0] >> 0) | ((uint16_t)a[3*i+1] << 8)) & 0xFFF;
74
- r->coeffs[2*i+1] = ((a[3*i+1] >> 4) | ((uint16_t)a[3*i+2] << 4)) & 0xFFF;
77
+ const uint16_t t0 = ((a[3*i+0] >> 0) | ((uint16_t)a[3*i+1] << 8)) & 0xFFF;
78
+ const uint16_t t1 = ((a[3*i+1] >> 4) | ((uint16_t)a[3*i+2] << 4)) & 0xFFF;
79
+
80
+ r->coeffs[2*i] = t0;
81
+ r->coeffs[2*i+1] = t1;
82
+ fail |= (uint32_t)(NTRUPLUS_Q - 1) - t0;
83
+ fail |= (uint32_t)(NTRUPLUS_Q - 1) - t1;
75
84
  }
85
+
86
+ return fail >> 31;
76
87
  }
77
88
 
78
89
  /*************************************************
@@ -129,6 +140,7 @@ void poly_sotp_encode(poly *r, const uint8_t msg[NTRUPLUS_N/8], const uint8_t bu
129
140
  }
130
141
 
131
142
  poly_cbd1(r, tmp);
143
+ secure_clear(tmp, sizeof tmp);
132
144
  }
133
145
 
134
146
  /*************************************************
@@ -147,7 +159,7 @@ int poly_sotp_decode(uint8_t msg[NTRUPLUS_N/8], const poly *a, const uint8_t buf
147
159
  uint8_t t1, t2, t3;
148
160
  uint16_t t4;
149
161
  uint32_t r = 0;
150
- uint8_t mask;
162
+ volatile uint8_t mask;
151
163
 
152
164
  for(size_t i = 0; i < NTRUPLUS_N / 8; i++)
153
165
  {
@@ -296,13 +308,12 @@ void poly_sub(poly *r, const poly *a, const poly *b)
296
308
  *
297
309
  * Description: Multiply polynomial by 3; no modular reduction is performed
298
310
  *
299
- * Arguments: - poly *r: pointer to output polynomial
300
- * - const poly *a: pointer to input polynomial
311
+ * Arguments: - poly *r: pointer to input/output polynomial
301
312
  **************************************************/
302
- void poly_triple(poly *r, const poly *a)
313
+ void poly_triple(poly *r)
303
314
  {
304
315
  for(int i = 0; i < NTRUPLUS_N; ++i)
305
- r->coeffs[i] = 3*a->coeffs[i];
316
+ r->coeffs[i] *= 3;
306
317
  }
307
318
 
308
319
  /*************************************************
@@ -310,11 +321,10 @@ void poly_triple(poly *r, const poly *a)
310
321
  *
311
322
  * Description: Compute modulus 3 operation to polynomial
312
323
  *
313
- * Arguments: - poly *r: pointer to output polynomial
314
- * - const poly *a: pointer to input polynomial
324
+ * Arguments: - poly *r: pointer to input/output polynomial
315
325
  **************************************************/
316
- void poly_crepmod3(poly *r, const poly *a)
326
+ void poly_crepmod3(poly *r)
317
327
  {
318
328
  for(int i = 0; i < NTRUPLUS_N; i++)
319
- r->coeffs[i] = crepmod3(a->coeffs[i]);
329
+ r->coeffs[i] = crepmod3(r->coeffs[i]);
320
330
  }
@@ -13,7 +13,7 @@ typedef struct{
13
13
  } poly;
14
14
 
15
15
  void poly_tobytes(uint8_t r[NTRUPLUS_POLYBYTES], const poly *a);
16
- void poly_frombytes(poly *r, const uint8_t a[NTRUPLUS_POLYBYTES]);
16
+ int poly_frombytes(poly *r, const uint8_t a[NTRUPLUS_POLYBYTES]);
17
17
 
18
18
  void poly_cbd1(poly *r, const uint8_t buf[NTRUPLUS_N/4]);
19
19
  void poly_sotp_encode(poly *r, const uint8_t msg[NTRUPLUS_N/8], const uint8_t buf[NTRUPLUS_N/4]);
@@ -25,7 +25,7 @@ int poly_baseinv(poly *r, const poly *a);
25
25
  void poly_basemul(poly *r, const poly *a, const poly *b);
26
26
  void poly_basemul_add(poly *r, const poly *a, const poly *b, const poly *c);
27
27
  void poly_sub(poly *r, const poly *a, const poly *b);
28
- void poly_triple(poly *r, const poly *a);
29
- void poly_crepmod3(poly *r, const poly *a);
28
+ void poly_triple(poly *r);
29
+ void poly_crepmod3(poly *r);
30
30
 
31
31
  #endif
@@ -4,6 +4,7 @@
4
4
  #include <stddef.h>
5
5
  #include <stdint.h>
6
6
 
7
+ /* KpqC bindings propagate failures from the operating-system entropy source. */
7
8
  int randombytes(uint8_t *out, size_t outlen);
8
9
 
9
10
  #endif
@@ -1,16 +1,8 @@
1
+ #include "util.h"
1
2
  #include <string.h>
2
3
  #include "symmetric.h"
3
4
  #include "fips202/fips202.h"
4
5
 
5
- #define HASH_F_INBYTES (NTRUPLUS_POLYBYTES)
6
- #define HASH_F_OUTBYTES (32)
7
-
8
- #define HASH_G_INBYTES (NTRUPLUS_POLYBYTES)
9
- #define HASH_G_OUTBYTES (NTRUPLUS_N / 4)
10
-
11
- #define HASH_H_INBYTES (NTRUPLUS_N / 8 + NTRUPLUS_SYMBYTES)
12
- #define HASH_H_OUTBYTES (NTRUPLUS_SSBYTES + NTRUPLUS_N / 4)
13
-
14
6
  void hash_f(uint8_t *buf, const uint8_t *msg)
15
7
  {
16
8
  uint8_t data[1 + HASH_F_INBYTES];
@@ -27,6 +19,7 @@ void hash_g(uint8_t *buf, const uint8_t *msg)
27
19
  data[0] = 0x01;
28
20
  memcpy(data + 1, msg, HASH_G_INBYTES);
29
21
  shake256(buf, HASH_G_OUTBYTES, data, HASH_G_INBYTES + 1);
22
+ secure_clear(data, sizeof data);
30
23
  }
31
24
 
32
25
  void hash_h(uint8_t *buf, const uint8_t *msg)
@@ -36,4 +29,5 @@ void hash_h(uint8_t *buf, const uint8_t *msg)
36
29
  data[0] = 0x02;
37
30
  memcpy(data + 1, msg, HASH_H_INBYTES);
38
31
  shake256(buf, HASH_H_OUTBYTES, data, HASH_H_INBYTES + 1);
32
+ secure_clear(data, sizeof data);
39
33
  }
@@ -3,10 +3,20 @@
3
3
 
4
4
  #include <stddef.h>
5
5
  #include <stdint.h>
6
+ #include "api.h"
6
7
  #include "params.h"
7
8
 
8
- void hash_f(uint8_t *buf, const uint8_t *msg);
9
- void hash_g(uint8_t *buf, const uint8_t *msg);
10
- void hash_h(uint8_t *buf, const uint8_t *msg);
9
+ #define HASH_F_INBYTES (NTRUPLUS_POLYBYTES)
10
+ #define HASH_F_OUTBYTES (NTRUPLUS_SYMBYTES)
11
+
12
+ #define HASH_G_INBYTES (NTRUPLUS_POLYBYTES)
13
+ #define HASH_G_OUTBYTES (NTRUPLUS_N / 4)
14
+
15
+ #define HASH_H_INBYTES (NTRUPLUS_N / 8 + NTRUPLUS_SYMBYTES)
16
+ #define HASH_H_OUTBYTES (NTRUPLUS_SSBYTES + NTRUPLUS_N / 4)
17
+
18
+ NTRUPLUS_INTERNAL void hash_f(uint8_t *buf, const uint8_t *msg);
19
+ NTRUPLUS_INTERNAL void hash_g(uint8_t *buf, const uint8_t *msg);
20
+ NTRUPLUS_INTERNAL void hash_h(uint8_t *buf, const uint8_t *msg);
11
21
 
12
22
  #endif /* SYMMETRIC_H */
@@ -0,0 +1,15 @@
1
+ #ifndef NTRUPLUS_UTIL_H
2
+ #define NTRUPLUS_UTIL_H
3
+
4
+ #include <stddef.h>
5
+ #include <stdint.h>
6
+
7
+ static inline void secure_clear(void *v, size_t len)
8
+ {
9
+ volatile uint8_t *p = v;
10
+
11
+ while (len-- > 0)
12
+ *p++ = 0;
13
+ }
14
+
15
+ #endif /* NTRUPLUS_UTIL_H */
@@ -3,6 +3,25 @@
3
3
 
4
4
  #include "params.h"
5
5
 
6
+ #ifndef NTRUPLUS_ABI_H
7
+ #define NTRUPLUS_ABI_H
8
+
9
+ #if defined(_MSC_VER)
10
+ #define NTRUPLUS_INTERNAL
11
+ #define NTRUPLUS_EXTERNAL
12
+ #define NTRUPLUS_SYSV
13
+ #elif defined(__MINGW32__) || defined(__MINGW64__)
14
+ #define NTRUPLUS_INTERNAL
15
+ #define NTRUPLUS_EXTERNAL __declspec(dllexport)
16
+ #define NTRUPLUS_SYSV __attribute__((sysv_abi))
17
+ #else
18
+ #define NTRUPLUS_INTERNAL __attribute__((visibility("hidden")))
19
+ #define NTRUPLUS_EXTERNAL __attribute__((visibility("default")))
20
+ #define NTRUPLUS_SYSV
21
+ #endif
22
+
23
+ #endif
24
+
6
25
  #define CRYPTO_SECRETKEYBYTES NTRUPLUS_SECRETKEYBYTES
7
26
  #define CRYPTO_PUBLICKEYBYTES NTRUPLUS_PUBLICKEYBYTES
8
27
  #define CRYPTO_CIPHERTEXTBYTES NTRUPLUS_CIPHERTEXTBYTES
@@ -10,15 +29,15 @@
10
29
 
11
30
  #define CRYPTO_ALGNAME NTRUPLUS_ALGNAME
12
31
 
13
- int crypto_kem_keypair(unsigned char *pk,
14
- unsigned char *sk);
32
+ NTRUPLUS_EXTERNAL int crypto_kem_keypair(unsigned char *pk,
33
+ unsigned char *sk);
15
34
 
16
- int crypto_kem_enc(unsigned char *ct,
17
- unsigned char *ss,
18
- const unsigned char *pk);
35
+ NTRUPLUS_EXTERNAL int crypto_kem_enc(unsigned char *ct,
36
+ unsigned char *ss,
37
+ const unsigned char *pk);
19
38
 
20
- int crypto_kem_dec(unsigned char *ss,
21
- const unsigned char *ct,
22
- const unsigned char *sk);
39
+ NTRUPLUS_EXTERNAL int crypto_kem_dec(unsigned char *ss,
40
+ const unsigned char *ct,
41
+ const unsigned char *sk);
23
42
 
24
43
  #endif